串口通过DMA发送一帧数据时总是缺少2个字节,且最后一个字节数据为0xff的原因及解决方法
本次记录为采用485串口发送数据,发送模式是循环检测串口数据寄存器为空(TXE)和发送完成标志位(TC)。DMA发送串口方式
按照以上程序编译运行时,发现装置每次发送一帧报文都不完整,总是缺少2个字节且最后一个字节为0xff。
根据本人的猜想,应该是数据还没来及发送出去就使能了485接收,导致数据发送不完整,随后又上网查看了类型问题,终于查到说进入DMA发送完成中断以后,还要延时2-4ms等待串口数据完全发送出去才使能485接收。按照以上的结论修改了DMA发送完成中断函数,如下
原文链接:https://blog.csdn.net/more_thinking/article/details/108575952
DMA发送完成中断处理
在其中加入延时函数
/********************************************************************
* name : DMA1_Channel7_IRQHandler
* description :
* Input :
* Output : 无
* Return :
********************************************************************/
void DMA1_Channel7_IRQHandler(void)
{
if(DMA_GetFlagStatus(DMA1_FLAG_TC7))
{
delaydma1_flag_tc7_ms(2);
DMA_ClearFlag(DMA1_FLAG_TC7); //清除全部中断标志
DMA_ClearFlag(DMA1_FLAG_GL7);// 清除DMA1的通道4的所有中断标志,因为只有发送完成标志,所以直接全部清除
USART_ClearFlag(USART1,USART_FLAG_TC);// 在关中断前先清中断标志,防止是串口上一个数据发送时的中断标志
USART_ITConfig(USART1, USART_IT_TC, ENABLE);// DMA1传输完成后使能Usart1发送完成中断
D_RS485DE_RE = DISABLE;//重新使能串口接收
}
}
DMA发送部分程序
打开485发送使能
D_RS485DE_RE = ENABLE;
void Write_Lcd_Mem(uint16_t addr, uint16_t *pBuffer, uint8_t len)
{
#ifdef DMA_SEND
uint8_t i;
rt_enter_critical();
Usartx_SendData(USART2, D_DGUS_FRAME_HEAD1);
Usartx_SendData(USART2, D_DGUS_FRAME_HEAD2);
Usartx_SendData(USART2, 2 * len + 3);
Usartx_SendData(USART2, 0x82);
Usartx_SendData(USART2, addr >> 8);
Usartx_SendData(USART2, addr & 0xff);
for(i = 0; i < len; i++)
{
Usartx_SendData(USART2, *(pBuffer + i) >> 8);
Usartx_SendData(USART2, *(pBuffer + i) & 0xff);
}
#ifdef D_PC_SEND
Usartx_SendData(USART2, D_DGUS_FRAME_END1);
Usartx_SendData(USART2, D_DGUS_FRAME_END2);
#endif
rt_thread_delay(50);//
rt_exit_critical();
#endif
uint8_t i;
D_RS485DE_RE = ENABLE;
g_aUSART2_TX_BUF[0] = D_DGUS_FRAME_HEAD1;
g_aUSART2_TX_BUF[1] = D_DGUS_FRAME_HEAD2;
g_aUSART2_TX_BUF[2] = 2 * len + 3;
g_aUSART2_TX_BUF[3] = 0x82;
g_aUSART2_TX_BUF[4] = addr >> 8;
g_aUSART2_TX_BUF[5] = addr & 0xff;
for(i = 0; i < len; i++)
{
g_aUSART2_TX_BUF[2 * len + 3 + i] = *(pBuffer + i) >> 8;
g_aUSART2_TX_BUF[2 * len + 3 + i] = *(pBuffer + i) & 0xff;
}
#ifdef D_PC_SEND
g_aUSART2_TX_BUF[2 * len + 5] = D_DGUS_FRAME_END1;
g_aUSART2_TX_BUF[2 * len + 6] = D_DGUS_FRAME_END2;
#endif
Usart2_TX_DMA_Enable( 2 * len + 7);
rt_thread_delay(50);
}
经测试 协议发送完整