历史上的今天
今天是:2025年01月07日(星期二)
2019年01月07日 | STM32 USART DMA未知长度的数据接收转发
2019-01-07 来源:eefocus
今天终于实现了,未知长度的数据,串口1接收上位机的指令,串口2转发指令给模块,再接收模块数据通过串口2发送出去。整个串口的收发由DMA完成,运用串口总线空闲中断,这个真的是STM32的内部很好的一个东东,不消耗CPU资源。
憋了我两天了,日思夜想,主要因为我对整个的逻辑开始没认真分析。
程序参考部分http://www.amobbs.com/forum.php?mod=viewthread&tid=5486343&highlight=STM32%E5%AE%9E%E7%8E%B0USART%2BDMA%E6%8E%A5%E6%94%B6%E6%9C%AA%E7%9F%A5%E9%95%BF%E5%BA%A6%E7%9A%84%E6%95%B0%E6%8D%AE%E5%92%8C%E5%8F%91%E9%80%81
下面贴上部分我修改的程序,配置都是参考以上的,上面的写得非常详细,非常推荐看一下。
在定义这一块修改了一下:
#define SENDBUFF_SIZE 10240
vu8 USART1_SEND_DATA[SENDBUFF_SIZE]; //512
vu8 USART2_SEND_DATA[SENDBUFF_SIZE]; //512
vu8 USART1_RECEIVE_DATA[SENDBUFF_SIZE]; //512
vu8 USART2_RECEIVE_DATA[SENDBUFF_SIZE]; //512
vu8 USART1_TX_Finish=1;// USART1发送完成标志量
vu8 USART2_TX_Finish=1; // USART2发送完成标志量
在DMA的配置里面
DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;//512
中断里面:
串口1中断
void USART1_IRQHandler(void)
{
u16 DATA_LEN;
u16 i;
if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)//如果为空闲总线中断
{
DMA_Cmd(DMA1_Channel5, DISABLE);//关闭DMA,防止处理其间有数据
//USART_RX_STA = USART1->SR;//先读SR,然后读DR才能清除
//USART_RX_STA = USART1->DR;
DATA_LEN=SENDBUFF_SIZE-DMA_GetCurrDataCounter(DMA1_Channel5);
if(DATA_LEN > 0)
{
while(USART2_TX_Finish==0)//等待数据传输完成才下一次
{
;
}
//将数据送DMA存储地址
for(i=0;i { USART2_SEND_DATA[i]=USART1_RECEIVE_DATA[i]; } //USART用DMA传输替代查询方式发送,克服被高优先级中断而产生丢帧现象。 DMA_Cmd(DMA1_Channel7, DISABLE); //改变datasize前先要禁止通道工作 DMA1_Channel7->CNDTR=DATA_LEN; //DMA1,传输数据量 USART2_TX_Finish=0; DMA_Cmd(DMA1_Channel7, ENABLE); } //DMA_Cmd(DMA1_Channel5, DISABLE);//关闭DMA,防止处理其间有数据 DMA_ClearFlag(DMA1_FLAG_GL5 | DMA1_FLAG_TC5 | DMA1_FLAG_TE5 | DMA1_FLAG_HT5);//清标志 DMA1_Channel5->CNDTR = SENDBUFF_SIZE;//重装填 512 DMA_Cmd(DMA1_Channel5, ENABLE);//处理完,重开DMA //读SR后读DR清除Idle i = USART1->SR; i = USART1->DR; } if(USART_GetITStatus(USART1, USART_IT_PE | USART_IT_FE | USART_IT_NE) != RESET)//出错 { USART_ClearITPendingBit(USART1, USART_IT_PE | USART_IT_FE | USART_IT_NE); } USART_ClearITPendingBit(USART1, USART_IT_TC); USART_ClearITPendingBit(USART1, USART_IT_IDLE); } 串口2中断 void USART2_IRQHandler(void) { u16 DATA_LEN; u16 i; if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET) //如果为空闲总线中断 { DMA_Cmd(DMA1_Channel6, DISABLE);//关闭DMA,防止处理其间有数据 //USART_RX_STA = USART1->SR;//先读SR,然后读DR才能清除 //USART_RX_STA = USART1->DR; DATA_LEN=SENDBUFF_SIZE-DMA_GetCurrDataCounter(DMA1_Channel6); if(DATA_LEN > 0) { while(USART1_TX_Finish==0)//等待数据完成才下一次 { ; } //将数据送DMA存储地址 for(i=0;i { USART1_SEND_DATA[i]=USART2_RECEIVE_DATA[i]; } //USART用DMA传输替代查询方式发送,克服被高优先级中断而产生丢帧现象。 DMA_Cmd(DMA1_Channel4, DISABLE); //改变datasize前先要禁止通道工作 DMA1_Channel4->CNDTR=DATA_LEN; //DMA1,传输数据量 USART1_TX_Finish=0; DMA_Cmd(DMA1_Channel4, ENABLE); } //DMA_Cmd(DMA1_Channel5, DISABLE);//关闭DMA,防止处理其间有数据 DMA_ClearFlag(DMA1_FLAG_GL6 | DMA1_FLAG_TC6 | DMA1_FLAG_TE6 | DMA1_FLAG_HT6);//清标志 DMA1_Channel6->CNDTR = SENDBUFF_SIZE;//重装填 512 DMA_Cmd(DMA1_Channel6, ENABLE);//处理完,重开DMA //读SR后读DR清除Idle i = USART2->SR; i = USART2->DR; } if(USART_GetITStatus(USART2, USART_IT_PE | USART_IT_FE | USART_IT_NE) != RESET)//出错 { USART_ClearITPendingBit(USART2, USART_IT_PE | USART_IT_FE | USART_IT_NE); } USART_ClearITPendingBit(USART2, USART_IT_TC); USART_ClearITPendingBit(USART2, USART_IT_IDLE); } 最近在CUBE实现了此功能,比老版本的库方便了许多。
史海拾趣
|
485总线稳定性解决方法 一、关于485 总线的几个概念: 1、485 总线的通讯距离可以达到1200 米。 根据485 总线结构理论,在理想环境的前提下,485 总线传输距离可以达到1200 米。其条件是通讯线材优质达标,波特率为9600,只负载一台485 设备,才 ...… 查看全部问答> |
|
如何通过Tornado自带的TCL命令实现对当前工程的编译? 问题:如何通过Tornado自带的TCL命令实现对当前工程的编译,不借助Tornado界面中所提供的编译操作,生成.o和.out文件。 实际上Tornado界面功能好像也是通过TCL命令来实现的,关键本人对TCL命令这块不太熟悉,有请大侠们指教。 … 查看全部问答> |
|
本帖最后由 paulhyde 于 2014-9-15 09:20 编辑 求拉杠天线匹配网络,拉杠天线长约一米,直径70mm左右...... … 查看全部问答> |
|
最近想接触一下Stellaris ,正好在汇总论坛的帖子,顺便看看以前的帖子,学习了很多。 突然想到以前学习一款单片机的时候,第一件事都是找这个单片机的书。然后我去各个网上商店, ...… 查看全部问答> |
|
Msp430 LaunchPad 与LCD1602的接口问题 本人是初学者,我最近也得到了msp430 Launchpad 这块板子,请问怎样能实现这块板子与LCD1602的连接啊,我要把AD转换的结果从LCD1602来显示。请高手指点一下。谢谢… 查看全部问答> |




