1015|1

241

帖子

0

TA的资源

纯净的硅(初级)

楼主
 

【国民技术车规MCU N32A455开发板】04、通过SPI FLASH熟悉SPI通讯(SPI1 & SPI2) [复制链接]

本帖最后由 xld0932 于 2024-3-14 15:26 编辑

1.概述

国民技术N32A455系列MCU搭载了3路SPI接口,同时还具备I2S功能;SPI允许芯片与外部设备以半/全双工、同步、串行方式通信。此接口可以被配置成主模式,并为外部从设备提供通信时钟(SCK)。接口还能以多主配置方式工作。它可用于多种用途,包括使用一条双向数据线的双线单工同步传输,还可使用CRC校验的可靠通信。

 

2.N32A455开发板SPI FLASH原理图

开发板板载一路SPI FLASH(W25Q128JVSIQTR),占用了SPI1外设资源,通过设置跳线J29、 J30、 J31、 J32与MCU的PA4、PA5、PA6、PA7相连接,所以在做SPI FLASH实验时,需要注意跳线的连接状态

 

3.SPI示例程序

我们参考官方的SPI FLASH示例工程,通过SPI1接口对SPI FLASH进行读、写、擦除等操作,通过修改代码将每个过程的数据打印出来,更加的直观:

  • int main(void)
  • {
  • /*!< At this stage the microcontroller clock setting is already configured,
  • this is done through SystemInit() function which is called from startup
  • file (startup_n32a455.s) before to branch to application main.
  • To reconfigure the default setting of SystemInit() function, refer to
  • system_n32a455.c file
  • */
  • log_init();
  • LedInit(GPIOE, LED1 | LED2);
  • LedOff(GPIOE, LED1 | LED2);
  • /* Initialize the SPI FLASH driver */
  • sFLASH_Init();
  • /* Get SPI Flash ID */
  • FlashID = sFLASH_ReadID();
  • printf("\r\nRead ID=0x%06x",FlashID);
  • /* Check the SPI Flash ID */
  • if ((FlashID == sFLASH_ID)||(FlashID == sFLASH_W25Q128_ID_DTR))
  • {
  • /* OK: Turn on LED1 */
  • LedOn(GPIOE, LED1);
  • /* Perform a write in the Flash followed by a read of the written data */
  • /* Erase SPI FLASH Sector to write on */
  • sFLASH_EraseSector(FLASH_SectorToErase);
  • /* Read data from SPI FLASH memory */
  • sFLASH_ReadBuffer(Rx_Buffer, FLASH_ReadAddress, BufferSize);
  • printf("\r\nRead after Erase...");
  • for (uint32_t i = 0; i < BufferSize; i++)
  • {
  • if ((i % 16) == 0)
  • {
  • printf("\r\n");
  • }
  • printf("0x%02X ", Rx_Buffer[i]);
  • }
  • printf("\r\n");
  • /* Write Tx_Buffer data to SPI FLASH memory */
  • sFLASH_WriteBuffer(Tx_Buffer, FLASH_WriteAddress, BufferSize);
  • /* Read data from SPI FLASH memory */
  • sFLASH_ReadBuffer(Rx_Buffer, FLASH_ReadAddress, BufferSize);
  • printf("\r\nRead after Write...");
  • for (uint32_t i = 0; i < BufferSize; i++)
  • {
  • if ((i % 16) == 0)
  • {
  • printf("\r\n");
  • }
  • printf("0x%02X ", Rx_Buffer[i]);
  • }
  • printf("\r\n");
  • printf("\r\n%s", Rx_Buffer);
  • printf("\r\n");
  • /* Check the correctness of written dada */
  • TransferStatus1 = Buffercmp(Tx_Buffer, Rx_Buffer, BufferSize);
  • if(PASSED == TransferStatus1)
  • printf("\r\nFlash write OK.");
  • else
  • printf("\r\nFlash write fail.");
  • /* TransferStatus1 = PASSED, if the transmitted and received data by SPI1
  • are the same */
  • /* TransferStatus1 = FAILED, if the transmitted and received data by SPI1
  • are different */
  • /* Perform an erase in the Flash followed by a read of the written data */
  • /* Erase SPI FLASH Sector to write on */
  • sFLASH_EraseSector(FLASH_SectorToErase);
  • /* Read data from SPI FLASH memory */
  • sFLASH_ReadBuffer(Rx_Buffer, FLASH_ReadAddress, BufferSize);
  • printf("\r\nRead after Erase...");
  • for (uint32_t i = 0; i < BufferSize; i++)
  • {
  • if ((i % 16) == 0)
  • {
  • printf("\r\n");
  • }
  • printf("0x%02X ", Rx_Buffer[i]);
  • }
  • printf("\r\n");
  • /* Check the correctness of erasing operation dada */
  • for (Index = 0; Index < BufferSize; Index++)
  • {
  • if (Rx_Buffer[Index] != 0xFF)
  • {
  • TransferStatus2 = FAILED;
  • break;
  • }
  • }
  • if(PASSED == TransferStatus2)
  • printf("\r\nSector erase OK.");
  • else
  • printf("\r\nSector erase fail.");
  • /* TransferStatus2 = PASSED, if the specified sector part is erased */
  • /* TransferStatus2 = FAILED, if the specified sector part is not well erased */
  • }
  • else
  • {
  • /* Error: Turn on LED2 */
  • LedOn(GPIOE, LED2);
  • printf("\r\nRead ID fail.");
  • }
  • while (1)
  • {
  • }
  • }

 

4.运行结果

4.1.硬件环境

 

4.2.运行结果

 

5.使用SPI2操作SPI FLASH的注意事项

N32A455开发板上的PE10\PE11\PE12\PE13这几个接口作为SPI2通讯接口,正好也没有被其它板载资源所占用,所以就使用这4个引脚来验证一下SPI2操作SPI FLASH的功能,首先需要对程序进行配置

5.1.在spi_flash.h文件中对操作SPI FLASH的接口和外设进行定义:

  • #if 0
  • #define sFLASH_SPI SPI1
  • #define sFLASH_SPI_CLK RCC_APB2_PERIPH_SPI1
  • #define sFLASH_SPI_SCK_PIN GPIO_PIN_5 /* PA.05 */
  • #define sFLASH_SPI_SCK_GPIO_PORT GPIOA /* GPIOA */
  • #define sFLASH_SPI_SCK_GPIO_CLK RCC_APB2_PERIPH_GPIOA
  • #define sFLASH_SPI_MISO_PIN GPIO_PIN_6 /* PA.06 */
  • #define sFLASH_SPI_MISO_GPIO_PORT GPIOA /* GPIOA */
  • #define sFLASH_SPI_MISO_GPIO_CLK RCC_APB2_PERIPH_GPIOA
  • #define sFLASH_SPI_MOSI_PIN GPIO_PIN_7 /* PA.07 */
  • #define sFLASH_SPI_MOSI_GPIO_PORT GPIOA /* GPIOA */
  • #define sFLASH_SPI_MOSI_GPIO_CLK RCC_APB2_PERIPH_GPIOA
  • #define sFLASH_CS_PIN GPIO_PIN_4 /* PA.04 */
  • #define sFLASH_CS_GPIO_PORT GPIOA /* GPIOA */
  • #define sFLASH_CS_GPIO_CLK RCC_APB2_PERIPH_GPIOA
  • #else
  • #define sFLASH_SPI SPI2
  • #define sFLASH_SPI_CLK RCC_APB1_PERIPH_SPI2
  • #define sFLASH_SPI_SCK_PIN GPIO_PIN_11/* PE.11 */
  • #define sFLASH_SPI_SCK_GPIO_PORT GPIOE /* GPIOE */
  • #define sFLASH_SPI_SCK_GPIO_CLK RCC_APB2_PERIPH_GPIOE
  • #define sFLASH_SPI_MISO_PIN GPIO_PIN_12/* PA.12 */
  • #define sFLASH_SPI_MISO_GPIO_PORT GPIOE /* GPIOE */
  • #define sFLASH_SPI_MISO_GPIO_CLK RCC_APB2_PERIPH_GPIOE
  • #define sFLASH_SPI_MOSI_PIN GPIO_PIN_13/* PA.13 */
  • #define sFLASH_SPI_MOSI_GPIO_PORT GPIOE /* GPIOE */
  • #define sFLASH_SPI_MOSI_GPIO_CLK RCC_APB2_PERIPH_GPIOE
  • #define sFLASH_CS_PIN GPIO_PIN_10/* PE.10 */
  • #define sFLASH_CS_GPIO_PORT GPIOE /* GPIOE */
  • #define sFLASH_CS_GPIO_CLK RCC_APB2_PERIPH_GPIOE
  • #endif

 

5.2.因为SPI1与SPI2这两个外设接口不在同一个总线上,所以需要对官方例程中出现外设时钟配置的地方进行修改,修改spi_flash.c文件中的函数,如下所示:

  • void sFLASH_LowLevel_DeInit(void)
  • {
  • GPIO_InitType GPIO_InitStructure;
  • /*!< Disable the sFLASH_SPI */
  • SPI_Enable(sFLASH_SPI, DISABLE);
  • /*!< DeInitializes the sFLASH_SPI */
  • SPI_I2S_DeInit(sFLASH_SPI);
  • /*!< sFLASH_SPI Periph clock disable */
  • if (sFLASH_SPI_CLK == RCC_APB2_PERIPH_SPI1)
  • {
  • RCC_EnableAPB2PeriphClk(sFLASH_SPI_CLK, DISABLE);
  • }
  • else
  • {
  • RCC_EnableAPB1PeriphClk(sFLASH_SPI_CLK, DISABLE);
  • }
  • /*!< Configure sFLASH_SPI pins: SCK */
  • GPIO_InitStructure.Pin = sFLASH_SPI_SCK_PIN;
  • GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  • GPIO_InitPeripheral(sFLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
  • /*!< Configure sFLASH_SPI pins: MISO */
  • GPIO_InitStructure.Pin = sFLASH_SPI_MISO_PIN;
  • GPIO_InitPeripheral(sFLASH_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
  • /*!< Configure sFLASH_SPI pins: MOSI */
  • GPIO_InitStructure.Pin = sFLASH_SPI_MOSI_PIN;
  • GPIO_InitPeripheral(sFLASH_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
  • /*!< Configure sFLASH_CS_PIN pin: sFLASH Card CS pin */
  • GPIO_InitStructure.Pin = sFLASH_CS_PIN;
  • GPIO_InitPeripheral(sFLASH_CS_GPIO_PORT, &GPIO_InitStructure);
  • }
  • void sFLASH_LowLevel_Init(void)
  • {
  • GPIO_InitType GPIO_InitStructure;
  • /*!< sFLASH_SPI_CS_GPIO, sFLASH_SPI_MOSI_GPIO, sFLASH_SPI_MISO_GPIO
  • and sFLASH_SPI_SCK_GPIO Periph clock enable */
  • RCC_EnableAPB2PeriphClk(
  • sFLASH_CS_GPIO_CLK | sFLASH_SPI_MOSI_GPIO_CLK | sFLASH_SPI_MISO_GPIO_CLK | sFLASH_SPI_SCK_GPIO_CLK, ENABLE);
  • /*!< sFLASH_SPI Periph clock enable */
  • if (sFLASH_SPI_CLK == RCC_APB2_PERIPH_SPI1)
  • {
  • RCC_EnableAPB2PeriphClk(sFLASH_SPI_CLK, ENABLE);
  • }
  • else
  • {
  • RCC_EnableAPB1PeriphClk(sFLASH_SPI_CLK, ENABLE);
  • GPIO_ConfigPinRemap(GPIO_RMP2_SPI2, ENABLE);
  • }
  • /*!< Configure sFLASH_SPI pins: SCK */
  • GPIO_InitStructure.Pin = sFLASH_SPI_SCK_PIN;
  • GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  • GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  • GPIO_InitPeripheral(sFLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
  • /*!< Configure sFLASH_SPI pins: MOSI */
  • GPIO_InitStructure.Pin = sFLASH_SPI_MOSI_PIN;
  • GPIO_InitPeripheral(sFLASH_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
  • /*!< Configure sFLASH_SPI pins: MISO */
  • GPIO_InitStructure.Pin = sFLASH_SPI_MISO_PIN;
  • GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  • GPIO_InitPeripheral(sFLASH_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
  • /*!< Configure sFLASH_CS_PIN pin: sFLASH Card CS pin */
  • GPIO_InitStructure.Pin = sFLASH_CS_PIN;
  • GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  • GPIO_InitPeripheral(sFLASH_CS_GPIO_PORT, &GPIO_InitStructure);
  • }

 

5.3.注意事项:查看SPI2使用的引脚,需要看一下复用功能,需不需要重映射配置;上例中使用了PE10~PE13,是需要进行重映射配置,要不然就无法通讯了!

 

5.4.SPI2测试环境

 

5.5.SPI2测试结果

 

6.工程源代码

SPI_FLASH.zip (1.46 MB, 下载次数: 4)
查看本帖全部内容,请登录或者注册
此帖出自汽车电子论坛

最新回复

看来官方的SPI FLASH示例工程跑起来是没有问题的哈   详情 回复 发表于 2024-3-17 18:25
点赞 关注
个人签名We are a team and we work as a team !

回复
举报

7032

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

看来官方的SPI FLASH示例工程跑起来是没有问题的哈

此帖出自汽车电子论坛
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条
有奖直播:当AI遇见仿真,会有什么样的电子行业革新之路?
首场直播:Simcenter AI 赋能电子行业研发创新
直播时间:04月15日14:00-14:50

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网 4

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表