|
以前在使用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就会自动产生,感觉时钟信号非常不稳,要用很低的频率来使用?
下面是代码,请大佬指导一下,谢谢~~
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")
}
}
|
|