硬汉嵌入式论坛

 找回密码
 立即注册
查看: 212|回复: 3
收起左侧

stm32F103和030的SPI仅读模式遇到的问题

[复制链接]

0

主题

5

回帖

5

积分

新手上路

积分
5
发表于 2025-5-13 13:21:54 | 显示全部楼层 |阅读模式
以前在使用SPI的时候都是使用全双工模式,今天想试一下SPI的双线仅读模式SPI_Direction_2Lines_RxOnly,但是很奇怪,得到的数据总是有点出错,不完全对。

我的理解是 双线全双工(SPI_Direction_2Lines_FullDuplex),双线只接收 (SPI_Direction_2Lines_RxOnly),单线只接收 (SPI_Direction_1Line_Rx)、单线只发送模式(SPI_Direction_1Line_Tx)


但是从字面理解,感觉双线只接收 (SPI_Direction_2Lines_RxOnly)和单线只接收 (SPI_Direction_1Line_Rx)好像没有什么区别啊~~都是没有发送,只有接收,


我的情况是这样,双线全双工的时候,SPI用2分频(36M)和4分频(18M),读W25Q128的图片数据是正常的,显示到LCD也正常,但是用单线只接收 (SPI_Direction_1Line_Rx)模式就出问题了,显示到LCD不正常,用逻辑分析仪看了一下,从W25Q128引脚出来的数据是完全正确的,应该是SPI接收数据进入MCU后出的问题,把SPI频率设置到64分频(1M左右)数据就正确了。1M的频率这么慢才正常,这不应该啊。


难道是双线只接收 (SPI_Direction_2Lines_RxOnly)的频率非常快?只要使能SPI就会自动产生,SPI从W25Q128读到的数据我没有及时从DR数据寄存器取出造成覆盖了?从我的程序来看也不应该啊~

我个人目前的感觉是,双线只接收 (SPI_Direction_2Lines_RxOnly)模式的时钟只要使能SPI就会自动产生,感觉时钟信号非常不稳,要用很低的频率来使用?


图1.png



下面是代码,请大佬指导一下,谢谢~~



int main()
{
        delay_init();                     //延时函数初始化      
        uart_init(115200);                 //串口初始化为11520
        W25QXX_Init();

        LCD_Init();

        LCD_DrawPicture(0, 0, 240, 320,0);
        for(;;)
        {
               
        }
}


void LCD_DrawPicture(uint16_t x, uint16_t y, uint16_t width, uint16_t height,u32 address)
{
        u16 i=0;
        u16 Buffer[240]={0};

        LCD_Set_Window(x, y, x + width-1, y + height-1);
                                          
        for(i=0;i<320;i++)
        {

                SFLASH_FastReadNByte(Buffer,address+i*240*2, 240);//从W25Q128里读取一行数据

                for (uint16_t pixels = 0; pixels < 240; pixels++)
                {
                        LCD_WR_DATA(Buffer[pixels]);//把从W25Q128里读出的数据填充一行LCD屏像素
                }
        }      
}





void SFLASH_FastReadNByte(uint16_t* pBuffer, uint32_t ReadAddr, uint16_t nByte)
{
        static uint8_t index;
      
        u8 point_data_01;//LCD高8位数据
        u8 point_data_02;//LCD低8位数据
      
      
        W25QXX_CS(0);                                    //使能器件   
        SPI1_ReadWriteByte(W25X_FastReadData);      //
        SPI1_ReadWriteByte((uint8_t)((ReadAddr)>>16));
        SPI1_ReadWriteByte((uint8_t)((ReadAddr)>>8));
        SPI1_ReadWriteByte((uint8_t)ReadAddr);
        SPI1_ReadWriteByte(0xFF);                   //等待8个时钟
      
      


        SPI1->CR1&=~(1<<6);//关闭SPI外设,更改SPI参数要先关闭SPI再更改才能起效.
        SPI1->CR1|=(1<<10);//只读模式
        SPI1->CR1|=(1<<6);//开启SPI外设
      

      
        for(u16 i=0;i<nByte;i++)
        {
               
        // 在RxOnly模式下,不需要发送数据
        // 只需等待接收完成

                while (SPI_I2S_GetFlagStatus(FLASH_SPIx, SPI_I2S_FLAG_RXNE) == RESET);//等待接收完一个byte
                point_data_01 = *(uint8_t*)&(SPI1->DR);//读取LCD高8位数据
                while (SPI_I2S_GetFlagStatus(FLASH_SPIx, SPI_I2S_FLAG_RXNE) == RESET);//等待接收完一个byte
                point_data_02 = *(uint8_t*)&(SPI1->DR);//读取LCD低8位数据
                       
                pBuffer = point_data_01 | point_data_02<<8;//把高低8位数据合并成16位数据
        }
        W25QXX_CS(1);
      

/*把SPI设置回全双工模式,方便其他地方使用*/
        SPI1->CR1&=~(1<<6);//关闭SPI
        SPI1->CR1&=~(1<<10); //全双工模式
        SPI1->CR1|=(1<<6);//开启SPI

      
/*把从W25Q128里读的一行数据打印出来*/
            for(u16 b=0;b<240;b++)
                {
                        printf("0x%04X  ", pBuffer);
                }
                 printf("\r\n");        printf("\r\n")
        }


}
回复

使用道具 举报

0

主题

5

回帖

5

积分

新手上路

积分
5
 楼主| 发表于 2025-5-13 13:31:12 | 显示全部楼层
中文说明书翻译有误,设置RXONLY=1是在SPI_CR1寄存器设置的,而不是SPI_CR2,所以我代码的 SPI1->CR1|=(1<<10)是没有问题的,大家别误会
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116194
QQ
发表于 2025-5-13 15:39:06 | 显示全部楼层
1、这两地方的描述没看懂。

到底是单线只接收 (SPI_Direction_1Line_Rx)模式速度慢,还是是双线只接收 (SPI_Direction_2Lines_RxOnly)速度慢,还是都慢。

2、操作SPI Flash,不发送的话,楼主这个如何实现读取SPI Flash指定地址数据的。
回复

使用道具 举报

0

主题

5

回帖

5

积分

新手上路

积分
5
 楼主| 发表于 2025-5-13 16:00:20 | 显示全部楼层
eric2013 发表于 2025-5-13 15:39
1、这两地方的描述没看懂。

到底是单线只接收 (SPI_Direction_1Line_Rx)模式速度慢,还是是双线只接收 ( ...

1.我用的是双线只接收 (SPI_Direction_2Lines_RxOnly),不是速度慢,是数据回到MCU不对了

2.我平时是正常全双工8位使用的,用来初始化或给SPI为指命令用,发完控制指令后,我读图片数据的时候再变成只读模式,因为听说用只读模式会比全双工的速度快,所以我才想这样操作。

我目前是为了显示全屏图片刷图速度快,48引脚的MCU,没有FMSC接口,只能模拟8080,16BIT驱动LCD,刷全屏目前用了双缓冲DMA加速,SPI FLASH读一行,LCD显示一行,速度不错,只是想再从仅读模式再加速一下,所以试一下仅读模式,结果没有用DMA方式,就简简单单的普通8位仅读模式数据就搞不对
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-6-9 15:42 , Processed in 0.236919 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表