[MM32硬件] 【灵动微电子MM32F0121测评】6.硬件SPI读写FLASH

[复制链接]
4454|1
 楼主| 阿源玩电子 发表于 2025-6-30 20:00 | 显示全部楼层 |阅读模式
硬件SPI读写FLASH

  • 原理图部分

原理图

原理图

SPI Flash 芯片(U6)
型号: W25Q80DVSNIG,这是一种串行外设接口(SPI)闪存芯片,常用于存储数据。
引脚功能:
  • VCC (引脚 8): 电源输入,连接到 3.3V 电源。
  • GND (引脚 4): 地线,连接到地(GND)。
  • CS (引脚 1): 片选信号,用于选择该 SPI 设备。
  • CLK (引脚 6): 时钟信号,由主设备(微控制器)提供,用于同步数据传输。
  • DI/IQ0 (引脚 5): 数据输入(Master Out Slave In, MOSI),主设备向从设备发送数据。
  • DO/IQ1 (引脚 2): 数据输出(Master In Slave Out, MISO),从设备向主设备发送数据。
  • WP/IQ2 (引脚 3): 写保护信号,用于防止意外写入或擦除操作。
  • HOLD/IQ3 (引脚 7): 持续信号,用于暂停当前操作。
2.dsp_spi.c
  1. #include "dsp_spi.h"


  2. #define SPI_FLASH_CS_H() SPI_CSInternalSelected(SPI1, DISABLE)
  3. #define SPI_FLASH_CS_L() SPI_CSInternalSelected(SPI1, ENABLE)


  4. volatile SPI_RxTx_TypeDef SPI_RxStruct;
  5. volatile SPI_RxTx_TypeDef SPI_TxStruct;

  6. void SPI_Configure(void)
  7. {
  8.     GPIO_InitTypeDef GPIO_InitStruct;
  9.     NVIC_InitTypeDef NVIC_InitStruct;
  10.     SPI_InitTypeDef  SPI_InitStruct;
  11.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
  12.     SPI_StructInit(&SPI_InitStruct);
  13.     SPI_InitStruct.SPI_Mode      = SPI_Mode_Master;
  14.     SPI_InitStruct.SPI_DataSize  = SPI_DataSize_8b;
  15.     SPI_InitStruct.SPI_DataWidth = 8;
  16.     SPI_InitStruct.SPI_CPOL      = SPI_CPOL_Low;
  17.     SPI_InitStruct.SPI_CPHA      = SPI_CPHA_1Edge;
  18.     SPI_InitStruct.SPI_NSS       = SPI_NSS_Soft;
  19.     SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
  20.     SPI_InitStruct.SPI_FirstBit  = SPI_FirstBit_MSB;
  21.     SPI_Init(SPI1, &SPI_InitStruct);
  22.     SPI_BiDirectionalLineConfig(SPI1, SPI_Enable_RX);
  23.     SPI_BiDirectionalLineConfig(SPI1, SPI_Enable_TX);
  24.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
  25.     GPIO_PinAFConfig(GPIOA, GPIO_PinSource4,  GPIO_AF_0);
  26.     GPIO_PinAFConfig(GPIOA, GPIO_PinSource5,  GPIO_AF_0);
  27.     GPIO_PinAFConfig(GPIOA, GPIO_PinSource6,  GPIO_AF_0);
  28.     GPIO_PinAFConfig(GPIOA, GPIO_PinSource7,  GPIO_AF_0);
  29.     GPIO_StructInit(&GPIO_InitStruct);
  30.     GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;
  31.     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
  32.     GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AF_PP;
  33.     GPIO_Init(GPIOA, &GPIO_InitStruct);
  34.     GPIO_StructInit(&GPIO_InitStruct);
  35.     GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_6;
  36.     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
  37.     GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_IPU;
  38.     GPIO_Init(GPIOA, &GPIO_InitStruct);
  39.     NVIC_InitStruct.NVIC_IRQChannel = SPI1_IRQn;
  40.     NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
  41.     NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  42.     NVIC_Init(&NVIC_InitStruct);
  43.     SPI_ITCmd(SPI1, ENABLE);
  44.     SPI_Cmd(SPI1, ENABLE);
  45. }
  46. void SPI_RxData_Interrupt(uint8_t *Buffer, uint8_t Length)
  47. {
  48.     uint8_t i = 0;
  49.     for (i = 0; i < Length; i++)
  50.     {
  51.         SPI_RxStruct.Buffer[i] = 0;
  52.         SPI_TxStruct.Buffer[i] = 0;
  53.     }
  54.     SPI_RxStruct.Length = Length;
  55.     SPI_RxStruct.CurrentCount = 0;
  56.     SPI_RxStruct.CompleteFlag = 0;
  57.     SPI_TxStruct.Length = Length;
  58.     SPI_TxStruct.CurrentCount = 0;
  59.     SPI_TxStruct.CompleteFlag = 0;
  60.     SPI_ITConfig(SPI1, SPI_IT_RX, ENABLE);
  61.     SPI_ITConfig(SPI1, SPI_IT_TX, ENABLE);
  62.     while (0 == SPI_TxStruct.CompleteFlag)
  63.     {
  64.     }
  65.     while (0 == SPI_RxStruct.CompleteFlag)
  66.     {
  67.     }
  68.     for (i = 0; i < Length; i++)
  69.     {
  70.         Buffer[i] = SPI_RxStruct.Buffer[i];
  71.     }
  72. }
  73. void SPI_TxData_Interrupt(uint8_t *Buffer, uint8_t Length)
  74. {
  75.     uint8_t i = 0;
  76.     for (i = 0; i < Length; i++)
  77.     {
  78.         SPI_RxStruct.Buffer[i] = 0;
  79.         SPI_TxStruct.Buffer[i] = Buffer[i];
  80.     }
  81.     SPI_RxStruct.Length = Length;
  82.     SPI_RxStruct.CurrentCount = 0;
  83.     SPI_RxStruct.CompleteFlag = 0;
  84.     SPI_TxStruct.Length = Length;
  85.     SPI_TxStruct.CurrentCount = 0;
  86.     SPI_TxStruct.CompleteFlag = 0;
  87.     SPI_ITConfig(SPI1, SPI_IT_RX, ENABLE);
  88.     SPI_ITConfig(SPI1, SPI_IT_TX, ENABLE);
  89.     while (0 == SPI_TxStruct.CompleteFlag)
  90.     {
  91.     }
  92.     while (0 == SPI_RxStruct.CompleteFlag)
  93.     {
  94.     }
  95. }
  96. void SPI_FLASH_RxBuffer(uint8_t *Buffer, uint8_t Length)
  97. {
  98.     if (Length)
  99.     {
  100.         SPI_RxData_Interrupt(Buffer, Length);
  101.     }
  102. }
  103. void SPI_FLASH_TxBuffer(uint8_t *Buffer, uint8_t Length)
  104. {
  105.     if (Length)
  106.     {
  107.         SPI_TxData_Interrupt(Buffer, Length);
  108.     }
  109. }
  110. void SPI_FLASH_ReadDeviceID(void)
  111. {
  112.     uint8_t  Command[4] =
  113.     {
  114.         0x90, 0xFF, 0xFF, 0x00
  115.     };
  116.     uint8_t  Buffer[2];
  117.     uint16_t DeviceID = 0;
  118.     SPI_FLASH_CS_L();
  119.     SPI_FLASH_TxBuffer(Command, 0x04);
  120.     SPI_FLASH_RxBuffer(Buffer, 0x02);
  121.     SPI_FLASH_CS_H();
  122.     DeviceID   = Buffer[0];
  123.     DeviceID <<= 8;
  124.     DeviceID  |= Buffer[1];
  125.     printf("\r\nSPI Flash DeviceID : 0x%04x", DeviceID);
  126. }
  127. void SPI_FLASH_ReadJEDEC_ID(void)
  128. {
  129.     uint8_t  Command = 0x9F;
  130.     uint8_t  Buffer[3];
  131.     uint32_t JEDEC_ID = 0;
  132.     SPI_FLASH_CS_L();
  133.     SPI_FLASH_TxBuffer(&Command, 0x01);
  134.     SPI_FLASH_RxBuffer(Buffer, 0x03);
  135.     SPI_FLASH_CS_H();
  136.     JEDEC_ID   = Buffer[0];
  137.     JEDEC_ID <<= 8;
  138.     JEDEC_ID  |= Buffer[1];
  139.     JEDEC_ID <<= 8;
  140.     JEDEC_ID  |= Buffer[2];
  141.     printf("\r\nSPI Flash JEDEC ID : 0x%06x", JEDEC_ID);
  142. }
  143. void SPI_FLASH_WaitBusy(void)
  144. {
  145.     uint8_t  Status     = 0;
  146.     uint8_t  Command[2] =
  147.     {
  148.         0x05, 0xFF
  149.     };
  150.     uint32_t Timeout = 0;
  151.     do
  152.     {
  153.         SPI_FLASH_CS_L();
  154.         SPI_FLASH_TxBuffer(Command, 0x02);
  155.         SPI_FLASH_RxBuffer(&Status, 0x01);
  156.         SPI_FLASH_CS_H();
  157.         if (Timeout++ > 0xFFFF)
  158.         {
  159.             break;
  160.         }
  161.     }
  162.     while (Status & 0x01);
  163. }
  164. void SPI_FLASH_WriteEnable(void)
  165. {
  166.     uint8_t Command = 0x06;
  167.     SPI_FLASH_CS_L();
  168.     SPI_FLASH_TxBuffer(&Command, 0x01);
  169.     SPI_FLASH_CS_H();
  170. }
  171. void SPI_FLASH_SectorErase(uint16_t Index)
  172. {
  173.     uint8_t  Command[4] =
  174.     {
  175.         0x20, 0x00, 0x00, 0x00
  176.     };
  177.     uint32_t Address = Index * 4 * 1024;
  178.     Command[1] = (uint8_t)((Address >> 16) & 0x000000FF);
  179.     Command[2] = (uint8_t)((Address >> 8) & 0x000000FF);
  180.     Command[3] = (uint8_t)((Address >> 0) & 0x000000FF);
  181.     SPI_FLASH_WriteEnable();
  182.     SPI_FLASH_CS_L();
  183.     SPI_FLASH_TxBuffer(Command, 4);
  184.     SPI_FLASH_CS_H();
  185.     SPI_FLASH_WaitBusy();
  186. }
  187. void SPI_FLASH_FastRead(uint32_t Address, uint8_t *Buffer, uint32_t Length)
  188. {
  189.     uint8_t Command[5] =
  190.     {
  191.         0x0B, 0x00, 0x00, 0x00, 0xFF
  192.     };
  193.     Command[1] = (uint8_t)((Address >> 16) & 0x000000FF);
  194.     Command[2] = (uint8_t)((Address >> 8) & 0x000000FF);
  195.     Command[3] = (uint8_t)((Address >> 0) & 0x000000FF);
  196.     SPI_FLASH_CS_L();
  197.     SPI_FLASH_TxBuffer(Command, 0x05);
  198.     SPI_FLASH_RxBuffer(Buffer, Length);
  199.     SPI_FLASH_CS_H();
  200. }
  201. void SPI_FLASH_PageProgram(uint32_t Address, uint8_t *Buffer, uint32_t Length)
  202. {
  203.     uint8_t Command[4] =
  204.     {
  205.         0x02, 0x00, 0x00, 0x00
  206.     };
  207.     Command[1] = (uint8_t)((Address >> 16) & 0x000000FF);
  208.     Command[2] = (uint8_t)((Address >> 8) & 0x000000FF);
  209.     Command[3] = (uint8_t)((Address >> 0) & 0x000000FF);
  210.     SPI_FLASH_WriteEnable();
  211.     SPI_FLASH_CS_L();
  212.     SPI_FLASH_TxBuffer(Command, 0x04);
  213.     SPI_FLASH_TxBuffer(Buffer, Length);
  214.     SPI_FLASH_CS_H();
  215.     SPI_FLASH_WaitBusy();
  216. }
  217. void SPI_Master_FLASH_Interrupt_Sample(void)
  218. {
  219.     uint8_t i = 0;
  220.     uint8_t WriteBuffer[100], ReadBuffer[100];
  221.     const char* helloStr = "Hello 21ic, Hello MM32F0121";
  222.     uint8_t strLen = strlen(helloStr);
  223.    
  224.     printf("\r\nTest %s", __FUNCTION__);
  225.     SPI_Configure();
  226.     SPI_FLASH_ReadDeviceID();
  227.     SPI_FLASH_ReadJEDEC_ID();
  228.    
  229.     printf("\r\nSPI FLASH Sector Erase...");
  230.     SPI_FLASH_SectorErase(0);
  231.    
  232.     printf("\r\nWriting string: "%s"", helloStr);
  233.    
  234.     for (i = 0; i < strLen; i++) {
  235.         WriteBuffer[i] = helloStr[i];
  236.     }
  237.    
  238.     printf("\r\nSPI FLASH Page Program...");
  239.     SPI_FLASH_PageProgram(0, WriteBuffer, strLen);
  240.    
  241.     printf("\r\nSPI FLASH Read...");
  242.     SPI_FLASH_FastRead(0, ReadBuffer, strLen);
  243.    
  244.     printf("\r\nRead Data: "");
  245.     for (i = 0; i < strLen; i++) {
  246.         printf("%c", ReadBuffer[i]);
  247.     }
  248.     printf(""");
  249.    
  250.     printf("\r\nHex Data:");
  251.     for (i = 0; i < strLen; i++) {
  252.         if (0 == (i % 10)) printf("\r\n");
  253.         printf("0x%02x ", ReadBuffer[i]);
  254.     }
  255.    
  256. }



  257. void SPI1_IRQHandler(void)
  258. {
  259.     uint8_t Data = 0;

  260.     if (SPI_RxStruct.CurrentCount != SPI_TxStruct.CurrentCount)
  261.     {
  262.         if (SET == SPI_GetITStatus(SPI1, SPI_IT_RX))
  263.         {
  264.             Data = SPI_ReceiveData(SPI1);

  265.             SPI_ClearITPendingBit(SPI1, SPI_IT_RX);

  266.             if (0 == SPI_RxStruct.CompleteFlag)
  267.             {
  268.                 SPI_RxStruct.Buffer[SPI_RxStruct.CurrentCount++] = Data;

  269.                 if (SPI_RxStruct.CurrentCount == SPI_RxStruct.Length)
  270.                 {
  271.                     SPI_RxStruct.CompleteFlag = 1;

  272.                     SPI_ITConfig(SPI1, SPI_IT_TX, DISABLE);
  273.                     SPI_ITConfig(SPI1, SPI_IT_RX, DISABLE);
  274.                 }
  275.             }
  276.         }
  277.     }
  278.     else
  279.     {
  280.         if (SET == SPI_GetITStatus(SPI1, SPI_IT_TX))
  281.         {
  282.             SPI_ClearITPendingBit(SPI1, SPI_IT_TX);

  283.             if (0 == SPI_TxStruct.CompleteFlag)
  284.             {
  285.                 SPI_SendData(SPI1, SPI_TxStruct.Buffer[SPI_TxStruct.CurrentCount++]);

  286.                 if (SPI_TxStruct.CurrentCount == SPI_TxStruct.Length)
  287.                 {
  288.                     SPI_TxStruct.CompleteFlag = 1;
  289.                 }
  290.             }
  291.         }
  292.     }
  293. }
3.dsp_spi.h
  1. #include <stdio.h>
  2. #include "hal_conf.h"

  3. typedef struct
  4. {
  5.     uint8_t Buffer[255];
  6.     uint8_t Length;
  7.     uint8_t CurrentCount;
  8.     uint8_t CompleteFlag;
  9. } SPI_RxTx_TypeDef;


  10. extern volatile SPI_RxTx_TypeDef SPI_RxStruct;
  11. extern volatile SPI_RxTx_TypeDef SPI_TxStruct;

  12. void SPI_Master_FLASH_Interrupt_Sample(void);
4.实验现象
实验现象.jpg






MM32F0121C6PV_06SPI.zip

6.14 MB, 下载次数: 0

AdaMaYun 发表于 2025-7-31 17:45 | 显示全部楼层
非常不错的硬件SPI读写FLASH
您需要登录后才可以回帖 登录 | 注册

本版积分规则

13

主题

35

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部