打印

有关STM32中DMA的奇怪问题!!困惑!

[复制链接]
4542|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
userchen|  楼主 | 2009-9-16 22:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
2片STM32F103E之间SPI通讯:CPU_A,CPU_B。
CPU_A使用SPI1,主方式;CPU_B使用SPI2,从方式。
其中SPI都是DMA控制。2片都使用同样大小的内存区域Memory1_A,Memory1_B,Memory2_A,Memory2_B,其中CPU_A使用DMA_Mode_Normal模式,CPU_B使用DMA_Mode_Circular模式。
目的是想:A发Memory1_A的数据给B的Memroy2_A的同时,读取B中Memory2_B 的数据只A的Memory1_B,从而实现2片cpu的数据通讯。

理论上,我想这样应该是没问题的吧。但是在调试时,刚开始数据能正常通讯;期间数据会出现如下错误:
A发给B的数据都正常,但是A从B读的数据会出现错位,错位的情况是:比如A从B读的数据应该是1 2 3 4 5 6 7 8  9 0,但是实际上读到的是 * 1 2 3 4 5 6 7 8 9,即错位了。

然后我为了能是程序自己修正,在传输的数据包内增加校验和,如果发现校验和不对,即发指令给B,让B把该SPI的DMA重新初始化一遍,以达到复位的效果。
但是这样做也没有效果,我的通讯依旧是错位的。。。。。

各位大侠,能帮忙指点下么,谢谢了。
沙发
香水城| | 2009-9-16 22:32 | 只看该作者
请问你的DMA操作是如何配置的,是否在A B两端各使用了2个DMA通道?一个作为输出,另一个作为输入?

另外你说“错位的情况是:比如A从B读的数据应该是1 2 3 4 5 6 7 8  9 0,但是实际上读到的是 * 1 2 3 4 5 6 7 8 9”,这个*代表什么意思?

使用特权

评论回复
板凳
userchen|  楼主 | 2009-9-16 23:46 | 只看该作者
香水城,你好。
A的DMA配置是

    DMA_DeInit(DMA1_Channel3);
    DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_BASE+0X000c;
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)pSPICommSendBuff;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize = SPI_Comm_SendSize;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA1_Channel3, &DMA_InitStructure);
    DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);

    DMA_DeInit(DMA1_Channel2);
     DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_BASE+0X000c;
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)pSPICommRecvBuff;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = SPI_Comm_RecvSize;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_Init(DMA1_Channel2, &DMA_InitStructure);

B的配置是
  DMA_DeInit(DMA1_Channel5);
    DMA_InitStructure.DMA_PeripheralBaseAddr = SPI2_BASE+0X000c;
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)pSPICommSendBuff;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize = SPI_Comm_SendSize;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA1_Channel5, &DMA_InitStructure);
    DMA_Cmd(DMA1_Channel5, ENABLE);
  
       DMA_DeInit(DMA1_Channel4);
     DMA_InitStructure.DMA_PeripheralBaseAddr = SPI2_BASE+0X000c;
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)pSPICommRecvBuff;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = SPI_Comm_RecvSize;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_Init(DMA1_Channel4, &DMA_InitStructure);
    DMA_Cmd(DMA1_Channel4, ENABLE);


那个*表示这个数据是未知的。实际中是0x00。

使用特权

评论回复
地板
userchen|  楼主 | 2009-9-16 23:48 | 只看该作者
可能问题是这样的,cpu B是被动读取的。有可能会当我A正在读B的时候,B正在修改那个Memory的数据,从而导致A读到那个数据后发现校验和不正确,然后发指令给B复位DMA,但此动作无效好像。

使用特权

评论回复
5
userchen|  楼主 | 2009-9-18 15:27 | 只看该作者
再顶一下。
为什么会这样的问题呢?
在B片中,出错后,我复位一下,复位代码如下:
SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, DISABLE);
    DMA_Cmd(DMA1_Channel5, DISABLE);
    SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, DISABLE);
    DMA_Cmd(DMA1_Channel4, DISABLE);
   
    DMA1_Channel5->CMAR = (u32)pSPICommSendBuff;
    DMA1_Channel5->CNDTR = SPI_Comm_SendSize;
      
    DMA1_Channel4->CMAR = (u32)pSPICommRecvBuff;
    DMA1_Channel4->CNDTR = SPI_Comm_RecvSize;
   
     DMA_Cmd(DMA1_Channel4, ENABLE);
    SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);
    DMA_Cmd(DMA1_Channel5, ENABLE);     
    SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);

请问这样有啥问题么?

使用特权

评论回复
6
香水城| | 2009-9-18 15:51 | 只看该作者
SPI的速率是多少?如果太快了有可能造成DMA来不及响应而产生错误。

使用特权

评论回复
7
香水城| | 2009-9-18 18:49 | 只看该作者
再看了一下5楼的问题:你的过程复位为什么没有重新复位SPI?因为之前的DMA传输已经开始,数据已经送到SPI的发送寄存器,只重新初始化DMA而不重新初始化SPI,再次传输时当然要把上次留在发送寄存器的数据先送出去了。

使用特权

评论回复
8
userchen|  楼主 | 2009-9-18 21:07 | 只看该作者
谢谢香水城的解答,我再试试看先,呵呵。马上回来。

使用特权

评论回复
9
userchen|  楼主 | 2009-9-18 21:26 | 只看该作者
果然是这个问题啊。呵呵。
谢谢香水城大哥!!
哎,这么简单的问题咋就没发现呢。。。呵呵。。好好学习!!!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

9

主题

60

帖子

2

粉丝