STM32中485采用串口DMA发送,切换收发状态问题 您所在的位置:网站首页 stm32如何配置DMA STM32中485采用串口DMA发送,切换收发状态问题

STM32中485采用串口DMA发送,切换收发状态问题

2024-07-16 03:28| 来源: 网络整理| 查看: 265

参考网上分享:https://www.amobbs.com/thread-5535672-2-1.html

RS485使用DMA发送,切换收发状态,有以下几种实现方式:

开启DMA的“发送完成中断”,在DMA的发送完成中断中,切换收发的状态。但是,这会导致最后的2个字节发送不出去,这是因为:DMA的“发送完成中断”出现在刚发送倒数第二个字节的起始位置,这个时候切换485的收发,若接收端不是奇校验的话 将会误收到0xFF 最后第一肯定也出不去。 网上提供的解决办法是:①在DMA的TC中断里面 加大于两个字节的延时 这是OK的。 ②在DMA的TC中断里面 开启USART的“发送完成中断” 去USART的中断里面去处理 这是OK的。看数据手册,可以利用串口的“发送完成中断TC”实现。开启USART的DMA,开启DMA传输通道,开启USART的“发送完成中断TC” 具体实现:

配置USART和DMA ,DMA中断不用开。 准备发送的时候,

切换为485发送 RS485EN_TX();-配置好DMA。传输的数据,与长度。开启USART的传输完成TC中断使能DMA =======等串口TC中断就行。中断服务函数中,失能TC 切换485接收。

开始传输:

//-----尝试不开启DMA TC中断 直接直观传输 void USART2_SendMsg(INT8U *msg,INT8U len) { SET_RS485_SEND; //高发送 DMA_ClearFlag(DMA1_FLAG_TC7); //清DMA发送完成标志 USART_ClearITPendingBit(USART2,USART_IT_TC); DMA_Cmd(DMA1_Channel7, DISABLE); //停止DMA DMA1_Channel7->CMAR = (INT32U) msg; //源地址 DMA1_Channel7->CNDTR = len;//重设传输长度 USART_ITConfig(USART2,USART_IT_TC,ENABLE); DMA_Cmd(DMA1_Channel7, ENABLE); //启动DMA }

传输完成后:

void USART2_IRQHandler(void) { /* ................... */ if(0x00000040 & (USART2->SR))//(USART_GetITStatus(USART2,USART_IT_TC)) { USART2->SR &= ~0x00000040;//USART_ClearITPendingBit(USART2,USART_IT_TC); OSSemPost(Sem_Usart2Send); SET_RS485_RECV; //发送完毕 改成接收状态 USART2->CR1 &= ~0x00000040;//USART_ITConfig(USART2,USART_IT_TC,DISABLE); //OSIntExit(); return; } /* ................... */ }

这里说一下,我由于使用的时候,在发送的时候没有“清除发送完成标志”,导致传输第一个字节后,就进入了TC中断,切换了485状态。 代码:

RS485EN_TX(); //485切换为发送模式 __HAL_UART_DISABLE_IT(&UART3_Handler,USART_IT_RXNE); /* 禁止接收中断 */ __HAL_UART_ENABLE_IT(&UART3_Handler,USART_IT_TC); /* 使能发送完成中断 */ if(__HAL_DMA_GET_FLAG(&UART3TxDMA_Handler,DMA_FLAG_TCIF3_7)) //等待传输完成 { __HAL_DMA_CLEAR_FLAG(&UART3TxDMA_Handler,DMA_FLAG_TCIF3_7);//清除DMA1_Steam3传输完成标志 HAL_UART_DMAStop(&UART3_Handler); //传输完成以后关闭串口DMA }

时序: 在这里插入图片描述 修改后,在前面添加清除发送完成标志TC”后,既可以。 代码:

RS485EN_TX(); //485切换为发送模式 __HAL_UART_CLEAR_FLAG(&UART3_Handler,UART_FLAG_TC); if(__HAL_DMA_GET_FLAG(&UART3TxDMA_Handler,DMA_FLAG_TCIF3_7)) //等待传输完成 { __HAL_DMA_CLEAR_FLAG(&UART3TxDMA_Handler,DMA_FLAG_TCIF3_7);//清除DMA1_Steam3传输完成标志 HAL_UART_DMAStop(&UART3_Handler); //传输完成以后关闭串口DMA } __HAL_UART_DISABLE_IT(&UART3_Handler,USART_IT_RXNE); /* 禁止接收中断 */ __HAL_UART_ENABLE_IT(&UART3_Handler,USART_IT_TC); /* 使能发送完成中断 */ MYDMA_USART_Transmit(&UART3_Handler,(u8*)USART3_TX_BUF,DRIVER_FRAME_LENGTH); //启动传输

传输完成后:

//串口3中断服务程序 void USART3_IRQHandler(void) { uint8_t Res=0; uint16_t u16CheckCrcTemp = 0; if((__HAL_UART_GET_FLAG(&UART3_Handler,UART_FLAG_TC)!=RESET)) { __HAL_UART_CLEAR_FLAG(&UART3_Handler,UART_FLAG_TC); RS485EN_RX(); __HAL_UART_ENABLE_IT(&UART3_Handler,USART_IT_RXNE); __HAL_UART_DISABLE_IT(&UART3_Handler,USART_IT_TC); } if((__HAL_UART_GET_FLAG(&UART3_Handler,UART_FLAG_RXNE)!=RESET)) { __HAL_UART_CLEAR_FLAG(&UART3_Handler,UART_FLAG_RXNE); Res = USART3->DR; g_us485AlarmCnt=0; //485通信5s报警检测 if(USART3_RX_STA & 0x4000) { ++USART3_RX_STA; USART3_RX_BUF[USART3_RX_STA & 0xfff] = Res; if((USART3_RX_STA & 0xfff) == DRIVER_FRAME_LENGTH-1) //接收帧尾 { u16CheckCrcTemp = *(uint16_t*)(USART3_RX_BUF + DRIVER_FRAME_LENGTH - 2); if(u16CheckCrcTemp == crc_16((unsigned char *)USART3_RX_BUF,DRIVER_FRAME_LENGTH-2)) { if(USART3_RX_BUF[2]==0xff || USART3_RX_BUF[2]==g_ulaGdBuf[INDEX_ID]) //是否是正确的ID { run_driver_cmd(); } } USART3_RX_STA = 0; } } else if(USART3_RX_STA & 0x8000) //接收一帧数据的第二个数据 ---0xef 2017.1.13 { if(Res != 0xfb) USART3_RX_STA = 0; else { USART3_RX_BUF[(++USART3_RX_STA)&0xfff] = Res; USART3_RX_STA |= 0x4000; } } else if(Res == 0xbf) //接收一帧数据的第一个数据 ---0xfb 2017.1.13 { USART3_RX_BUF[USART3_RX_STA & 0xfff] = Res; USART3_RX_STA |= 0x8000; } } }

时序为: 在这里插入图片描述



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有