简介
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
|
|