×
单片机 > 单片机程序设计 > 详情

STM32 USART DMA未知长度的数据接收转发

发布时间:2020-08-27 发布时间:
|

今天终于实现了,未知长度的数据,串口1接收上位机的指令,串口2转发指令给模块,再接收模块数据通过串口2发送出去。整个串口的收发由DMA完成,运用串口总线空闲中断,这个真的是STM32的内部很好的一个东东,不消耗CPU资源。


  憋了我两天了,日思夜想,主要因为我对整个的逻辑开始没认真分析。



下面贴上部分我修改的程序,配置都是参考以上的,上面的写得非常详细,非常推荐看一下。


 在定义这一块修改了一下:


#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实现了此功能,比老版本的库方便了许多。

关键字:STM32  USART  DMA  未知长度  数据接收转发 


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
基于AT91M42800A的LED显示系统设计