程序实现结果:
用stm32的一个SPI,用DMA方式读取spi flsh中的内容,然后将读到的数据用usart1 dma发到PC上,baud:115200;
选用的FLASH:W25X40 4M bit
电路接法:
stm32的spi1的四只引脚分别与flash的四只引脚一一对就就好
程序:
见附件
以下为这两天的调试过程:(可以略过)
刚开始自己把它想得似乎过于简单点了,以为只要用spi占用dma通道进行读取就行,实际上做起来问题来了?我要读取flash中的某个地址开始的一段数据,得先把命令和地址发过去给flash呀,不光是发,发了还要收呀,难道要用两个spi?spi1负责发送命令,spi2负责接收数据?纠结了会,正当要开始按这种思路开始的时候,思路终于来了。。。。
我的思路:
用SPI1-tx发送命令,同时用SPI1-rx接收数据;
程序中的几个细节处理:
1>定义一个地址和命令的发送数组: Flash_Add_Table[4],用来配置spi1-tx dma的reg地址;存放的是要发送的命令和地址信息,每次发送前将里面的内容更新,如:它的值为:0x0b 0x00 0x00 0x00,那么它代表的意思就是命令0x0b,开始地址为0x000000;(0x0b为flash的快速读取命令,地址宽度为3字节);
注意这里只定义数组大小为4,哪怕是读取几千个字节它也是4,因为读取的时候只有前面命令字节和地址信息才有用,之后的信息是没用的,哪怕它越界;
2>定义一个接收数据数组:Usart_TX_Buf[FLASH_BUF_TOTAL_NUM],用来配置spi1-rx dma的reg地址,这里的FLASH_BUF_TOTAL_NUM包括了发命令时收到的数据(前5字节)、真正要读取的数据(N字节)、CRC值(1字节),详细情况看程序;
3>每次接收完成后复位CRC的值,要不然会出错;
SPI_CalculateCRC( SPI1, DISABLE);
SPI_CalculateCRC( SPI1, ENABLE);
4>spi作主机模式,NSS脚得注意了,这种读数据的场合NSS得用软件管理了,NSS脚用GPIO用来驱动flash上的片选信息;
讨论点:
1>本想用一个数据实现上述1,2功能,但始终只能正确接收一次,下午搞了好几个小时也没搞成,后来才换成2个数据来实现,原因:rx-dma tx-dma同一时间抢占一个地址延时??
2>程序的内容是循环读0x000000开始的4K内容,刚开始只有第一次是正常,随后的就是接收到的数前面多了一个字节,spi-rx dma传完后还有字节,什么原因还没找到,应急就在每次rx-dma启动前加了下面语句:
if(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE)!=RESET)
{
temp5=SPI1->DR;
}
这个地方还待改善;
3>接收一次后发现SPI1_SR的CRCERR被置位了?我对过数据了,接收到的数据和flash中的数据是一样的,为什么会报CRC检验错误?怎么理解这个问题
手册中写道:
SPI带CRC的DMA功能
当使能SPI使用CRC检验并且启用DMA模式时,在通信结束时,CRC字节的发送和接收是自动完成的。
数据和CRC传输结束时,SPI_SR寄存器的CRCERR标志为’1’表示在传输期间发生错误。
CRCERR:CRC错误标志 (CRC error flag) 位4
0:收到的CRC值和SPI_RXCRCR寄存器中的值匹配;
1:收到的CRC值和SPI_RXCRCR寄存器中的值不匹配。
该位由硬件置位,由软件写’0’而复位。
既然是自动完成的,为什么报错? |