2.4 查看 SPI 传输状态
在 SPI 传输过程中,要判断数据是否传输完成,发送区是否为空等等状态,
通过函数 SPI_I2S_GetFlagStatus 实现的,判断发送是否完成的方法是:
SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE);
1
3. SPI FLASH 操作
3.1 宏定义部分
#define FLASH_WRITE_ENABLE_CMD 0x06
#define FLASH_WRITE_DISABLE_CMD 0x04
#define FLASH_READ_SR_CMD 0x05
#define FLASH_WRITE_SR_CMD 0x01
#define FLASH_READ_DATA 0x03
#define FLASH_FASTREAD_DATA 0x0b
#define FLASH_WRITE_PAGE 0x02
#define FLASH_ERASE_PAGE 0x81
#define FLASH_ERASE_SECTOR 0x20
#define FLASH_ERASE_BLOCK 0xd8
#define FLASH_ERASE_CHIP 0xc7
#define FLASH_POWER_DOWN 0xb9
#define FLASH_RELEASE_POWER_DOWN 0xab
#define FLASH_READ_DEVICE_ID 0x90
#define FLASH_READ_JEDEC_ID 0x9f
#define FLASH_SIZE (1*1024*1024) // 1M字节
#define PAGE_SIZE 8192 // 256 bytes
#define SECTOR_SIZE 512 // 4-Kbyte
#define BLOCK_SIZE 32 // 64-Kbyte
#define PAGE_LEN 255 //一页256字节
3.2 中间层函数封装
注明: 此部分函数的封装是为了统一硬件 SPI 和软件模拟 SPI 接口。
//--------------------------------------------------------------------------------------------------------
// 函 数 名: hal_spi_send_bytes
// 功能说明: SPI 发送数据,包含软件和硬件通信方式
// 形 参: mode:通信方式选择(0:软件SPI;1:硬件SPI)
// pbdata:发送数据的首地址
// send_length:发送数据长度
// 返 回 值: 执行状态(true or false)
// 日 期: 2020-03-12
// 备 注: 中间层封装底层接口
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
uint8_t hal_spi_send_bytes(uint8_t mode, uint8_t *pbdata, uint16_t send_length)
{
if (mode == 0)
{
for (uint16_t i = 0; i < send_length; i++)
{
Spi_WriteByte(pbdata);
}
return true;
}
else if (mode == 1)
{
spi_master_send_some_bytes(1, pbdata, send_length);
// for (uint16_t i = 0; i < send_length; i++)
// {
// spi_master_send_recv_byte(1, pbdata);
// }
return true;
}
else
{
return false;
}
}
//--------------------------------------------------------------------------------------------------------
// 函 数 名: hal_spi_recv_bytes
// 功能说明: SPI 接收数据,包含软件和硬件通信方式
// 形 参: mode:通信方式选择(0:软件SPI;1:硬件SPI)
// pbdata:发送数据的首地址
// send_length:发送数据长度
// 返 回 值: 执行状态(true or false)
// 日 期: 2020-03-12
// 备 注: 中间层封装底层接口
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
uint8_t hal_spi_recv_bytes(uint8_t mode, uint8_t *pbdata, uint16_t recv_length)
{
if (mode == 0)
{
for (uint16_t i = 0; i < recv_length; i++)
{
*pbdata++ = Spi_ReadByte(); //软件模拟SPI
}
return true;
}
else if (mode == 1)
{
spi_master_recv_some_bytes(1, pbdata, recv_length); //硬件SPI
// for (uint16_t i = 0; i < recv_length; i++)
// {
// *pbdata++ = spi_master_send_recv_byte(1, 0xFF);
// }
return true;
}
else
{
return false;
}
}
关于软件模拟 SPI 部分代码,参看:软件模拟SPI代码 。此处不再贴出。
3.3 FLASH 部分
__align(4) uint8_t g_DataTmpBuffer[0x1000] = {0};
#define SectorBuf g_DataTmpBuffer
//--------------------------------------------------------------------------------------------------------
// 函 数 名: Flash_WriteEnable
// 功能说明: 写使能,置位 WEL 位 WEL 位(WEL-->1)
// 形 参: 无
// 返 回 值: 无
// 日 期: 2020-03-07
// 备 注:
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
void Flash_WriteEnable(void)
{
uint8_t command = FLASH_WRITE_ENABLE_CMD;
FLASH_CS_LOW;
hal_spi_send_bytes(SPI_COMM_MODE, &command, 1);//开启写使能
FLASH_CS_HIGH;
}
//--------------------------------------------------------------------------------------------------------
// 函 数 名: Flash_WriteDisable
// 功能说明: 写失能,复位 WEL 位(WEL-->0)
// 形 参: 无
// 返 回 值: 无
// 日 期: 2020-03-07
// 备 注:
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
void Flash_WriteDisable(void)
{
uint8_t command = FLASH_WRITE_DISABLE_CMD;
FLASH_CS_LOW;
hal_spi_send_bytes(SPI_COMM_MODE, &command, 1);
// Spi_WriteByte(FLASH_WRITE_DISABLE_CMD); //开启写失能 04h
FLASH_CS_HIGH;
}
//--------------------------------------------------------------------------------------------------------
// 函 数 名: Flash_WriteSR
// 功能说明: 读状态寄存器
// 形 参: 无
// 返 回 值: 无
// 日 期: 2020-03-07
// 备 注: 多用于检查 BUSY 位
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
uint8_t Flash_ReadSR(void)
{
uint8_t ucTmpVal = 0;
uint8_t command = FLASH_READ_SR_CMD;
FLASH_CS_LOW;
hal_spi_send_bytes(SPI_COMM_MODE, &command, 1); //05h
hal_spi_recv_bytes(SPI_COMM_MODE, &ucTmpVal, 1);
// ucTmpVal = Spi_ReadByte();
FLASH_CS_HIGH;
return ucTmpVal;
}
//--------------------------------------------------------------------------------------------------------
// 函 数 名: Flash_WriteSR
// 功能说明: 写状态寄存器
// 形 参: _ucByte:写入状态寄存器的数值
// 返 回 值: no
// 日 期: 2020-03-07
// 备 注:
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
void Flash_WriteSR(uint8_t _ucByte)
{
uint8_t command = FLASH_WRITE_SR_CMD;
Flash_WriteEnable();
Flash_WaitNobusy();
FLASH_CS_LOW;
hal_spi_send_bytes(SPI_COMM_MODE, &command, 1); //01h
hal_spi_send_bytes(SPI_COMM_MODE, &_ucByte, 1); //写入一个字节
FLASH_CS_HIGH;
}
//--------------------------------------------------------------------------------------------------------
// 函 数 名: Flash_WaitNobusy
// 功能说明: 检查 FLASH BUSY 位状态
// 形 参: no
// 返 回 值: no
// 日 期: 2020-03-07
// 备 注: 调用Flash_ReadSR(),判断状态寄存器的R0位,执行结束操作清零
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
void Flash_WaitNobusy(void)
{
//FLASH_READ_SR_CMD 指令的发送,有的FLASH仅需发送一次,FLASH自动回复,有的FLASH无法自动回复,需要循环一直发送等待
while(((Flash_ReadSR()) & 0x01)==0x01); //等待BUSY位清空
}
//--------------------------------------------------------------------------------------------------------
// 函 数 名: Flash_FastReadByte
// 功能说明: flash 都数据(快速读取:Fast read operate at the highest poossible frequency)
// 形 参: ucpBuffer:数据存储区首地址
// _ulReadAddr: 要读出Flash的首地址
// _usNByte: 要读出的字节数(最大65535B)
// 返 回 值: no
// 日 期: 2020-03-07
// 备 注: 从_ulReadAddr地址,连续读出_usNByte长度的字节
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
void Flash_ReadSomeBytes(uint8_t *ucpBuffer, uint32_t _ulReadAddr, uint16_t _usNByte)
{
uint8_t command = FLASH_READ_DATA;
uint8_t temp_buff[3] = {0};
temp_buff[0] = (uint8_t)(_ulReadAddr >> 16);
temp_buff[1] = (uint8_t)(_ulReadAddr >> 8);
temp_buff[2] = (uint8_t)(_ulReadAddr >> 0);
FLASH_CS_LOW;
hal_spi_send_bytes(SPI_COMM_MODE, &command, 1);
hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[0], 1);
hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[1], 1);
hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[2], 1);
hal_spi_recv_bytes(SPI_COMM_MODE, ucpBuffer, _usNByte);
// Spi_WriteByte(FLASH_READ_DATA); //连续读取数据 03h
// Spi_WriteByte((uint8_t)(_ulReadAddr>>16)); //写入24位地址
// Spi_WriteByte((uint8_t)(_ulReadAddr>>8));
// Spi_WriteByte((uint8_t)(_ulReadAddr>>0));
// while(_usNByte--)
// {
// *ucpBuffer = Spi_ReadByte();
// ucpBuffer++;
// }
FLASH_CS_HIGH;
}
//--------------------------------------------------------------------------------------------------------
// 函 数 名: Flash_FastReadByte
// 功能说明: flash 都数据(快速读取:Fast read operate at the highest poossible frequency)
// 形 参: ucpBuffer:数据存储区首地址
// _ulReadAddr: 要读出Flash的首地址
// _usNByte: 要读出的字节数(最大65535B)
// 返 回 值: no
// 日 期: 2020-03-07
// 备 注: 从_ulReadAddr地址,连续读出_usNByte长度的字节
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
void Flash_FastReadByte(uint8_t *ucpBuffer, uint32_t _ulReadAddr, uint16_t _usNByte)
{
uint8_t command = FLASH_FASTREAD_DATA;
uint8_t temp_buff[3] = {0};
temp_buff[0] = (uint8_t)(_ulReadAddr >> 16);
temp_buff[1] = (uint8_t)(_ulReadAddr >> 8);
temp_buff[2] = (uint8_t)(_ulReadAddr >> 0);
FLASH_CS_LOW;
hal_spi_send_bytes(SPI_COMM_MODE, &command, 1);
hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[0], 1);
hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[1], 1);
hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[2], 1);
hal_spi_recv_bytes(SPI_COMM_MODE, ucpBuffer, _usNByte);
// Spi_WriteByte(FLASH_FASTREAD_DATA);//快速读取数据 0bh
// Spi_WriteByte((uint8_t)(_ulReadAddr>>16));//写入24位地址
// Spi_WriteByte((uint8_t)(_ulReadAddr>>8));
// Spi_WriteByte((uint8_t)(_ulReadAddr>>0));
// Spi_WriteByte(0xFF);//等待8个时钟(dummy byte)
// while(_usNByte--)
// {
// *ucpBuffer = Spi_ReadByte();
// ucpBuffer++;
// }
FLASH_CS_HIGH;
}
2.4 查看 SPI 传输状态
在 SPI 传输过程中,要判断数据是否传输完成,发送区是否为空等等状态,
通过函数 SPI_I2S_GetFlagStatus 实现的,判断发送是否完成的方法是:
SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE);
1
3. SPI FLASH 操作
3.1 宏定义部分
#define FLASH_WRITE_ENABLE_CMD 0x06
#define FLASH_WRITE_DISABLE_CMD 0x04
#define FLASH_READ_SR_CMD 0x05
#define FLASH_WRITE_SR_CMD 0x01
#define FLASH_READ_DATA 0x03
#define FLASH_FASTREAD_DATA 0x0b
#define FLASH_WRITE_PAGE 0x02
#define FLASH_ERASE_PAGE 0x81
#define FLASH_ERASE_SECTOR 0x20
#define FLASH_ERASE_BLOCK 0xd8
#define FLASH_ERASE_CHIP 0xc7
#define FLASH_POWER_DOWN 0xb9
#define FLASH_RELEASE_POWER_DOWN 0xab
#define FLASH_READ_DEVICE_ID 0x90
#define FLASH_READ_JEDEC_ID 0x9f
#define FLASH_SIZE (1*1024*1024) // 1M字节
#define PAGE_SIZE 8192 // 256 bytes
#define SECTOR_SIZE 512 // 4-Kbyte
#define BLOCK_SIZE 32 // 64-Kbyte
#define PAGE_LEN 255 //一页256字节
3.2 中间层函数封装
注明: 此部分函数的封装是为了统一硬件 SPI 和软件模拟 SPI 接口。
//--------------------------------------------------------------------------------------------------------
// 函 数 名: hal_spi_send_bytes
// 功能说明: SPI 发送数据,包含软件和硬件通信方式
// 形 参: mode:通信方式选择(0:软件SPI;1:硬件SPI)
// pbdata:发送数据的首地址
// send_length:发送数据长度
// 返 回 值: 执行状态(true or false)
// 日 期: 2020-03-12
// 备 注: 中间层封装底层接口
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
uint8_t hal_spi_send_bytes(uint8_t mode, uint8_t *pbdata, uint16_t send_length)
{
if (mode == 0)
{
for (uint16_t i = 0; i < send_length; i++)
{
Spi_WriteByte(pbdata);
}
return true;
}
else if (mode == 1)
{
spi_master_send_some_bytes(1, pbdata, send_length);
// for (uint16_t i = 0; i < send_length; i++)
// {
// spi_master_send_recv_byte(1, pbdata);
// }
return true;
}
else
{
return false;
}
}
//--------------------------------------------------------------------------------------------------------
// 函 数 名: hal_spi_recv_bytes
// 功能说明: SPI 接收数据,包含软件和硬件通信方式
// 形 参: mode:通信方式选择(0:软件SPI;1:硬件SPI)
// pbdata:发送数据的首地址
// send_length:发送数据长度
// 返 回 值: 执行状态(true or false)
// 日 期: 2020-03-12
// 备 注: 中间层封装底层接口
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
uint8_t hal_spi_recv_bytes(uint8_t mode, uint8_t *pbdata, uint16_t recv_length)
{
if (mode == 0)
{
for (uint16_t i = 0; i < recv_length; i++)
{
*pbdata++ = Spi_ReadByte(); //软件模拟SPI
}
return true;
}
else if (mode == 1)
{
spi_master_recv_some_bytes(1, pbdata, recv_length); //硬件SPI
// for (uint16_t i = 0; i < recv_length; i++)
// {
// *pbdata++ = spi_master_send_recv_byte(1, 0xFF);
// }
return true;
}
else
{
return false;
}
}
关于软件模拟 SPI 部分代码,参看:软件模拟SPI代码 。此处不再贴出。
3.3 FLASH 部分
__align(4) uint8_t g_DataTmpBuffer[0x1000] = {0};
#define SectorBuf g_DataTmpBuffer
//--------------------------------------------------------------------------------------------------------
// 函 数 名: Flash_WriteEnable
// 功能说明: 写使能,置位 WEL 位 WEL 位(WEL-->1)
// 形 参: 无
// 返 回 值: 无
// 日 期: 2020-03-07
// 备 注:
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
void Flash_WriteEnable(void)
{
uint8_t command = FLASH_WRITE_ENABLE_CMD;
FLASH_CS_LOW;
hal_spi_send_bytes(SPI_COMM_MODE, &command, 1);//开启写使能
FLASH_CS_HIGH;
}
//--------------------------------------------------------------------------------------------------------
// 函 数 名: Flash_WriteDisable
// 功能说明: 写失能,复位 WEL 位(WEL-->0)
// 形 参: 无
// 返 回 值: 无
// 日 期: 2020-03-07
// 备 注:
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
void Flash_WriteDisable(void)
{
uint8_t command = FLASH_WRITE_DISABLE_CMD;
FLASH_CS_LOW;
hal_spi_send_bytes(SPI_COMM_MODE, &command, 1);
// Spi_WriteByte(FLASH_WRITE_DISABLE_CMD); //开启写失能 04h
FLASH_CS_HIGH;
}
//--------------------------------------------------------------------------------------------------------
// 函 数 名: Flash_WriteSR
// 功能说明: 读状态寄存器
// 形 参: 无
// 返 回 值: 无
// 日 期: 2020-03-07
// 备 注: 多用于检查 BUSY 位
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
uint8_t Flash_ReadSR(void)
{
uint8_t ucTmpVal = 0;
uint8_t command = FLASH_READ_SR_CMD;
FLASH_CS_LOW;
hal_spi_send_bytes(SPI_COMM_MODE, &command, 1); //05h
hal_spi_recv_bytes(SPI_COMM_MODE, &ucTmpVal, 1);
// ucTmpVal = Spi_ReadByte();
FLASH_CS_HIGH;
return ucTmpVal;
}
//--------------------------------------------------------------------------------------------------------
// 函 数 名: Flash_WriteSR
// 功能说明: 写状态寄存器
// 形 参: _ucByte:写入状态寄存器的数值
// 返 回 值: no
// 日 期: 2020-03-07
// 备 注:
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
void Flash_WriteSR(uint8_t _ucByte)
{
uint8_t command = FLASH_WRITE_SR_CMD;
Flash_WriteEnable();
Flash_WaitNobusy();
FLASH_CS_LOW;
hal_spi_send_bytes(SPI_COMM_MODE, &command, 1); //01h
hal_spi_send_bytes(SPI_COMM_MODE, &_ucByte, 1); //写入一个字节
FLASH_CS_HIGH;
}
//--------------------------------------------------------------------------------------------------------
// 函 数 名: Flash_WaitNobusy
// 功能说明: 检查 FLASH BUSY 位状态
// 形 参: no
// 返 回 值: no
// 日 期: 2020-03-07
// 备 注: 调用Flash_ReadSR(),判断状态寄存器的R0位,执行结束操作清零
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
void Flash_WaitNobusy(void)
{
//FLASH_READ_SR_CMD 指令的发送,有的FLASH仅需发送一次,FLASH自动回复,有的FLASH无法自动回复,需要循环一直发送等待
while(((Flash_ReadSR()) & 0x01)==0x01); //等待BUSY位清空
}
//--------------------------------------------------------------------------------------------------------
// 函 数 名: Flash_FastReadByte
// 功能说明: flash 都数据(快速读取:Fast read operate at the highest poossible frequency)
// 形 参: ucpBuffer:数据存储区首地址
// _ulReadAddr: 要读出Flash的首地址
// _usNByte: 要读出的字节数(最大65535B)
// 返 回 值: no
// 日 期: 2020-03-07
// 备 注: 从_ulReadAddr地址,连续读出_usNByte长度的字节
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
void Flash_ReadSomeBytes(uint8_t *ucpBuffer, uint32_t _ulReadAddr, uint16_t _usNByte)
{
uint8_t command = FLASH_READ_DATA;
uint8_t temp_buff[3] = {0};
temp_buff[0] = (uint8_t)(_ulReadAddr >> 16);
temp_buff[1] = (uint8_t)(_ulReadAddr >> 8);
temp_buff[2] = (uint8_t)(_ulReadAddr >> 0);
FLASH_CS_LOW;
hal_spi_send_bytes(SPI_COMM_MODE, &command, 1);
hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[0], 1);
hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[1], 1);
hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[2], 1);
hal_spi_recv_bytes(SPI_COMM_MODE, ucpBuffer, _usNByte);
// Spi_WriteByte(FLASH_READ_DATA); //连续读取数据 03h
// Spi_WriteByte((uint8_t)(_ulReadAddr>>16)); //写入24位地址
// Spi_WriteByte((uint8_t)(_ulReadAddr>>8));
// Spi_WriteByte((uint8_t)(_ulReadAddr>>0));
// while(_usNByte--)
// {
// *ucpBuffer = Spi_ReadByte();
// ucpBuffer++;
// }
FLASH_CS_HIGH;
}
//--------------------------------------------------------------------------------------------------------
// 函 数 名: Flash_FastReadByte
// 功能说明: flash 都数据(快速读取:Fast read operate at the highest poossible frequency)
// 形 参: ucpBuffer:数据存储区首地址
// _ulReadAddr: 要读出Flash的首地址
// _usNByte: 要读出的字节数(最大65535B)
// 返 回 值: no
// 日 期: 2020-03-07
// 备 注: 从_ulReadAddr地址,连续读出_usNByte长度的字节
// 作 者: by 霁风AI
//--------------------------------------------------------------------------------------------------------
void Flash_FastReadByte(uint8_t *ucpBuffer, uint32_t _ulReadAddr, uint16_t _usNByte)
{
uint8_t command = FLASH_FASTREAD_DATA;
uint8_t temp_buff[3] = {0};
temp_buff[0] = (uint8_t)(_ulReadAddr >> 16);
temp_buff[1] = (uint8_t)(_ulReadAddr >> 8);
temp_buff[2] = (uint8_t)(_ulReadAddr >> 0);
FLASH_CS_LOW;
hal_spi_send_bytes(SPI_COMM_MODE, &command, 1);
hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[0], 1);
hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[1], 1);
hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[2], 1);
hal_spi_recv_bytes(SPI_COMM_MODE, ucpBuffer, _usNByte);
// Spi_WriteByte(FLASH_FASTREAD_DATA);//快速读取数据 0bh
// Spi_WriteByte((uint8_t)(_ulReadAddr>>16));//写入24位地址
// Spi_WriteByte((uint8_t)(_ulReadAddr>>8));
// Spi_WriteByte((uint8_t)(_ulReadAddr>>0));
// Spi_WriteByte(0xFF);//等待8个时钟(dummy byte)
// while(_usNByte--)
// {
// *ucpBuffer = Spi_ReadByte();
// ucpBuffer++;
// }
FLASH_CS_HIGH;
}
举报