STM32 USART DMA

来源:互联网 发布:baidu软件 编辑:程序博客网 时间:2024/05/02 22:14

  今天终于实现了,串口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<DATA_LEN;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<DATA_LEN;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);


}


原创粉丝点击