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

参考网上分享: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;            
        }	
    }
} 

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

  • 11
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: stm32f103作为一款常见的嵌入式控制器,具备丰富的外设使其在工业自动化、通讯和控制等领域有着广泛的应用。其,rs485串口通讯作为一种支持多节点通讯的标准,也是工业现场通讯应用的常见方式。而如何通过stm32f103实现rs485通讯,则需要借助于其dma功能来完成。 stm32f103内置的dma控制器,能够支持硬件直接存储器访问。由于rs485串口通讯需要在传输过程不断地交替进行发送和接收操作,而dma控制器能够通过设置传输方向和源地址等参数,在不同的传输状态下自动完成数据的传输。因此,在实现stm32f103与rs485串口通讯时,可以使用dma控制器来提高传输效率和稳定性。 需要注意的是,在实现stm32f103与rs485通讯时,除了使用dma控制器完成数据传输,还需要考虑缓存数据的存储、校验和处理、适当的数据传输速率等问题。因此,需要在程序设计过程进行合理的策略选择和参数配置,以提高通讯效率和可靠性。 总之,通过充分发挥stm32f103的dma功能,我们可以实现高效、稳定的rs485串口通讯,提高工业现场的自动化控制和通讯效率。 ### 回答2: STM32F103是一款ARM Cortex-M3内核的单片机,支持RS485通讯协议。为了提高通讯效率和稳定性,可以使用DMA进行数据收发DMA是直接内存访问技术,可以将传输数据的过程交给DMA控制器,从而减轻CPU的负担,提高系统的性能。在STM32F103,可以使用USART1、USART2和USART3作为RS485的通讯接口,DMA控制器可以与这些接口进行配合,实现数据的高效传输。 在使用DMA进行RS485通讯时,需要配置相关的寄存器,包括DMA控制器的寄存器、USART接口的寄存器等。为了保证数据的安全性和稳定性,需要对数据流控制进行合理的配置,并加入错误校验机制。 总之,在STM32F103上使用RS485通讯协议,可以通过DMA技术实现快速、稳定和可靠的数据收发。需要注意选择合适的USART接口,并对DMA控制器和相关寄存器进行正确的配置和编程。 ### 回答3: STM32F103是一款由STMicroelectronics公司推出的32位微控制器,它集成了丰富的外设和功能模块,可广泛应用于各种控制、通信和数据处理领域。其,RS485总线接口是STM32F103常用的通信接口之一,它可以实现高速、长距离的数据传输,并且具有抗干扰能力强、抗噪声能力强等优点。 在使用STM32F103进行RS485通信时,可以利用DMA(Direct Memory Access)引擎提高数据传输效率和代码运行效率。DMA是一种硬件机制,可以直接访问系统内存和外设寄存器,无需CPU的干预,从而提高数据传输速率和系统响应速度。通过使用DMA,可以实现RS485收发缓冲区自动映射,减少CPU的负担和数据传输的延迟,提高系统的稳定性和可靠性。 具体实现上,可以使用STM32F103的内置DMA控制器,将RS485的数据收发缓冲区映射为内存块,通过设置DMA传输方向、数据长度、传输模式和断处理方式等参数,实现RS485数据的DMA收发。在RS485数据收发过程,可以通过设置DMA传输完成断和RS485数据传输完成断来进行数据处理和错误处理等操作,从而实现更加稳定、高效和可靠的RS485通信。 总之,STM32F103在RS485通信DMA收发应用,可以提高数据传输效率和代码运行效率,降低CPU负担及数据传输延迟,从而提高系统稳定性和可靠性,同时也为实现更加高效、可靠的通信模式提供了重要技术支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值