打印
[STM32F1]

关于串口DMA循环接收方式的数据错位问题!

[复制链接]
3669|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
robotfan|  楼主 | 2014-12-8 17:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
uint8_t Buffrev[5];

DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;          
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)Buffrev;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;               
DMA_InitStructure.DMA_BufferSize = 1;            
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;               
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_Medium;  
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;          
DMA_Init(DMA1_Channel5, &DMA_InitStructure);           
DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);
USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
DMA_Cmd (DMA1_Channel5,ENABLE);

问题描述:
比如上位机发送的数据为十六进制0x12 0x13 0x14 0x15 0x16五个字节,下位机在开启DMA循环接收模式(DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;DMA_InitStructure.DMA_BufferSize = 5;)后正常传输后Buffrev[0]=0x12,Buffrev[1]=0x13,Buffrev[2]=0x14,Buffrev[3]=0x15,Buffrev[4]=0x16,但万一上位机发送有误或发生干扰,传输的过程中多了或少了一个字节数据,比如实际发送了0x12 0x13 0x14 0x15 0x16 0xAA 六个数据,则第一次数据接收正常,这时其实Buffrev[0]=0xAA,第二次发送正确数据的时候0x12 0x13 0x14 0x15 0x16,接收到0x15就产生了DMA接受中断Buffrev[0]=0xAA,Buffrev[1]=0x12,Buffrev[2]=0x13,Buffrev[3]=0x14,Buffrev[4]=0x15,这样我接受的数据就全部错位了,请问大家如何解决?
沙发
Ketose| | 2014-12-8 17:46 | 只看该作者
设置 标志位,如果没收到开始标志就能通知上位机重发。

使用特权

评论回复
板凳
robotfan|  楼主 | 2014-12-8 18:06 | 只看该作者
Ketose 发表于 2014-12-8 17:46
设置 标志位,如果没收到开始标志就能通知上位机重发。

但数据错位就持续下去了

使用特权

评论回复
地板
Ketose| | 2014-12-8 20:26 | 只看该作者
标志位错了,就要通知上位机重发, 上位机不能只管发送,不管对错。

使用特权

评论回复
5
robotfan|  楼主 | 2014-12-8 21:56 | 只看该作者
Ketose 发表于 2014-12-8 20:26
标志位错了,就要通知上位机重发, 上位机不能只管发送,不管对错。

因为DMA是要接收固定字节数中断的,错位不消除,下次发送上来的还是错位。

使用特权

评论回复
6
596142041| | 2014-12-8 21:58 | 只看该作者
自己添加一个数据格式就行。我一直使用的是中断。

使用特权

评论回复
7
robotfan|  楼主 | 2014-12-8 22:02 | 只看该作者
596142041 发表于 2014-12-8 21:58
自己添加一个数据格式就行。我一直使用的是中断。

不好意思不明白

使用特权

评论回复
8
mmuuss586| | 2014-12-8 22:42 | 只看该作者
robotfan 发表于 2014-12-8 22:02
不好意思不明白

他的意思不用DMA,用中断实现;

使用特权

评论回复
9
robotfan|  楼主 | 2014-12-8 23:03 | 只看该作者
mmuuss586 发表于 2014-12-8 22:42
他的意思不用DMA,用中断实现;

目前必须使用DMA实现

使用特权

评论回复
10
Ketose| | 2014-12-9 00:58 | 只看该作者
robotfan 发表于 2014-12-8 21:56
因为DMA是要接收固定字节数中断的,错位不消除,下次发送上来的还是错位。 ...

那就用空闲中断+DMA的方式。

使用特权

评论回复
11
罗菜鸟| | 2014-12-9 14:42 | 只看该作者
IDLE中断可以当成timeout来用

使用特权

评论回复
12
robotfan|  楼主 | 2014-12-9 15:53 | 只看该作者
罗菜鸟 发表于 2014-12-9 14:42
IDLE中断可以当成timeout来用

超时处理也不能处理错位问题

使用特权

评论回复
13
robotfan|  楼主 | 2014-12-9 22:14 | 只看该作者
今天实验又发现一个现象,DMA_Cmd (DMA1_Channel5,ENABLE);执行后又立刻会收到多发的数据,中间加延时也没用,清空串口缓冲区也没用

void DMA1_Channel5_IRQHandler(void)
{

       
   if(DMA_GetITStatus(DMA1_IT_TC5))
   {
                        DMA_ClearITPendingBit(DMA1_IT_GL5);
                  DMA_ClearFlag(DMA1_FLAG_GL5);
                  DMA_Cmd(DMA1_Channel5,DISABLE);                 
                 
                 USART_SendData(USART1,Buff[0]);
                 while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
                 USART_SendData(USART1,Buff[1]);
                 while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
                 USART_SendData(USART1,Buff[2]);
                 while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
                 USART_SendData(USART1,Buff[3]);
                 while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
                 USART_SendData(USART1,Buff[4]);
                 while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
                 Buff[0]=0;
                 Buff[1]=0;
                 Buff[2]=0;
                 Buff[3]=0;
                 Buff[4]=0;
DMA_SetCurrDataCounter(DMA1_Channel5,5);

DMA_Cmd (DMA1_Channel5,ENABLE);




         }

}

使用特权

评论回复
14
泰山特曲123| | 2014-12-10 00:06 | 只看该作者
线找到多发的原因,再考虑多发后如何处理。

使用特权

评论回复
15
robotfan|  楼主 | 2014-12-10 01:46 | 只看该作者
找到原因了,每次DMA中断后都要重新初始化串口以清除寄存器数据,不然当DMA开启后未被接收的数据依然会被DMA接受。

使用特权

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

本版积分规则

3

主题

18

帖子

0

粉丝