打印
[应用相关]

GD25Q128读写接口在stm32

[复制链接]
982|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-1-19 19:16 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
简介

spi配置
void MX_SPI2_Init(void)
{
  /* USER CODE BEGIN SPI2_Init 0 */
  /* USER CODE END SPI2_Init 0 */
  /* USER CODE BEGIN SPI2_Init 1 */
  /* USER CODE END SPI2_Init 1 */
  hspi2.Instance = SPI2;
  hspi2.Init.Mode = SPI_MODE_MASTER;
  hspi2.Init.Direction = SPI_DIRECTION_2LINES;
  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi2.Init.NSS = SPI_NSS_SOFT;
  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi2.Init.CRCPolynomial = 7;
  hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
  if (HAL_SPI_Init(&hspi2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI2_Init 2 */
  /* USER CODE END SPI2_Init 2 */
}



读写代码接口示例
#include "spi.h"
#include "string.h"
#include "spi_flash.h"



#define SPI2_FLASH_NSS_PORT       GPIOA
#define SPI2_FLASH_NSS_PIN        GPIO_PIN_8

#define CMD_PAGE_PROGRAM           0x02
#define CMD_READ_DATA_BYTES        0x03
#define CMD_READ_STA_REG           0x05
#define CMD_WRITE_ENABLE           0x06
#define CMD_SECTOR_ERASE           0x20
#define GET_DEVICE_ID              0x90
#define GET_IDENTIFICATION         0x9f

#define DUMMY_BYTE          0xff

#define  SFLASH_ID             0xC84018  //Flash ID

#define SPI_FLASH_NSS_ENABLE      HAL_GPIO_WritePin(SPI2_FLASH_NSS_PORT, SPI2_FLASH_NSS_PIN, GPIO_PIN_RESET)
#define SPI_FLASH_NSS_DISENABLE  HAL_GPIO_WritePin(SPI2_FLASH_NSS_PORT, SPI2_FLASH_NSS_PIN, GPIO_PIN_SET)


#define SPI_FLASH_PAGE_SIZE    0x100 //GD25Qxx每页有256个字节
#define WIP_FLAG         0x01     /* write in progress(wip)flag */

#define DEVICE_SIZE  0x400000  // 4M
#define BLOCK_SIZE  0x10000  // 64K
#define SECTOR_SIZE  0x1000   // 4K
#define PAGE_SIZE    0x100   // 256

static uint8_t gs_sectorBuf[SECTOR_SIZE] = {0};
union GD32_UINT32_DATA_TYPE
{
uint8_t b[4];
    uint32_t Uint32_Data;
};
uint8_t spi_SendRcvByte(uint8_t TxData)
{
    uint8_t Rxdata;
    HAL_SPI_TransmitReceive(&hspi2, &TxData, &Rxdata, 1, 100);
    return Rxdata;
}
/*
* @brief 读取DEVICE_ID
* @return 返回ID号
*/
uint16_t get_DeviceId(void)
{
uint16_t dev_id = 0;

SPI_FLASH_NSS_ENABLE;

spi_SendRcvByte(GET_DEVICE_ID);
spi_SendRcvByte(DUMMY_BYTE);
spi_SendRcvByte(DUMMY_BYTE);
spi_SendRcvByte(DUMMY_BYTE);


dev_id = spi_SendRcvByte(DUMMY_BYTE) << 8;
  dev_id |= spi_SendRcvByte(DUMMY_BYTE);

SPI_FLASH_NSS_DISENABLE;
     
return dev_id;
}

/*
* @brief 读取Identifica
* @param data_out 输出ID号
*/
void get_Identifica(uint8_t *data_out)
{
SPI_FLASH_NSS_ENABLE;

spi_SendRcvByte(GET_IDENTIFICATION);
data_out [0] = spi_SendRcvByte(DUMMY_BYTE);
data_out [1] = spi_SendRcvByte(DUMMY_BYTE);
data_out [2] = spi_SendRcvByte(DUMMY_BYTE);

SPI_FLASH_NSS_DISENABLE;
}

/*
* @brief 读取数据
* @param dest_addr 目标地址
* @param data 将要写入数据
* @param len 将要写入数据长度
*/
void get_ReadDataBytes(uint32_t dest_addr, uint8_t *data, uint32_t len)
{
SPI_FLASH_NSS_ENABLE;

spi_SendRcvByte(CMD_READ_DATA_BYTES);
spi_SendRcvByte((uint8_t)(dest_addr >> 16));
spi_SendRcvByte((uint8_t)(dest_addr >> 8));
spi_SendRcvByte((uint8_t)(dest_addr));

while(len--)
{
  *data = spi_SendRcvByte(DUMMY_BYTE);
  data++;
}

SPI_FLASH_NSS_DISENABLE;
}

//函数功能:发送"写使能命令"
void spi_flash_write_enable(void)
{
SPI_FLASH_NSS_ENABLE;
spi_SendRcvByte(CMD_WRITE_ENABLE); //发送"写使能命令"
SPI_FLASH_NSS_DISENABLE;
}
//函数功能:等待空闲
void spi_flash_wait_for_write_end(void)
{
uint8_t flash_status = 0;

SPI_FLASH_NSS_ENABLE;
spi_SendRcvByte(CMD_READ_STA_REG);//发送"读状态寄存器命令"

do
{
  flash_status = spi_SendRcvByte(DUMMY_BYTE);
  //发送DUMMY_BYTE数据为的是读取状态寄存器的值
}while( (flash_status & WIP_FLAG) == SET );
//WIP位置1,表示芯片正处于编程/擦除/写状态

SPI_FLASH_NSS_DISENABLE;
}

//函数功能:擦除扇区,其首地址为sector_addr
void spi_flash_sector_erase(uint32_t sector_addr)
{
union GD32_UINT32_DATA_TYPE addr;

addr.Uint32_Data=sector_addr;

spi_flash_write_enable();//发送"写使能命令"

SPI_FLASH_NSS_ENABLE;
spi_SendRcvByte(CMD_SECTOR_ERASE); //发送扇区擦除命令
spi_SendRcvByte( addr.b[2] );     //发送扇区地址的bit16~bit23
spi_SendRcvByte( addr.b[1] );     //发送扇区地址的bit8~bit15
spi_SendRcvByte( addr.b[0] );     //发送扇区地址的bit0~bit7
SPI_FLASH_NSS_DISENABLE;

spi_flash_wait_for_write_end();//等待空闲
}

//函数功能:将pbuffer[]中的num_byte_to_write个字节型数据写入首地址为write_addr的Flash空间
static void spi_flash_page_write(uint8_t* pbuffer, uint32_t write_addr, uint16_t num_byte_to_write)
{
union GD32_UINT32_DATA_TYPE addr;

addr.Uint32_Data=write_addr;

spi_flash_write_enable();//发送"写使能命令"

SPI_FLASH_NSS_ENABLE;

spi_SendRcvByte(CMD_PAGE_PROGRAM);//发送"页编程命令"
spi_SendRcvByte( addr.b[2] );   //发送页地址的bit16~bit23
spi_SendRcvByte( addr.b[1] );   //发送页地址的bit8~bit15
spi_SendRcvByte( addr.b[0] );   //发送页地址的bit0~bit7
while(num_byte_to_write--)
{
  spi_SendRcvByte(*pbuffer);
  pbuffer++;
}

SPI_FLASH_NSS_DISENABLE;

spi_flash_wait_for_write_end();//等待空闲
}
/*
* @brief 写数据
* @param write_addr 目标地址
* @param pbuffer 将要写入数据
* @param len 将要写入数据长度
*/
void spi_flash_buffer_write(uint8_t* pbuffer, uint32_t write_addr, uint16_t len)
{
uint8_t num_of_page = 0, num_of_single = 0, addr = 0, count = 0, temp = 0;

addr          = write_addr % SPI_FLASH_PAGE_SIZE;
count         = SPI_FLASH_PAGE_SIZE - addr; //计算当前页剩余多少个字节空间
num_of_page   = len / SPI_FLASH_PAGE_SIZE;//计算需要写多少页
num_of_single = len % SPI_FLASH_PAGE_SIZE;//计算不满一页的字节数量

if(0 == addr)//位于页边界
{
  if(0 == num_of_page)//所写字节数量不满一页,num_byte_to_write < SPI_FLASH_PAGE_SIZE
   spi_flash_page_write(pbuffer,write_addr, len);
  else//所写字节数量超过一页,num_byte_to_write > SPI_FLASH_PAGE_SIZE
  {
   while(num_of_page--)
   {
    spi_flash_page_write(pbuffer,write_addr,SPI_FLASH_PAGE_SIZE);
    write_addr += SPI_FLASH_PAGE_SIZE;
    pbuffer += SPI_FLASH_PAGE_SIZE;
   }
   spi_flash_page_write(pbuffer,write_addr,num_of_single);
  }
}
else
{
  if(0 == num_of_page)//所写字节数量不满一页
  {
   if(num_of_single > count)//超过当前页
   {
    temp = num_of_single - count;//计算跨页的字节数量
    spi_flash_page_write(pbuffer,write_addr,count);
    write_addr += count;//修改Flash地址
    pbuffer += count;   //修改指针
    spi_flash_page_write(pbuffer,write_addr,temp);
   }
   else//没有超过当前页
   spi_flash_page_write(pbuffer,write_addr,len);
  }
  else//所写字节数量超过一页
  {
   len -= count;//计算写当前页后的剩余字节总数
   num_of_page = len / SPI_FLASH_PAGE_SIZE;  //剩余字节总数需要多少页
   num_of_single = len % SPI_FLASH_PAGE_SIZE;//剩余字节总数写完整页后的剩余字节数量

   spi_flash_page_write(pbuffer,write_addr, count);//向当前页写入count字节,凑成1整页
   write_addr += count;//修改Flash地址
   pbuffer += count;   //修改指针

   while(num_of_page--)
   {
    spi_flash_page_write(pbuffer,write_addr,SPI_FLASH_PAGE_SIZE);
    write_addr += SPI_FLASH_PAGE_SIZE;//修改Flash地址
    pbuffer += SPI_FLASH_PAGE_SIZE;   //修改指针
   }

   if(0 != num_of_single)//最后写剩余的字节
    spi_flash_page_write(pbuffer,write_addr,num_of_single);
  }
}
}
————————————————
版权声明:本文为CSDN博主「路过的小熊~」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_32348883/article/details/127416013

使用特权

评论回复
沙发
玛尼玛尼哄| | 2024-1-23 20:45 | 只看该作者
GD25Q128是一款SPI Flash存储器,通常与STM32微控制器一起使用。以下是使用STM32的HAL库实现GD25Q128读写的基本步骤。

1. 连接硬件:
确保GD25Q128正确连接到STM32的SPI总线,并注意配置正确的引脚。GD25Q128有四个引脚:CS(片选)、MISO(主入从出)、MOSI(主出从入)和CLK(时钟)。配置这些引脚,并确保SPI总线已启用。

使用特权

评论回复
板凳
玛尼玛尼哄| | 2024-1-23 20:46 | 只看该作者
2. 初始化SPI:
使用STM32的HAL库初始化SPI。以下是一个简单的例子:
#include "stm32f4xx_hal.h"

SPI_HandleTypeDef hspi1;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_SPI1_Init();

    while (1) {
        // 主程序逻辑
    }
}

3. 编写GD25Q128读写函数:
使用SPI进行读写GD25Q128。以下是一个简单的例子:
#include "stm32f4xx_hal.h"

#define CS_LOW()    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET)
#define CS_HIGH()   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET)

void GD25Q128_WriteEnable(void) {
    CS_LOW();
    // 发送写使能命令
    // ...
    CS_HIGH();
}

void GD25Q128_WriteByte(uint8_t data, uint32_t address) {
    GD25Q128_WriteEnable();
    CS_LOW();
    // 发送写命令和地址
    // 发送数据
    // ...
    CS_HIGH();
}

uint8_t GD25Q128_ReadByte(uint32_t address) {
    CS_LOW();
    // 发送读命令和地址
    // 读取数据
    // ...
    CS_HIGH();
    return data;
}

使用特权

评论回复
地板
玛尼玛尼哄| | 2024-1-23 20:46 | 只看该作者
4. 调用读写函数:
在主程序中调用GD25Q128读写函数。例如:
int main(void) {
    // ...

    GD25Q128_WriteByte(0x55, 0x1000);  // 在地址0x1000处写入数据0x55
    uint8_t data = GD25Q128_ReadByte(0x1000);  // 从地址0x1000处读取数据

    while (1) {
        // 主程序逻辑
    }
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1923

主题

15596

帖子

11

粉丝