[AT32F403/403A] SPI全双工DMA方式读取时,前面总会多读几个字节

[复制链接]
2165|7
 楼主| dopod577w 发表于 2022-6-1 10:43 | 显示全部楼层 |阅读模式
例如,用全双工DMA模式读SPI Flash芯片的数据,首先要发送2个命令字节,然后再读回3个数据字节。
但是,你必须读5个字节才行,前面2个字节是无用数据,因为发送前面2个字节时,SPI的接收电路也在工作。

处理的方法也比较简单,去掉前面2个字节,只保留后面3个字节就行了。
但是这样很不通用,每次读取时,前面的命令字节数是不定长的,后面的接收缓冲区也可能指向不同的数组,总不能为每个接收数组预留几个空字节吧。

但是ST的HAL库函数HAL_SPI_Receive_DMA就没有这个烦恼,直接指定接收缓冲区的地址就行,用不着手工去掉前面的无用字节

不知道AT32里面该怎么实现?

我的代码大概如此:
  1. void spi_read(uint8_t *addr, uint32_t len)
  2. {
  3. //1. 配置RX DMA
  4.         //禁用DMA通道,否则不能改参数
  5.         dma_channel_enable(DMA2_CHANNEL1, FALSE);

  6.         //改参数后打开DMA
  7.         DMA2_CHANNEL1->dtcnt = len;
  8.         DMA2_CHANNEL1->maddr = (uint32_t)addr;
  9.         dma_channel_enable(DMA2_CHANNEL1, TRUE);

  10. //2. 配置TX DMA,输出dummy数据,否则没有CLK
  11.         //禁用DMA通道,否则不能改参数
  12.         dma_channel_enable(DMA2_CHANNEL2, FALSE);

  13.         //改参数后打开DMA
  14.         DMA2_CHANNEL2->dtcnt = len;
  15.         DMA2_CHANNEL2->maddr = (uint32_t)addr;
  16.         dma_channel_enable(DMA2_CHANNEL2, TRUE);

  17. //3. 等到传输完成标志=1
  18.         while (dma_flag_get(DMA2_FDT1_FLAG)==RESET){};
  19. }
上面只是SPI DMA读取的代码。该代码执行前,先用spi_send发送N个字节,器件会返回M个字节,而spi_read的len必须等于N+M。
我希望,器件返回M个字节,那么spi_read的len就设置为M,不要再费劲从*addr指向的缓冲区里抠掉N个字节。

carpsnow 发表于 2022-6-1 20:58 | 显示全部楼层
每次都这样?
 楼主| dopod577w 发表于 2022-6-2 21:10 | 显示全部楼层

是的,原理上就是这样
以前用ST的,最开始HAL库也是这样
后来不知哪个版本HAL库,就不用自己抠字节了

前两天有事没继续研究,我这两天试试
carpsnow 发表于 2022-6-2 22:08 | 显示全部楼层
半双工试试
hoop 发表于 2022-6-5 13:24 | 显示全部楼层
这只是应用层逻辑。
AT demo的做法是命令通过轮训的方式发送,随后数据收发的时候切换使用DMA。
CosOxygen 发表于 2022-7-10 11:32 | 显示全部楼层
楼主你好,你的问题现在解决了吗?
我这几天也遇到了这样的问题,我给dma 传输使能之后delay 5us好像就好了(不这样做dma就无法正确搬运数据到内存),读一个字节,
如果读多个字节读出来的数据不是0x00,就是0xFF很奇怪,偶尔出现其他数据
CosOxygen 发表于 2022-7-10 11:36 | 显示全部楼层
CosOxygen 发表于 2022-7-10 11:32
楼主你好,你的问题现在解决了吗?
我这几天也遇到了这样的问题,我给dma 传输使能之后delay 5us好像就好了 ...

补充一下,发送没有发现问题

评论

每次发送接收复位dma寄存器重新配置就好了。  发表于 2022-7-27 23:10
您需要登录后才可以回帖 登录 | 注册

本版积分规则

12

主题

26

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部