OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 10855|回复: 10

STM32串口使用DMA方式进行接收,出现发送和接收的数据不一致

[复制链接]

15

主题

49

帖子

0

精华

初级会员

Rank: 2

积分
94
金钱
94
注册时间
2014-10-22
在线时间
24 小时
发表于 2015-1-9 10:50:22 | 显示全部楼层 |阅读模式
5金钱
我STM32串口为不占cpu资源使用DMA方式进行接收,设定接收缓冲区,在while(1)中查询已接收到的数据并进行处理,可是使用串口调试工具发送数据到板子,板子再将数据通过窗口打印处理,打印的数据和发送的数据出现不一致情况,求大侠帮忙看看!
[mw_shl_code=c,true]void User_Uart1Init(void) { GPIO_InitTypeDef GPIO_InitStructure; /* 定义GPIO初始化结构体 */ USART_InitTypeDef USART_InitStructure; /* 定义USART初始化结构体 */ /*-----------使能相关模块时钟 --------------------------------------------------------------------------*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* 使能GPIO外设时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); /* 使能USART1外设时钟 */ /*-----------是否重映射端口连接模块 --------------------------------------------------------------------*/ GPIO_PinRemapConfig(GPIO_Remap_USART1,DISABLE); /* 引脚连接模块不重映射 */ /*-----------GPIO引脚始化 ------------------------------------------------------------------------------*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; /* 设置RX引脚模式 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; /* 设置TX引脚模式 */ GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA,&GPIO_InitStructure); /*-----------UART1设置始化 -----------------------------------------------------------------------------*/ USART_InitStructure.USART_BaudRate = 9600; /* 设置USART模式 */ USART_InitStructure.USART_WordLength= USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(USART1,&USART_InitStructure); USART_Cmd(USART1,ENABLE); /* 启动USART1外设 */ USART_GetFlagStatus(USART1,USART_FLAG_TC); //不清除将导致发送的第一个字节丢失 } void Uart1_DMA_Config(void) { DMA_InitTypeDef DMA_InitS ; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //开启DMA时钟 DMA_DeInit(DMA1_Channel5); DMA_InitS.DMA_PeripheralBaseAddr = (u32)(&USART1->DR); DMA_InitS.DMA_MemoryBaseAddr = (u32)Uart_Buffer.Rxbuffer; DMA_InitS.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitS.DMA_BufferSize = RECVBUFF_SIZE; DMA_InitS.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitS.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitS.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitS.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitS.DMA_Mode = DMA_Mode_Circular; DMA_InitS.DMA_Priority = DMA_Priority_Medium; DMA_InitS.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel5, &DMA_InitS); DMA_Cmd (DMA1_Channel5,ENABLE); //使能DMA USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE); } 在while(1)中进行查询,调用下面这个函数[/mw_shl_code] [mw_shl_code=c,true]
[mw_shl_code=c,true]void ReadUartBuffer(void) { static u8 count = 0; static u8 revbuf[5] = {0}; u8 curr_char = 0; Uart_Buffer.indexnew = (RECVBUFF_SIZE - DMA_GetCurrDataCounter(DMA1_Channel5)); if(Uart_Buffer.indexnew != Uart_Buffer.indexold) { while(Uart_Buffer.indexold != Uart_Buffer.indexnew) { curr_char = Uart_Buffer.Rxbuffer[Uart_Buffer.indexold%RECVBUFF_SIZE]; Uart_Buffer.indexold = (Uart_Buffer.indexold + 1)%RECVBUFF_SIZE; if(curr_char == 0xFF) // packet head { count = 0; revbuf[count++] = curr_char; continue; } if(revbuf[0] != 0xFF) { continue; } revbuf[count] = curr_char; if(count++ < 4) { continue; } //收到一个包 count = 0; Uart_Unpack(revbuf); } if(Uart_Buffer.indexold >= RECVBUFF_SIZE) { Uart_Buffer.indexold = 0; } } } [/mw_shl_code]
[mw_shl_code=c,true]Uart_Unpack(revbuf);函数就是将收到的数据用printf通过串口打印出来。[/mw_shl_code] [mw_shl_code=c,true]实际情况是,有时候是完全正常的,运行久了一段时间又会出现发送和打印的不一样,求解释![/mw_shl_code]
[/mw_shl_code]

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

58

主题

6294

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11559
金钱
11559
注册时间
2014-4-1
在线时间
1318 小时
发表于 2015-1-9 12:17:29 | 显示全部楼层
用仿真器直接观察缓冲区,这才是根。
发出来就多了道手续。
一步一步查,就是把几个过程分开,保证前面的结果正确,再查下一步。一步一步,就是这意思。
回复

使用道具 举报

5

主题

68

帖子

0

精华

版主

Rank: 7Rank: 7Rank: 7

积分
114
金钱
114
注册时间
2014-12-25
在线时间
2 小时
发表于 2015-1-9 14:58:04 | 显示全部楼层
用DMA接收数据时要注意一帧数据接收完,或者一帧数据和设定的DMA缓冲区不一样长时候的处理方法。
回复

使用道具 举报

15

主题

49

帖子

0

精华

初级会员

Rank: 2

积分
94
金钱
94
注册时间
2014-10-22
在线时间
24 小时
 楼主| 发表于 2015-1-9 15:05:35 | 显示全部楼层
回复【2楼】xuande:
---------------------------------
通过j-link在线仿真调试,发现打印出来的数据和缓冲区的数据一致,可是这个数据和我发送的是有区别的,比如我发送
ff fe fe f0 e0
可是缓冲区的数据变成了
ff fe 20 f0 f0
这样的的数据,难道DMA搬运数据出问题?可是我的配置和网上的例程基本差不多的。如果DMA搬运数据出问题,可是第一个字节ff总是不会出错,这是为啥?
回复

使用道具 举报

15

主题

49

帖子

0

精华

初级会员

Rank: 2

积分
94
金钱
94
注册时间
2014-10-22
在线时间
24 小时
 楼主| 发表于 2015-1-9 15:13:08 | 显示全部楼层
回复【3楼】惯性坐标系:
---------------------------------
谢谢版主回复
虽然DMA缓冲区长度大于一帧数据,可是void ReadUartBuffer(void)函数是在while(1)中执行的,是一直在查询是否收到数据并处理收到的数据。而且是手动发送方的数据并且数据不多也不频繁,所以应该不会出现数据覆盖。
现在的问题是,每帧数据都是能收到的,可是收到数据和我发送的数据总有一两个字节有差别,但是第一个字节一定是正确的。用j-link在线调试也看DMA的缓冲区是这样
回复

使用道具 举报

15

主题

49

帖子

0

精华

初级会员

Rank: 2

积分
94
金钱
94
注册时间
2014-10-22
在线时间
24 小时
 楼主| 发表于 2015-1-9 15:16:19 | 显示全部楼层
回复【3楼】惯性坐标系:
---------------------------------
版主,有木有可能是硬件问题,因为断电一段时候在上电是发送正常,长时间运行一下,又可能出现这样的问题??
回复

使用道具 举报

5

主题

68

帖子

0

精华

版主

Rank: 7Rank: 7Rank: 7

积分
114
金钱
114
注册时间
2014-12-25
在线时间
2 小时
发表于 2015-1-9 15:36:13 | 显示全部楼层
硬件的问题可能性比较小,你多高的波特率?
回复

使用道具 举报

15

主题

49

帖子

0

精华

初级会员

Rank: 2

积分
94
金钱
94
注册时间
2014-10-22
在线时间
24 小时
 楼主| 发表于 2015-1-9 16:10:55 | 显示全部楼层
回复【7楼】惯性坐标系:
---------------------------------
波特率才设置为9600
回复

使用道具 举报

58

主题

6294

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11559
金钱
11559
注册时间
2014-4-1
在线时间
1318 小时
发表于 2015-1-9 16:32:56 | 显示全部楼层
DMA搬移肯定不会出问题的,多少人都用过了。
只可能是程序或者硬件有问题。
回复

使用道具 举报

15

主题

49

帖子

0

精华

初级会员

Rank: 2

积分
94
金钱
94
注册时间
2014-10-22
在线时间
24 小时
 楼主| 发表于 2015-1-9 16:54:47 | 显示全部楼层
回复【9楼】xuande:
---------------------------------
因为程序简单,就这点配置,没发现问题所在,换另一块板子试,不会出现这样的错误,但是说之前那块是硬件问题,我也觉得不太可能!!!
回复

使用道具 举报

15

主题

49

帖子

0

精华

初级会员

Rank: 2

积分
94
金钱
94
注册时间
2014-10-22
在线时间
24 小时
 楼主| 发表于 2015-1-9 20:15:02 | 显示全部楼层
不是硬件问题,是程序问题,因为另一块板子也出现同一的情况了!!可是程序中,真心找不出问题出来!!急死了!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-27 06:05

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表