阿源玩电子 发表于 2025-6-30 20:00

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

硬件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
#include "dsp_spi.h"


#define SPI_FLASH_CS_H() SPI_CSInternalSelected(SPI1, DISABLE)
#define SPI_FLASH_CS_L() SPI_CSInternalSelected(SPI1, ENABLE)


volatile SPI_RxTx_TypeDef SPI_RxStruct;
volatile SPI_RxTx_TypeDef SPI_TxStruct;

void SPI_Configure(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;
    SPI_InitTypeDefSPI_InitStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
    SPI_StructInit(&SPI_InitStruct);
    SPI_InitStruct.SPI_Mode      = SPI_Mode_Master;
    SPI_InitStruct.SPI_DataSize= SPI_DataSize_8b;
    SPI_InitStruct.SPI_DataWidth = 8;
    SPI_InitStruct.SPI_CPOL      = SPI_CPOL_Low;
    SPI_InitStruct.SPI_CPHA      = SPI_CPHA_1Edge;
    SPI_InitStruct.SPI_NSS       = SPI_NSS_Soft;
    SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
    SPI_InitStruct.SPI_FirstBit= SPI_FirstBit_MSB;
    SPI_Init(SPI1, &SPI_InitStruct);
    SPI_BiDirectionalLineConfig(SPI1, SPI_Enable_RX);
    SPI_BiDirectionalLineConfig(SPI1, SPI_Enable_TX);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource4,GPIO_AF_0);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource5,GPIO_AF_0);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6,GPIO_AF_0);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource7,GPIO_AF_0);
    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
    GPIO_InitStruct.GPIO_Mode= GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStruct);
    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_6;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
    GPIO_InitStruct.GPIO_Mode= GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitStruct);
    NVIC_InitStruct.NVIC_IRQChannel = SPI1_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);
    SPI_ITCmd(SPI1, ENABLE);
    SPI_Cmd(SPI1, ENABLE);
}
void SPI_RxData_Interrupt(uint8_t *Buffer, uint8_t Length)
{
    uint8_t i = 0;
    for (i = 0; i < Length; i++)
    {
      SPI_RxStruct.Buffer = 0;
      SPI_TxStruct.Buffer = 0;
    }
    SPI_RxStruct.Length = Length;
    SPI_RxStruct.CurrentCount = 0;
    SPI_RxStruct.CompleteFlag = 0;
    SPI_TxStruct.Length = Length;
    SPI_TxStruct.CurrentCount = 0;
    SPI_TxStruct.CompleteFlag = 0;
    SPI_ITConfig(SPI1, SPI_IT_RX, ENABLE);
    SPI_ITConfig(SPI1, SPI_IT_TX, ENABLE);
    while (0 == SPI_TxStruct.CompleteFlag)
    {
    }
    while (0 == SPI_RxStruct.CompleteFlag)
    {
    }
    for (i = 0; i < Length; i++)
    {
      Buffer = SPI_RxStruct.Buffer;
    }
}
void SPI_TxData_Interrupt(uint8_t *Buffer, uint8_t Length)
{
    uint8_t i = 0;
    for (i = 0; i < Length; i++)
    {
      SPI_RxStruct.Buffer = 0;
      SPI_TxStruct.Buffer = Buffer;
    }
    SPI_RxStruct.Length = Length;
    SPI_RxStruct.CurrentCount = 0;
    SPI_RxStruct.CompleteFlag = 0;
    SPI_TxStruct.Length = Length;
    SPI_TxStruct.CurrentCount = 0;
    SPI_TxStruct.CompleteFlag = 0;
    SPI_ITConfig(SPI1, SPI_IT_RX, ENABLE);
    SPI_ITConfig(SPI1, SPI_IT_TX, ENABLE);
    while (0 == SPI_TxStruct.CompleteFlag)
    {
    }
    while (0 == SPI_RxStruct.CompleteFlag)
    {
    }
}
void SPI_FLASH_RxBuffer(uint8_t *Buffer, uint8_t Length)
{
    if (Length)
    {
      SPI_RxData_Interrupt(Buffer, Length);
    }
}
void SPI_FLASH_TxBuffer(uint8_t *Buffer, uint8_t Length)
{
    if (Length)
    {
      SPI_TxData_Interrupt(Buffer, Length);
    }
}
void SPI_FLASH_ReadDeviceID(void)
{
    uint8_tCommand =
    {
      0x90, 0xFF, 0xFF, 0x00
    };
    uint8_tBuffer;
    uint16_t DeviceID = 0;
    SPI_FLASH_CS_L();
    SPI_FLASH_TxBuffer(Command, 0x04);
    SPI_FLASH_RxBuffer(Buffer, 0x02);
    SPI_FLASH_CS_H();
    DeviceID   = Buffer;
    DeviceID <<= 8;
    DeviceID|= Buffer;
    printf("\r\nSPI Flash DeviceID : 0x%04x", DeviceID);
}
void SPI_FLASH_ReadJEDEC_ID(void)
{
    uint8_tCommand = 0x9F;
    uint8_tBuffer;
    uint32_t JEDEC_ID = 0;
    SPI_FLASH_CS_L();
    SPI_FLASH_TxBuffer(&Command, 0x01);
    SPI_FLASH_RxBuffer(Buffer, 0x03);
    SPI_FLASH_CS_H();
    JEDEC_ID   = Buffer;
    JEDEC_ID <<= 8;
    JEDEC_ID|= Buffer;
    JEDEC_ID <<= 8;
    JEDEC_ID|= Buffer;
    printf("\r\nSPI Flash JEDEC ID : 0x%06x", JEDEC_ID);
}
void SPI_FLASH_WaitBusy(void)
{
    uint8_tStatus   = 0;
    uint8_tCommand =
    {
      0x05, 0xFF
    };
    uint32_t Timeout = 0;
    do
    {
      SPI_FLASH_CS_L();
      SPI_FLASH_TxBuffer(Command, 0x02);
      SPI_FLASH_RxBuffer(&Status, 0x01);
      SPI_FLASH_CS_H();
      if (Timeout++ > 0xFFFF)
      {
            break;
      }
    }
    while (Status & 0x01);
}
void SPI_FLASH_WriteEnable(void)
{
    uint8_t Command = 0x06;
    SPI_FLASH_CS_L();
    SPI_FLASH_TxBuffer(&Command, 0x01);
    SPI_FLASH_CS_H();
}
void SPI_FLASH_SectorErase(uint16_t Index)
{
    uint8_tCommand =
    {
      0x20, 0x00, 0x00, 0x00
    };
    uint32_t Address = Index * 4 * 1024;
    Command = (uint8_t)((Address >> 16) & 0x000000FF);
    Command = (uint8_t)((Address >> 8) & 0x000000FF);
    Command = (uint8_t)((Address >> 0) & 0x000000FF);
    SPI_FLASH_WriteEnable();
    SPI_FLASH_CS_L();
    SPI_FLASH_TxBuffer(Command, 4);
    SPI_FLASH_CS_H();
    SPI_FLASH_WaitBusy();
}
void SPI_FLASH_FastRead(uint32_t Address, uint8_t *Buffer, uint32_t Length)
{
    uint8_t Command =
    {
      0x0B, 0x00, 0x00, 0x00, 0xFF
    };
    Command = (uint8_t)((Address >> 16) & 0x000000FF);
    Command = (uint8_t)((Address >> 8) & 0x000000FF);
    Command = (uint8_t)((Address >> 0) & 0x000000FF);
    SPI_FLASH_CS_L();
    SPI_FLASH_TxBuffer(Command, 0x05);
    SPI_FLASH_RxBuffer(Buffer, Length);
    SPI_FLASH_CS_H();
}
void SPI_FLASH_PageProgram(uint32_t Address, uint8_t *Buffer, uint32_t Length)
{
    uint8_t Command =
    {
      0x02, 0x00, 0x00, 0x00
    };
    Command = (uint8_t)((Address >> 16) & 0x000000FF);
    Command = (uint8_t)((Address >> 8) & 0x000000FF);
    Command = (uint8_t)((Address >> 0) & 0x000000FF);
    SPI_FLASH_WriteEnable();
    SPI_FLASH_CS_L();
    SPI_FLASH_TxBuffer(Command, 0x04);
    SPI_FLASH_TxBuffer(Buffer, Length);
    SPI_FLASH_CS_H();
    SPI_FLASH_WaitBusy();
}
void SPI_Master_FLASH_Interrupt_Sample(void)
{
    uint8_t i = 0;
    uint8_t WriteBuffer, ReadBuffer;
    const char* helloStr = "Hello 21ic, Hello MM32F0121";
    uint8_t strLen = strlen(helloStr);
   
    printf("\r\nTest %s", __FUNCTION__);
    SPI_Configure();
    SPI_FLASH_ReadDeviceID();
    SPI_FLASH_ReadJEDEC_ID();
   
    printf("\r\nSPI FLASH Sector Erase...");
    SPI_FLASH_SectorErase(0);
   
    printf("\r\nWriting string: \"%s\"", helloStr);
   
    for (i = 0; i < strLen; i++) {
      WriteBuffer = helloStr;
    }
   
    printf("\r\nSPI FLASH Page Program...");
    SPI_FLASH_PageProgram(0, WriteBuffer, strLen);
   
    printf("\r\nSPI FLASH Read...");
    SPI_FLASH_FastRead(0, ReadBuffer, strLen);
   
    printf("\r\nRead Data: \"");
    for (i = 0; i < strLen; i++) {
      printf("%c", ReadBuffer);
    }
    printf("\"");
   
    printf("\r\nHex Data:");
    for (i = 0; i < strLen; i++) {
      if (0 == (i % 10)) printf("\r\n");
      printf("0x%02x ", ReadBuffer);
    }
   
}



void SPI1_IRQHandler(void)
{
    uint8_t Data = 0;

    if (SPI_RxStruct.CurrentCount != SPI_TxStruct.CurrentCount)
    {
      if (SET == SPI_GetITStatus(SPI1, SPI_IT_RX))
      {
            Data = SPI_ReceiveData(SPI1);

            SPI_ClearITPendingBit(SPI1, SPI_IT_RX);

            if (0 == SPI_RxStruct.CompleteFlag)
            {
                SPI_RxStruct.Buffer = Data;

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

                  SPI_ITConfig(SPI1, SPI_IT_TX, DISABLE);
                  SPI_ITConfig(SPI1, SPI_IT_RX, DISABLE);
                }
            }
      }
    }
    else
    {
      if (SET == SPI_GetITStatus(SPI1, SPI_IT_TX))
      {
            SPI_ClearITPendingBit(SPI1, SPI_IT_TX);

            if (0 == SPI_TxStruct.CompleteFlag)
            {
                SPI_SendData(SPI1, SPI_TxStruct.Buffer);

                if (SPI_TxStruct.CurrentCount == SPI_TxStruct.Length)
                {
                  SPI_TxStruct.CompleteFlag = 1;
                }
            }
      }
    }
}3.dsp_spi.h
#include <stdio.h>
#include "hal_conf.h"

typedef struct
{
    uint8_t Buffer;
    uint8_t Length;
    uint8_t CurrentCount;
    uint8_t CompleteFlag;
} SPI_RxTx_TypeDef;


extern volatile SPI_RxTx_TypeDef SPI_RxStruct;
extern volatile SPI_RxTx_TypeDef SPI_TxStruct;

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






AdaMaYun 发表于 2025-7-31 17:45

非常不错的硬件SPI读写FLASH
页: [1]
查看完整版本: 【灵动微电子MM32F0121测评】6.硬件SPI读写FLASH