今天终于实现了,未知长度的数据,串口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);
}