打印
[MM32硬件]

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

[复制链接]
141|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
硬件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_InitTypeDef  SPI_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[i] = 0;
        SPI_TxStruct.Buffer[i] = 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[i] = SPI_RxStruct.Buffer[i];
    }
}
void SPI_TxData_Interrupt(uint8_t *Buffer, uint8_t Length)
{
    uint8_t i = 0;
    for (i = 0; i < Length; i++)
    {
        SPI_RxStruct.Buffer[i] = 0;
        SPI_TxStruct.Buffer[i] = Buffer[i];
    }
    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_t  Command[4] =
    {
        0x90, 0xFF, 0xFF, 0x00
    };
    uint8_t  Buffer[2];
    uint16_t DeviceID = 0;
    SPI_FLASH_CS_L();
    SPI_FLASH_TxBuffer(Command, 0x04);
    SPI_FLASH_RxBuffer(Buffer, 0x02);
    SPI_FLASH_CS_H();
    DeviceID   = Buffer[0];
    DeviceID <<= 8;
    DeviceID  |= Buffer[1];
    printf("\r\nSPI Flash DeviceID : 0x%04x", DeviceID);
}
void SPI_FLASH_ReadJEDEC_ID(void)
{
    uint8_t  Command = 0x9F;
    uint8_t  Buffer[3];
    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[0];
    JEDEC_ID <<= 8;
    JEDEC_ID  |= Buffer[1];
    JEDEC_ID <<= 8;
    JEDEC_ID  |= Buffer[2];
    printf("\r\nSPI Flash JEDEC ID : 0x%06x", JEDEC_ID);
}
void SPI_FLASH_WaitBusy(void)
{
    uint8_t  Status     = 0;
    uint8_t  Command[2] =
    {
        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_t  Command[4] =
    {
        0x20, 0x00, 0x00, 0x00
    };
    uint32_t Address = Index * 4 * 1024;
    Command[1] = (uint8_t)((Address >> 16) & 0x000000FF);
    Command[2] = (uint8_t)((Address >> 8) & 0x000000FF);
    Command[3] = (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[5] =
    {
        0x0B, 0x00, 0x00, 0x00, 0xFF
    };
    Command[1] = (uint8_t)((Address >> 16) & 0x000000FF);
    Command[2] = (uint8_t)((Address >> 8) & 0x000000FF);
    Command[3] = (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[4] =
    {
        0x02, 0x00, 0x00, 0x00
    };
    Command[1] = (uint8_t)((Address >> 16) & 0x000000FF);
    Command[2] = (uint8_t)((Address >> 8) & 0x000000FF);
    Command[3] = (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[100], ReadBuffer[100];
    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[i] = helloStr[i];
    }
   
    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[i]);
    }
    printf("\"");
   
    printf("\r\nHex Data:");
    for (i = 0; i < strLen; i++) {
        if (0 == (i % 10)) printf("\r\n");
        printf("0x%02x ", ReadBuffer[i]);
    }
   
}



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[SPI_RxStruct.CurrentCount++] = 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[SPI_TxStruct.CurrentCount++]);

                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[255];
    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.实验现象






MM32F0121C6PV_06SPI.zip

6.14 MB

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

11

主题

29

帖子

0

粉丝