• F303 驱动 W25Q64 遇到的问题(收的的数据被右移一位)


    问题出现:

      昨天在移植W25Q64的驱动到F3飞控上,使用正点原子的F4的驱动,细节处做了修改,但是无论如何器件ID无法正确读出,一直读出 FFEF,但手册上是说明 EF16。

    定位问题:

      首先看到读取芯片ID的函数

    //读取芯片ID
    u16 SPI_Flash_ReadID(void)
    {
        u16 Temp = 0;
        
        SPI_FLASH_CS_L();
        SPI2_ReadWriteByte(0X90);   //发送读取ID命令
        SPI2_ReadWriteByte(0x00);
        SPI2_ReadWriteByte(0x00);
        SPI2_ReadWriteByte(0x00);
        ( SPI2_ReadWriteByte(0x00); ) 
        Temp|=SPI2_ReadWriteByte(0xFF)<<8;
        Temp|=SPI2_ReadWriteByte(0xFF);
        SPI_FLASH_CS_H();
        return Temp;
    }

      其中 三句 SPI2_ReadWriteByte(0x00);是发送3个任意帧,然后第四帧就可以开始读取数据,于是,我就多加了一句(括号中),发现读出ef16,这说明,STM32的硬件SPI配置无误,SPI可以通讯,但是数据像是被右移了一位。但是程序此处不能修改,问题应该出现在SPI收发,因为此时W25Q64依旧无法读取数据,不可能在每一个W25Q64要读取前多加这一条语句,这无法根本解决问题。

      于是看到SPI收发函数

    //SPIx 读写一个字节
    //TxData:要写入的字节
    //返回值:读取到的字节
    u8 SPI2_ReadWriteByte(u8 TxData)
    {        
    //    u8 retry=0;  
        
        while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
        {
    //        retry++;
    //        if(retry>200)return 0;
        }
        SPI_SendData8(SPI2, TxData); //通过外设SPIx发送一个数据
    //    SPI_I2S_SendData16(SPI2, TxData);
    //    retry=0;
    
        while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)//检查指定的SPI标志位设置与否:接受缓存非空标志位
        {
    //        retry++;
    //        if(retry>200)return 0;
        }                                  
        return SPI_ReceiveData8(SPI2); //返回通过SPIx最近接收的数据 
    //    return SPI_I2S_ReceiveData16(SPI2);
    }

      其中,未打注释就是原子的例程,后来我查到很多人用 SPI_I2S_ReceiveData();这个函数,区别就是这句函数形参是u16,而例程是u8,会不会是这里的问题呢?于是我用打注释的两句发送/接收函数代替了例程的发送/接收函数,结果仍是不对.....

      整的一天都在上网查资料,修改,失败....不断循环

      今天早上一来,灵光一现。难道F303和F4有什么细微不同我还没发现?(我这么想是因为之前移植软件IIC的驱动,F3无响应,而F1有响应,查了快一周才发现F3是不支持位带操作的),于是再检查SPI初始化函数(昨天看了不知道多少遍了...),配合网上一查,看到ST官方F3 Discover板子的SPI初始化,在使能SPI前,还有一句函数 SPI_RxFIFOThresholdConfig(SPI2, SPI_RxFIFOThreshold_QF); 于是加上去试试,没想到正常了,ID读取正确,可对Flsah执行读取/存入操作!问题完美解决!

    下面是SPI初始化函数(不包含CS脚)

    void SPI2_Init(void)
    {
        GPIO_InitTypeDef GPIO_InitStructure;
        SPI_InitTypeDef  SPI_InitStructure;
        
        RCC_AHBPeriphClockCmd( SPI2_GPIO_RCC, ENABLE );
        RCC_APB1PeriphClockCmd(SPI2_RCC, ENABLE);
    
        GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF; 
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_Pin   = SPI2_CLK_Pin|SPI2_DI_Pin|SPI2_DO_Pin;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
        GPIO_Init(SPI2_GPIO_Port, &GPIO_InitStructure);
        
        GPIO_PinAFConfig(SPI2_GPIO_Port, SPI2_CLK_PinSource, GPIO_AF_5);
        GPIO_PinAFConfig(SPI2_GPIO_Port, SPI2_DI_PinSource,  GPIO_AF_5);
        GPIO_PinAFConfig(SPI2_GPIO_Port, SPI2_DO_PinSource,  GPIO_AF_5);
    
        SPI_InitStructure.SPI_Direction         = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
        SPI_InitStructure.SPI_Mode              = SPI_Mode_Master;      //设置SPI工作模式:设置为主SPI
        SPI_InitStructure.SPI_DataSize          = SPI_DataSize_8b;      //设置SPI的数据大小:SPI发送接收8位帧结构
        SPI_InitStructure.SPI_CPOL              = SPI_CPOL_High;        //串行同步时钟的空闲状态为高电平
        SPI_InitStructure.SPI_CPHA              = SPI_CPHA_2Edge;       //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
        SPI_InitStructure.SPI_NSS               = SPI_NSS_Soft;         //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;    //定义波特率预分频的值:波特率预分频值为256
        SPI_InitStructure.SPI_FirstBit          = SPI_FirstBit_MSB;     //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
        SPI_InitStructure.SPI_CRCPolynomial     = 7;                    //CRC值计算的多项式
        SPI_Init(SPI2, &SPI_InitStructure);  
     
        SPI_RxFIFOThresholdConfig(SPI2, SPI_RxFIFOThreshold_QF);
        
        SPI_Cmd(SPI2, ENABLE); //使能SPI外设
    }

    原因分析:

      官方对这个函数的说明是 "Configures the FIFO reception threshold for the selected SPI." 也就是对选中的SPI的接收FIFO的阈值进行配置。SPI_RxFIFOThreshold_QF: RXNE event is generated if the FIFO level is greater or equal to 1/4.也就是 如果FIFO使用大于等于1/4RXNE事件发生。

  • 相关阅读:
    【机器学习】浅谈协方差
    python {}.format
    【机器学习】准确率、精确率、召回率
    【声纹识别】 EER
    【机器学习】 最形象的入门
    逻辑卷-LVM
    RAID及软RAID的实现
    输入数字or 字符串,统计重复次数---字典统计练习
    Python-数据结构之dict(字典*****)
    POJ 3204 网络流的必须边
  • 原文地址:https://www.cnblogs.com/sypspace/p/10147606.html
Copyright © 2020-2023  润新知