打印
[开发板]

CW32L0开发板学习记录七:调试板载的SPI通讯芯片WQ25Q64

[复制链接]
96|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 聪聪哥哥 于 2024-12-30 19:34 编辑

1.1 SPI 介绍:
​  SPI(Serial Peripheral Interface)是由Motorola公司开发的一种通用数据总线四根通信线:SCK(Serial Clock)、MOSI(Master Output Slave Input)、MISO(Master Input Slave Output)、SS(Slave Select)。
​SPI通信具有以下特点:
同步,全双工;
支持总线挂载多设备(SPI仅支持一主多从);
在不同情况下,通信线的名称可能有所变化:
SCK:SCLK、CLK、CK;
MOSI:DI(对从机而言);
MISO:DO(对从机而言);
SS:CS(Chip Select)、NSS(Not Slave Select);
SPI通信的SS线可以有多条,即对每一个从机而言都有单独的从机选择线,一般为低电平有效。
1.2 硬件连接
所有SPI设备的SCK、MOSI、MISO分别连在一起
主机另外引出多条SS控制线,分别接到各从机的SS引脚,同一时间,主机只能选择一条SS线为低电平
输出引脚配置为推挽输出(推挽输出能使SPI的通信速度轻松达到MHz的级别),输入引脚配置为浮空或上拉输入。当从机未被SS线选中时,从机的输出引脚MISO必须呈现高阻态,以防止数据冲突
2:硬件连接方式:
由于CW32FL010开发板没有将SPI通讯线连接起来,仅仅是将芯片的引脚引出,这样做有一个好处是我们可以任意的切换SPI的引脚,或者是选择其他的引脚,只是外部在调试的时候需用杜邦线连接起来就可以,只是杜邦线有时候会出现松动的情况,不利于我们查找软件问题或者是硬件问题。
这是我们使用的是 SPI1,W25Q64的引脚如下;

SPI_NCS    ←----→ PA02
SPI_MISO    ←----→ PA3
SPI_MOSI    ←----→ PA4
SPI_CLK   ←----→ PA05
我们利用串口1,将测试数据打印到串口接收工具,接线如下:

同样我们需要利用杜邦线接线连接到一起,由于我使用的是串口供电,不知道为什么J5接线端子,并没有电压,导致在我调试的过程中CH340芯片并没有工作,我还以为是代码的问题,找了半天才去测试电压,原来供电都不正常,将3.3V接入,就正常了。
我们这边使用OLED屏幕对调试的结果信息进行一个显示,显示SPI的通讯状态是否可以正常通过;
软件代码编写:定义一下发送的数据
uint8_t TxBuffer[] = "CW32L010 SPI FLASH Test by cong cong ge ge ";
uint8_t RxBuffer[BufferSize];
OLED屏幕显示固定的信息如下所示:
  OLED_Init();   //OLED初始化
                OLED_ShowString(1,2,"21IC lun tan ");
                OLED_ShowString(2,2,"CW32 SPI TEST");
                OLED_ShowString(3,2,"congcong gegge");
        //        OLED_ShowString(4,2,"FLASH SUCCESS");
SPI有关初始化部分:
void SPI_FLASH_Init(void)
{
    SPI_InitTypeDef  SPI_InitStructure = {0};
    GPIO_InitTypeDef GPIO_InitStructure = {0};

    /************************GPIO Configuration***********************/
    SYSCTRL_AHBPeriphClk_Enable(FLASH_SPI_SCK_GPIO_CLK | FLASH_SPI_MISO_GPIO_CLK | FLASH_SPI_MOSI_GPIO_CLK | FLASH_SPI_CS_GPIO_CLK, ENABLE);
    FLASH_SPI_APBClkENx(FLASH_SPI_CLK, ENABLE);  

    //CS
    GPIO_InitStructure.Pins = FLASH_SPI_CS_GPIO_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_Init(FLASH_SPI_CS_GPIO_PORT, &GPIO_InitStructure);

    //SCK
    GPIO_InitStructure.Pins = FLASH_SPI_SCK_GPIO_PIN;
    GPIO_Init(FLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);

    //MOSI
    GPIO_InitStructure.Pins = FLASH_SPI_MOSI_GPIO_PIN;
    GPIO_Init(FLASH_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);

    //MISO
    GPIO_InitStructure.Pins = FLASH_SPI_MISO_GPIO_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
    GPIO_Init(FLASH_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
   
    //SPI SCK MOSI MISO 复用
    FLASH_SPI_AF_SCK;
    FLASH_SPI_AF_MISO;
    FLASH_SPI_AF_MOSI;

    //拉高CS
    FLASH_SPI_CS_HIGH();

    /************************SPI Configuration***********************/
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;    // 双线全双工
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                         // 主机模式
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                     // 帧数据长度为8bit
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                           // 时钟空闲电平为高
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                          // 第二个边沿采样
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                             // 片选信号由SSI寄存器控制
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;    // 波特率为PCLK的8分频
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                    // 最高有效位 MSB 收发在前
    SPI_InitStructure.SPI_Speed = SPI_Speed_Low;                          // 低速SPI

    SPI_Init(FLASH_SPIx, &SPI_InitStructure);
    SPI_Cmd(FLASH_SPIx, ENABLE);
}
这里我们使用两线制的SPI通讯,根据存储芯片的特点,在第二哥个边沿进行采样,配置信息如上所示:

主程序测试代码如下:
 SPI_FLASH_BufferRead(RxBuffer, FLASH_ReadAddress, BufferSize);
        printf("Read data:%s\r\n", RxBuffer);
        //检查写入的数据与读出的数据是否一致
        TransferStatus = Buffercmp(TxBuffer, RxBuffer, BufferSize);
        //擦除扇区 4KB
        SPI_FLASH_SectorErase(FLASH_SectorToEraseAddress);
        //读数据
        SPI_FLASH_BufferRead(RxBuffer, FLASH_ReadAddress, BufferSize);
        if(TransferStatus == PASSED)
        {
            PB02_SETHIGH();
            printf("\r\nFLASH Success\r\n");
                                                OLED_ShowString(4,2,"FLASH SUCCESS");
        }
        else
        {            
            printf("\r\nFLASH Error 1\r\n");
                                        OLED_ShowString(4,2,"FLASH ERROR");
        }
        for(uint8_t j = 0; j < BufferSize; j++)
        {
            if(RxBuffer[j] != 0xFF)
            {               
                printf("\r\nFLASH Error 2\r\n");
            }
        }
如上所示:先将发送buffer写到外部存储芯片后,并输出调试串口,随后对存储地址的内的数据,写入到读取buffer里面。为了检测SPI读写是否正常,需要将TXBUFFER 和RXBUFFER 里面的数据进行比较,当保持一致时,在OLED上面,显示“flash SUCCESS”的字样,如下图所示:
这里由于之前的代码中OLED显示所用的IO口,与SPI接口冲突,所以对IO口进行更换,不过在修改底层驱动的时候,只需要更改宏定义就可以,很方面。

串口工具接收到的数据如下所示:

使用特权

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

本版积分规则

43

主题

111

帖子

0

粉丝