OpenEdv-开源电子网

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

stm32新手,使用串口2的空闲中断,DMA接收数据,为什么总是丢失部分数据,求大侠们帮忙!!!

[复制链接]

12

主题

85

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
437
金钱
437
注册时间
2014-10-21
在线时间
49 小时
发表于 2014-12-1 14:18:51 | 显示全部楼层 |阅读模式
5金钱
[mw_shl_code=c,true]void DMA_uart2_init(void) { RCC->AHBENR |= 1; //使能DMA时钟 /*DMA1CHANNEL7 INIT for USART2-TXD */ DMA1_Channel7->CCR |= 1<<1;//允许传输完成中断 DMA1_Channel7->CCR |= 1<<4;//从存储器读 DMA1_Channel7->CCR |= 1<<5;//循环操作 DMA1_Channel7->CCR |= 1<<7;//存储器地址增量 DMA1_Channel7->CCR |= 2<<12;//优先级别为高 DMA1_Channel7->CNDTR = 15;//传输数据长度 DMA1_Channel7->CPAR = (unsigned int)&(USART2->DR);//传输数据外设地址 DMA1_Channel7->CMAR = (unsigned int)(uart2.DMA_txBuffer);//传输数据存储器地址 MY_NVIC_Init(2,2,DMA1_Channel7_IRQChannel,2);//组2,最低优先级 DMA1_Channel6->CCR |= 1<<7;//存储器地址增量 DMA1_Channel6->CCR |= 1<<5;//循环操作 DMA1_Channel6->CCR |= 3<<12;//优先级别为高 DMA1_Channel6->CNDTR = UART_BUFFER_LENGTH;//传输数据长度 DMA1_Channel6->CPAR = (unsigned int)&(USART2->DR);//传输数据外设地址 DMA1_Channel6->CMAR = (unsigned int)(uart2.DMA_rxBuffer);//传输数据存储器地址 DMA1CHANNEL6_ENABLE; } unsigned short get_DMA1ch6_reclen(void) { return UART_BUFFER_LENGTH - DMA1_Channel6->CNDTR; } /*获取通道7数据发送剩余长度*/ unsigned short get_DMA1ch7_remlen(void) { return DMA1_Channel7->CNDTR; } void uart2_init_230400(void) { u32 pclk1; u32 bound; float temp; u16 mantissa; u16 fraction; pclk1=36; bound=230400; temp=(float)(pclk1*1000000)/(bound*16);//得到USARTDIV mantissa=temp; //得到整数部分 fraction=(temp-mantissa)*16; //得到小数部分 mantissa<<=4; mantissa+=fraction; RCC->APB2ENR|=1<<2; //使能PORTA口时钟 GPIOA->CRL&=0XFFFF00FF; //IO状态设置 GPIOA->CRL|=0X00008B00; //IO状态设置 RCC->APB1ENR|=1<<17; //使能串口2时钟 RCC->APB1RSTR|=1<<17; //复位串口2 RCC->APB1RSTR&=~(1<<17);//停止复位 //波特率设置 USART2->BRR=mantissa; // 波特率设置 USART2->CR1|=0X200C; //使能空闲中断 USART2->CR1|=1<<4; USART2->CR3 |= (3<<6); //使能串口DMA功能 MY_NVIC_Init(3,4,USART2_IRQChannel,2);//组2,最低优先级 DMA_uart2_init(); } void USART2_IRQHandler(void) { //DMA unsigned char *tempPtr; unsigned short templen; if(USART2->SR&(1<<4))//空闲中断 { uart2Tmp = USART2->SR; uart2Tmp = USART2->DR; templen = get_DMA1ch6_reclen(); tempPtr = uart2.DMA_rxBuffer; DMA1CHANNEL6_DISABLE; DMA1->IFCR |= 7<<20;//清除DMA1通道6全局中断标志 DMA1_Channel6->CNDTR = UART_BUFFER_LENGTH;//接收数据长度 while(templen--) { uart2.rcBuffer++ = *tempPtr++; DMA1CHANNEL6_ENABLE; } } } void DMAChannel7_IRQHandler(void) { DMA1->IFCR |= 7<<24; //清除DMA1通道7全局中断标志 }[/mw_shl_code]

最佳答案

查看完整内容[请看2#楼]

搞定了,真高兴 u16 USART3_RX_STA=0;  //接收数据状态 u8 USART3_RX_BUF;  //接收缓冲,最大USART3_MAX_RECV_LEN个字节.  void DMA_uart3_init(void) { RCC->AHBENR|=1;  //使能DMA时钟  /*DMA1CHANNEL3 INIT for USART3-RXD */ DMA1_Channel3->CCR&=~(1<<4);   //从外设读取数据 DMA1_Channel3->CCR&=~(1<<5); //不 ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

8

主题

76

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
264
金钱
264
注册时间
2013-9-5
在线时间
31 小时
发表于 2014-12-1 14:18:52 | 显示全部楼层
搞定了,真高兴

u16 USART3_RX_STA=0;  //接收数据状态
u8 USART3_RX_BUF[USART3_MAX_RECV_LEN];  //接收缓冲,最大USART3_MAX_RECV_LEN个字节. 

void DMA_uart3_init(void)
{
RCC->AHBENR|=1;  //使能DMA时钟 
/*DMA1CHANNEL3 INIT for USART3-RXD */
DMA1_Channel3->CCR&=~(1<<4);   //从外设读取数据
DMA1_Channel3->CCR&=~(1<<5); //不循环
DMA1_Channel3->CCR|=1<<7; //存储器地址增量
DMA1_Channel3->CCR|=1<<12; //优先级别中
DMA1_Channel3->CCR&=~(1<<14);  //非存储器到存储器模式
DMA1_Channel3->CNDTR=USART3_MAX_RECV_LEN; //传输数据长度
DMA1_Channel3->CPAR =(u32)&(USART3->DR);//传输数据外设地址
DMA1_Channel3->CMAR =(u32)(USART3_RX_BUF);//传输数据存储器地址
DMA1_Channel3->CCR|=(1<<0);  //开始DMA传输 
}

u16 get_DMA1ch3_reclen(void) 

   return USART3_MAX_RECV_LEN - DMA1_Channel3->CNDTR; 



void USART3_IRQHandler(void)
{
if(USART3->SR&(1<<4)) //空闲中断
{
USART3_RX_STA=USART3->SR;//先读SR,然后读DR才能清除IDLE
USART3_RX_STA=USART3->DR;
USART3_RX_STA=get_DMA1ch3_reclen();
USART3_RX_STA|=1<<15; //强制标记接收完成
DMA1_Channel3->CCR&=~(1<<0);  //关闭DMA传输 
DMA1_Channel3->CNDTR = USART3_MAX_RECV_LEN;
DMA1_Channel3->CCR|=(1<<0);  //开启DMA传输 
}
}   
//初始化IO 串口3
//pclk1CLK1时钟频率(Mhz)
//bound:波特率   
void USART3_Init(u32 pclk1,u32 bound)
{      
RCC->APB2ENR|=1<<3;    //使能PORTB时钟
GPIOB->CRH&=0XFFFF00FF; //IO状态设置
GPIOB->CRH|=0X00008B00; //PB10输出,PB11输入
RCC->APB1ENR|=1<<18;   //使能串口3时钟   
RCC->APB1RSTR|=1<<18;   //复位串口3
RCC->APB1RSTR&=~(1<<18);//停止复位        
//波特率设置
USART3->BRR=(pclk1*1000000)/(bound);// 波特率设置  
USART3->CR1|=0X200C;   //1位停止,无校验位.

USART3->CR1|=1<<4;     //空闲中断使能
USART3->CR3=1<<6;    //使能串口3的DMA接收
MY_NVIC_Init(3,3,USART3_IRQChannel,2);//组2,优先级3,3 
DMA_uart3_init();
}

/*************************主程序*******************************/
int main(void)
{     
u8 t=0;
u8 n=0;
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72);      //延时初始化
uart_init(72,9600);  //72M主频下串口初始化为9600
USART3_Init(36,9600);
//KEY_Init();          //初始化与按键连接的硬件接口
RTC_Init();
Auto_Time_Set(); //自动设置时间为编译器时间 
LCD19264_IO();
ini19264();
ClearScreen();
disptimeHEAD();
while(1)
{
if(USART3_RX_STA&0X8000) //串口3接收到一次数据了

USART3_RX_BUF[USART3_RX_STA&0X7FFF]=0; //添加结束符 
printf("%s",USART3_RX_BUF); //发送到串口1
USART3_RX_STA=0;
printf("%d\r\n",n);
n++;
}
        }
}
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2014-12-1 15:19:38 | 显示全部楼层
没搞过,论坛有网友发过帖子你找到研究下吧。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

12

主题

85

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
437
金钱
437
注册时间
2014-10-21
在线时间
49 小时
 楼主| 发表于 2014-12-1 15:20:38 | 显示全部楼层
[mw_shl_code=c,true]不好意思贴错了一段代码,修改如下:[/mw_shl_code] [mw_shl_code=c,true]void USART2_IRQHandler(void) 71 { //DMA unsigned char *tempPtr; unsigned short templen; if(USART2->SR&(1<<4))//空闲中断 { uart2Tmp = USART2->SR; uart2Tmp = USART2->DR; templen = get_DMA1ch6_reclen(); tempPtr = uart2.DMA_rxBuffer; DMA1CHANNEL6_DISABLE; DMA1->IFCR |= 7<<20;//清除DMA1通道6全局中断标志 DMA1_Channel6->CNDTR = UART_BUFFER_LENGTH;//接收数据长度 uart2.rxPtr=uart2.rxBuffer; while(templen--) { uart2.rxPtr++= *tempPtr++; DMA1CHANNEL6_ENABLE; } } } [/mw_shl_code]

回复

使用道具 举报

12

主题

85

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
437
金钱
437
注册时间
2014-10-21
在线时间
49 小时
 楼主| 发表于 2014-12-1 15:22:20 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
看了论坛好多帖子了,还是百思不得其解。请求各位大侠帮忙
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2014-12-1 15:31:53 | 显示全部楼层
回复【4楼】lionmon:
---------------------------------
我也没用过DMA接收,你再研究下吧。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

1

主题

80

帖子

0

精华

初级会员

Rank: 2

积分
104
金钱
104
注册时间
2014-11-26
在线时间
0 小时
发表于 2014-12-1 15:48:30 | 显示全部楼层
看看丢失的是哪个地方的数据。如果是最前面的,应该就是DMA启动前就丢失了,应该检查DMA启动触发部分。如果是最后面的丢失,应该是数据帧中有间隙停顿。这类通讯就不适合用空闲中断。如果是帧中间丢字节,就是疑难杂症了。用DMA接收空闲确实不好弄,不利于程序的稳定,健壮,要走的更远,还是用通用方案吧。
回复

使用道具 举报

12

主题

85

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
437
金钱
437
注册时间
2014-10-21
在线时间
49 小时
 楼主| 发表于 2014-12-1 16:18:02 | 显示全部楼层
回复【6楼】好人:
---------------------------------
我用的串口2,接收蓝牙发送来的数据,用手点击发送200字节数据,接受正常,但是每50ms发送就会丢失数据
我在仔细看下是丢失的哪部分数据
回复

使用道具 举报

12

主题

85

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
437
金钱
437
注册时间
2014-10-21
在线时间
49 小时
 楼主| 发表于 2014-12-2 08:57:57 | 显示全部楼层
大侠。。。。。。
回复

使用道具 举报

8

主题

76

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
264
金钱
264
注册时间
2013-9-5
在线时间
31 小时
发表于 2015-7-5 14:01:03 | 显示全部楼层
记号一个,学习
回复

使用道具 举报

12

主题

85

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
437
金钱
437
注册时间
2014-10-21
在线时间
49 小时
 楼主| 发表于 2015-7-6 09:34:13 | 显示全部楼层
回复【10楼】kuanglf:
---------------------------------
谢谢哈!学习了
回复

使用道具 举报

8

主题

76

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
264
金钱
264
注册时间
2013-9-5
在线时间
31 小时
发表于 2015-7-6 18:09:09 | 显示全部楼层
回复【11楼】lionmon:
---------------------------------
向你学习,没你的贴子,我根本无从下手。
回复

使用道具 举报

12

主题

85

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
437
金钱
437
注册时间
2014-10-21
在线时间
49 小时
 楼主| 发表于 2015-7-7 15:40:35 | 显示全部楼层
回复【12楼】kuanglf:
---------------------------------
我还没有仔细研究你的代码呢,太忙了没有时间,有时间在仔细研读!大家一起学习!
回复

使用道具 举报

7

主题

34

帖子

0

精华

初级会员

Rank: 2

积分
88
金钱
88
注册时间
2014-12-30
在线时间
1 小时
发表于 2015-7-30 16:50:50 | 显示全部楼层
高手啊!这个太有用了!学习了!
回复

使用道具 举报

12

主题

43

帖子

0

精华

初级会员

Rank: 2

积分
148
金钱
148
注册时间
2014-10-28
在线时间
8 小时
发表于 2015-9-7 17:26:03 | 显示全部楼层
MARK,学习一下。。
回复

使用道具 举报

1

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
136
金钱
136
注册时间
2016-1-18
在线时间
45 小时
发表于 2016-4-11 20:21:19 | 显示全部楼层
解决了吗?
回复

使用道具 举报

2

主题

474

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6509
金钱
6509
注册时间
2018-6-27
在线时间
549 小时
发表于 2019-9-25 18:44:46 | 显示全部楼层
学习学习,学习学习。
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-10 20:25

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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