STM32F4 SPI双线双向全双工DMA读写W25Q128

2019-07-20 04:40发布

        首先说明,本人是刚刚入手F4的新人,各位大牛还请多指教。      
        在学习了一年半的stm32f103后,逐渐逐渐的觉得F1的资源已经不够自己用了,前两天购入了一块F4的开发板,接下来这几天一直钻在实验室写F4板子上的各种驱动,这两天写到了SPI flash的驱动,借鉴了原子哥的flash驱动的主体架构,自己修改了SPI的DMA传输。调试了两天,刚刚调通,还没测试两个传输方式之间的差异,现在将我的代码与大家一起分享,再来说一下我调试过程中遇到的一些问题,和我的一些心得。
        
        这两天的时间,第一天拿着我之前的F1和新买的F4调试两块板子的SPI DMA方式的通信,对于调试方式,我采取的是:先调通两块板子普通方式的SPI通信,调通之后再修改为DMA方式。直到晚上,普通方式的通信还是有问题,我就一直在检查两块板子的SPI部分的代码,遇到的问题是F1从机一直在while (SPI_I2S_GetFlagStatus(SPI_NUM, SPI_I2S_FLAG_RXNE) == RESET),判断接受区不为空这里出不来了,调试了很久,最后终于解决了。我的从机是通过片选引脚来判断主机是否来了数据,CS拉低则接收主机的数据,并且发送出去数据,结果问题就是出在这个片选脚上,主机没及时的拉高CS引脚,导致从机再次进入读数据,这是主机已经不再发数据过来了,导致从机卡在了接收缓冲区那里。这个问题解决了,接下来的DMA方式很快也弄好了。对于DMA,需要注意一点的就是,两个DMA通道一定要配置好,每次修改传输数据长度之前需要关闭DMA通道,DMA传输完成后需要清除标志位。
        第二天开始调试FLASH,读flash的ID很easy的就完成了,我心中就有些窃喜了,想着接下来的数据读写问题也不大了,主要是操作一些寄存器就OK了。根据原子哥的程序逻辑,把代码全部写完打好注释之后,把程序烧到板子上,结果傻眼了,数据都出来全为0xFF,很明显数据写入就有问题,仔细的查看了自己的代码,发现并没有什么问题,于是我上网搜索,看到了这篇帖子http://www.openedv.com/posts/list/47163.htm,我发现我的问题与这位仁兄的一模一样,于是我再仔细看了自己的代码, [mw_shl_code=c,true] uint8_t cnt = 0; uint8_t temp = 0; /* 写入页写入指令 */ SPI_TX_BUFFER[cnt++] = PAGE_PROGRAM; /* 写入24位写数据地址 */ SPI_TX_BUFFER[cnt++] = (uint8_t)(write_addr >> 16); SPI_TX_BUFFER[cnt++] = (uint8_t)(write_addr >> 8); SPI_TX_BUFFER[cnt++] = (uint8_t) write_addr; /* 使能写 */ w25qxx_write_enable(); W25QXX_CS_L; /* 开始传输 */ spi_trans(SPI_RX_BUFFER, SPI_TX_BUFFER, cnt); spi_trans_write(&temp, tx_buffer, length); W25QXX_CS_H; w25qxx_wait_free();[/mw_shl_code] 看到这里我的写入使能是在flash 片选信号上调用的,这时是不能正确的写入数据的,我修改之后的代码如下: [mw_shl_code=c,true] uint8_t cnt = 0; uint8_t temp = 0; w25qxx_write_enable(); /* 写入页写入指令 */ SPI_TX_BUFFER[cnt++] = PAGE_PROGRAM; /* 写入24位写数据地址 */ SPI_TX_BUFFER[cnt++] = (uint8_t)(write_addr >> 16); SPI_TX_BUFFER[cnt++] = (uint8_t)(write_addr >> 8); SPI_TX_BUFFER[cnt++] = (uint8_t) write_addr; /* 使能写 */ W25QXX_CS_L; /* 开始传输 */ spi_trans(SPI_RX_BUFFER, SPI_TX_BUFFER, cnt); spi_trans_write(&temp, tx_buffer, length); W25QXX_CS_H; w25qxx_wait_free();[/mw_shl_code] 我把使能写在写入数据的一开始就执行。这时能正常写入和读出了,那么问题在哪里呢?

我猜测是IO口的速度太快,FLASH没有成功的判断出CS脚的电平变化。

因为使能flash写之后紧跟着的是一个CS置高信号,函数出来之后,又来一个CS置低信号,就是这里导致了我的程序写入错误。
至此,我的SPI flash驱动就算完成了。下面我贴出我的代码,由于板子不是用的原子哥的,用探索者运行该程序,需要修改CS引脚。

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。