stm32h750 RS485收发问题

    最近在对h750板子上的485串口进行收发功能测试的时候,遇到的一个问题,特地记录一下。

    由于对板子上的485引脚做了特殊处理,在通过Tx引脚发送报文的时候,Rx也会收到Tx发送出去的报文,触发接收中断,所以我的报文发送逻辑是:发送N个字节时,只主动发送第一个字节,然后在接收中断中判断接收到的字节和我发送的字节是否一致,如果一致则继续发送下一个字节,不一致则发送失败,退出发送。

     一开始使用的是野火的485例程,使用hal库的接口进行字节的收发和接收中断处理

中断使能

    /* 配置抢占优先级的分组 */
    HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);
    /*中断设置,抢占优先级0,子优先级为0*/
    HAL_NVIC_SetPriority(USART6_IRQn, 0,0);
    HAL_NVIC_EnableIRQ(USART6_IRQn);
    /*配置串口接收中断 */
    __HAL_UART_ENABLE_IT(&Uart6_Handle,UART_IT_RXNE);
    __HAL_UART_ENABLE_IT(&Uart6_Handle,USART_IT_ERR);
    __HAL_UART_ENABLE_IT(&Uart6_Handle,UART_IT_PE);

发送

    if(BSP_RS485_TxState != RS485_TX_ING)
    {
        BSP_RS485_BusFreeCount = 0;
        Enter_485Tx();

        p = RS485_Tx_Buf;
        for(i=0; i

接收中断

    if(__HAL_UART_GET_IT(&Uart6_Handle,USART_IT_ORE)!=RESET) {
        __HAL_UART_CLEAR_OREFLAG(&Uart6_Handle);
    }

    if((__HAL_UART_GET_FLAG(&Uart6_Handle,UART_FLAG_RXNE)!=RESET))
    {
        HAL_UART_Receive(&Uart6_Handle, (uint8_t *)(&temp),1, 1000);
        BSP_RS485_BusFreeCount = 0;

        USART_RX_vect(temp);
    }
	else if(__HAL_UART_GET_FLAG(&Uart6_Handle,USART_IT_TC)!=RESET)
	{
		__HAL_UART_CLEAR_IT( &Uart6_Handle, USART_IT_TC );
	}
	else
	{
		 HAL_UART_Receive(&Uart6_Handle, (uint8_t *)(&temp),1, 1000);
		
	}
	 __HAL_UART_CLEAR_OREFLAG(&Uart6_Handle);
    if(__HAL_UART_GET_FLAG(&Uart6_Handle, USART_FLAG_NE) != RESET)
    {
        __HAL_UART_CLEAR_NEFLAG(&Uart6_Handle);
    }




    if(__HAL_UART_GET_FLAG(&Uart6_Handle, USART_FLAG_FE) != RESET)
    {
        __HAL_UART_CLEAR_FEFLAG(&Uart6_Handle);
    }


    if(__HAL_UART_GET_FLAG(&Uart6_Handle, USART_FLAG_PE) != RESET)
    {
        __HAL_UART_CLEAR_PEFLAG(&Uart6_Handle);
    }

接收中断中发送处理

        if(c != Tx_Last)
        {   //发送的同接收的不一致,退出发送
            _485_RX_EN();
            BSP_RS485_TxState = RS485_TX_FAIL;
        } else
        {   //发送下一个
            if(--TxLen>0)
            {
                Tx_Last = *pTx;
                ch=*pTx++;
				RS485_UART->TDR=ch;
            } else
            {
                Enter_485Rx();
                BSP_RS485_TxState = RS485_TX_SUCCESS;
            }
        }

在实际使用过程中,发现虽然也能正常的进行收发,但是时不时会在接收中断的发送处理函数出现问题,经常出现发送的字节和接收中断收到的字节不一致的问题,导致报文发送失败,并且一旦出现这种情况,接收中断就会失效,再也无法触发。后来想的办法是在发生错误时重新初始化串口,这样又能继续收发了,但是这种方式治标不治本,还是无法解决报文频繁发送失败的问题。

        if(c != Tx_Last)
        {   //发送的同接收的不一致,退出发送
			BSP_RS485_Init(19200);
            BSP_RS485_TxState = RS485_TX_FAIL;
        }

最后,参考了安富莱的485例程,不调用hal库接口,而是直接对寄存器进行操作。

中断使能

SET_BIT(RS485_UART->ICR, USART_ICR_TCCF);	/* 清除TC发送完成标志 */
SET_BIT(RS485_UART->RQR, USART_RQR_RXFRQ);  /* 清除RXNE接收标志 */
SET_BIT(RS485_UART->CR1, USART_CR1_RXNEIE);	/* 使能PE. RX接受中断 */

发送接收

RS485_UART->TDR=Tx_Last;//发送
temp = READ_REG(RS485_UART->RDR);//接收

接收中断

 volatile UNS8 temp;
	uint32_t isrflags   = READ_REG(RS485_UART->ISR);
	uint32_t cr1its     = READ_REG(RS485_UART->CR1);
	uint32_t cr3its     = READ_REG(RS485_UART->CR3);
	
		/* 处理接收中断  */
	if ((isrflags & USART_ISR_RXNE_RXFNE) != RESET)
	{
		temp = READ_REG(RS485_UART->RDR);
		BSP_RS485_BusFreeCount = 0;
		USART_RX_vect(temp);
	}
	if ( ((isrflags & USART_ISR_TXE_TXFNF) != RESET) && (cr1its & USART_CR1_TXEIE) != RESET)
	{
		CLEAR_BIT(RS485_UART->CR1, USART_CR1_TXEIE);
	}
	if (((isrflags & USART_ISR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
	{
		CLEAR_BIT(RS485_UART->CR1, USART_CR1_TCIE);
	}
	
		/* 清除中断标志 */
	SET_BIT(RS485_UART->ICR, UART_CLEAR_PEF);
	SET_BIT(RS485_UART->ICR, UART_CLEAR_FEF);
	SET_BIT(RS485_UART->ICR, UART_CLEAR_NEF);
	SET_BIT(RS485_UART->ICR, UART_CLEAR_OREF);
	SET_BIT(RS485_UART->ICR, UART_CLEAR_IDLEF);
	SET_BIT(RS485_UART->ICR, UART_CLEAR_TCF);
	SET_BIT(RS485_UART->ICR, UART_CLEAR_LBDF);
	SET_BIT(RS485_UART->ICR, UART_CLEAR_CTSF);
	SET_BIT(RS485_UART->ICR, UART_CLEAR_CMF);
	SET_BIT(RS485_UART->ICR, UART_CLEAR_WUF);
	SET_BIT(RS485_UART->ICR, UART_CLEAR_TXFECF);

     改成寄存器版后,错误基本不再出现,两个版本的差异在于接收中断中对于中断信号的处理,野火基本只处理了接收中断,其他中断都没怎么处理,一开始直接hal库的HAL_UART_IRQHandler(&Uart6_Handle);接口让其自行处理,发现没啥用后我才按照网上其他人的说法多加了几个中断处理。不过仍然无法彻底解决问题。另外就是收发接口的不同,HAL_UART_Receive和HAL_UART_Transmit接口会进行不少操作,不知道会不会出现问题。而安富莱的例程是直接操作寄存器,且对中断信号做了不少处理。

    至于到底是和原因导致的错误,时间有限,没空去进行验证了,反正先用第二种方法进行485的收发完成项目再说。

你可能感兴趣的:(stm32h750 RS485收发问题)