基于ST MCU( STM32L431RCTx) SPI模块外接SPI FALSH的案例

举报
aiot_bigbear 发表于 2022/09/25 00:26:49 2022/09/25
3.6k+ 0 0
【摘要】 文章目录 1.相关开发环境2.SPI1 外接SPI FLASH3.SPI FLASH初始化3.1 SPI FLASH支持SPI MODE0/3的通讯控制3.2 SPI 硬件CRC 不需要D...


1.相关开发环境

硬件版本:STM32L431RCTx

开发软件:KEIL

2.SPI1 外接SPI FLASH

MCU SPI1 外接SPI FLASH

#define CS_PORT GPIOB
#define CS_PIN GPIO_PIN_11

#define FLASH_CS_ENABLE() HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_RESET)
#define FLASH_CS_DISABLE() HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_SET)

  
 

3.SPI FLASH初始化

根据 FLASH 芯片的说明,它支持 SPI模式 0及模式 3,支持双线全双工,使用 MSB先行模式,支持最高通讯时钟为 104MHz,数据帧长度为 8 位。我们要把 STM32 的 SPI 外设中的这些参数配置一致。

SPI 1初始化 Init的具体定义如下:

static void st_SPI1_Init(void)
{

	/* SPI1 parameter configuration*/
	hspi1.Instance = SPI1;
	hspi1.Init.Mode = SPI_MODE_MASTER;
	hspi1.Init.Direction = SPI_DIRECTION_2LINES;
	hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
//	hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
//	hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
	
		hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
	hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
	
	hspi1.Init.NSS = SPI_NSS_SOFT;
	hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
	hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
	hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
	hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
	hspi1.Init.CRCPolynomial = 7;
	hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
	hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
	if (HAL_SPI_Init(&hspi1) != HAL_OK)
	{
		Error_Handler();
	}

}
  
 

3.1 SPI FLASH支持SPI MODE0/3的通讯控制

//	hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
//	hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;

hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;

  
 

3.2 SPI 硬件CRC 不需要DISABLE即可

hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

3.3 SPI CS 软件GPIO控制即可

hspi1.Init.NSS = SPI_NSS_SOFT;

4.SPI FLASH 的读 写 等操作验证代码

4.1 SPI FLASH ID读取

uint32_t stmcu_W25Q64_ReadDeviceID(void)
{
    uint8_t command = FLASH_READ_DEVICE_ID;
    uint32_t usFlashId = 0;
    uint8_t temp_buff[3] = {0};

    FLASH_CS_ENABLE();
    HAL_SPI_Transmit(&hspi1, &command, 1, 1);  // 90h
    HAL_SPI_Transmit(&hspi1, temp_buff, 3, 3); //写入24位地址;假地址
    HAL_SPI_Receive(&hspi1, temp_buff, 2, 2);
    FLASH_CS_DISABLE();

		//usFlashId = (uint32_t)temp_buff[2]|(temp_buff[1] << 8) | (temp_buff[0] << 16);
    usFlashId = (uint16_t)(temp_buff[1]) | (temp_buff[0] << 8);
    return usFlashId;
}
uint32_t stmcu_W25Q64_ReadDeviceID_JEDEC(void)
{
    uint8_t command = FLASH_READ_JEDEC_ID;
    uint32_t usFlashId = 0;
    uint8_t temp_buff[3] = {0};

    FLASH_CS_ENABLE();
    HAL_SPI_Transmit(&hspi1, &command, 1, 1);  // 9Fh
  //  HAL_SPI_Transmit(&hspi1, temp_buff, 3, 3); //写入24位地址;假地址
    HAL_SPI_Receive(&hspi1, temp_buff, 3, 3);
    FLASH_CS_DISABLE();

    usFlashId = (uint32_t)temp_buff[2]|(temp_buff[1] << 8) | (temp_buff[0] << 16);
    return usFlashId;
}

  
 

4.2 SPI FLASH 读写

void stmcu_W25Q64_WriteEnable(void)
{
    uint8_t command = FLASH_WRITE_ENABLE_CMD;

    FLASH_CS_ENABLE();
    HAL_SPI_Transmit(&hspi1, &command, 1, 1);
    FLASH_CS_DISABLE();
}
void stmcu_W25Q64_WriteDisable(void)
{
    uint8_t command = FLASH_WRITE_DISABLE_CMD;

    FLASH_CS_ENABLE();
    HAL_SPI_Transmit(&hspi1, &command, 1, 1);
    FLASH_CS_DISABLE();
}

uint8_t stmcu_W25Q64_ReadSR(void)
{
    uint8_t ucTmpVal = 0;
    uint8_t command = FLASH_READ_SR_CMD;

    FLASH_CS_ENABLE();
    HAL_SPI_Transmit(&hspi1, &command, 1, 1);
    HAL_SPI_Receive(&hspi1, &ucTmpVal, 1, 1);
    FLASH_CS_DISABLE();

    return ucTmpVal;
}
void stmcu_W25Q64_WriteSR(uint8_t _ucByte)
{
    uint8_t CMD[2] = {FLASH_WRITE_SR_CMD, 0};

    CMD[1] = _ucByte;

    stmcu_W25Q64_WriteEnable();
    stmcu_W25Q64_WaitNobusy();

    FLASH_CS_ENABLE();
    HAL_SPI_Transmit(&hspi1, CMD, 2, 2);
    FLASH_CS_DISABLE();

    stmcu_W25Q64_WaitNobusy();
}

void stmcu_W25Q64_WaitNobusy(void)
{
    while (((stmcu_W25Q64_ReadSR()) & 0x01) == 0x01) //等待BUSY位清空
    {
        osDelay(1);
    }
}
  
 
void stmcu_W25Q64_ReadData(uint32_t Addr, uint8_t *Buffer, uint16_t NByte)
{
    uint8_t temp_buff[4] = {0};

    if (Buffer == NULL)
    {
        return;
    }

    temp_buff[0] = FLASH_READ_DATA;
    temp_buff[1] = (uint8_t)(Addr >> 16);
    temp_buff[2] = (uint8_t)(Addr >> 8);
    temp_buff[3] = (uint8_t)(Addr >> 0);

    FLASH_CS_ENABLE();
    HAL_SPI_Transmit(&hspi1, temp_buff, 4, 4);
    HAL_SPI_Receive(&hspi1, Buffer, NByte, NByte);
    FLASH_CS_DISABLE();
}
  
 
void stmcu_W25Q64_WriteData(uint32_t Addr, uint8_t *Buffer, uint16_t NByte)
{
    uint8_t temp_buff[4] = {0};

    if (Buffer == NULL)
    {
        return;
    }

    temp_buff[0] = FLASH_WRITE_PAGE;
    temp_buff[1] = (uint8_t)(Addr >> 16);
    temp_buff[2] = (uint8_t)(Addr >> 8);
    temp_buff[3] = (uint8_t)(Addr >> 0);

    stmcu_W25Q64_WriteEnable();
    stmcu_W25Q64_WaitNobusy();

    FLASH_CS_ENABLE();
    HAL_SPI_Transmit(&hspi1, temp_buff, 4, 4);
    HAL_SPI_Transmit(&hspi1, Buffer, NByte, NByte);
    FLASH_CS_DISABLE();

    stmcu_W25Q64_WaitNobusy();
}

  
 

5.参考

本文引用《STM32库开发实战指南》

obusy();

FLASH_CS_ENABLE();
HAL_SPI_Transmit(&hspi1, temp_buff, 4, 4);
HAL_SPI_Transmit(&hspi1, Buffer, NByte, NByte);
FLASH_CS_DISABLE();

stmcu_W25Q64_WaitNobusy();

  
 

}


## 5.参考

本文引用《STM32库开发实战指南》
## 

  
 

文章来源: blog.csdn.net,作者:悟空胆好小,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/xushx_bigbear/article/details/125137942

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。