/* * uart.c * * Created on: May 14, 2025 * Author: cc * * 目前有两个 RS485口 * * Uart1 -> 调试串口 * Uart0 -> U1 -> RS485 1 * UART2 -> U2 -> RS485 2 * Uart3 -> U3 -> BUS * */ #include "includes.h" #include UART_t g_uart[UART_MAX]; void UART0_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); void UART1_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); void UART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); void UART3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); /********************************************************************* * @fn UARTx_Init * @brief UART初始化函数,注意串口2通讯引脚是PB22,PB23 - Boot,RST引脚 * @param uart_id - 串口ID * @param buad - 波特率 * @param prt_cf - 串口接收回调函数 * @return none */ void UARTx_Init(UART_IDX uart_id, uint32_t buad) { switch (uart_id) { case UART_0: //RS485通讯引脚 GPIOD_ModeCfg(GPIO_Pin_21, GPIO_ModeOut_PP); MCU485_EN1_L; UART0_Reset(); GPIO_PinRemapConfig(GPIO_NoRemap_UART0,ENABLE); GPIOB_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP); GPIOB_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_Floating); UART0_BaudRateCfg(buad); R8_UART0_FCR = RB_FCR_FIFO_TRIG | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 14 bytes R8_UART0_LCR = RB_LCR_WORD_SZ; R8_UART0_IER = RB_IER_TXD_EN; UART0_CLR_RXFIFO(); UART0_CLR_TXFIFO(); UART0_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_THR_EMPTY); NVIC_EnableIRQ(UART0_IRQn); memset(&g_uart[UART_0],0,sizeof(UART_t)); Set_Uart_recvTimeout(&g_uart[UART_0],buad); g_uart[UART_0].send_data_cf = UART0_SendString; g_uart[UART_0].set_baud_cf = UART0_ChangeBaud; break; case UART_1: UART1_Reset(); GPIO_PinRemapConfig(GPIO_NoRemap_UART1,ENABLE); GPIOB_ModeCfg(GPIO_Pin_11, GPIO_ModeOut_PP); GPIOB_ModeCfg(GPIO_Pin_10, GPIO_ModeIN_Floating); UART1_BaudRateCfg(buad); R8_UART1_FCR = RB_FCR_FIFO_TRIG | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 14 bytes R8_UART1_LCR = RB_LCR_WORD_SZ; R8_UART1_IER = RB_IER_TXD_EN; UART1_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_THR_EMPTY); NVIC_EnableIRQ(UART1_IRQn); memset(&g_uart[UART_1],0,sizeof(UART_t)); Set_Uart_recvTimeout(&g_uart[UART_1],buad); g_uart[UART_1].send_data_cf = UART1_SendString; g_uart[UART_1].set_baud_cf = UART1_ChangeBaud; break; case UART_2: //RS485通讯引脚 GPIOB_ModeCfg(GPIO_Pin_15, GPIO_ModeOut_PP); MCU485_EN2_L; UART2_Reset(); GPIO_PinRemapConfig(GPIO_PartialRemap1_UART2,ENABLE); GPIOB_ModeCfg(GPIO_Pin_14, GPIO_ModeOut_PP); GPIOB_ModeCfg(GPIO_Pin_12, GPIO_ModeIN_Floating); UART2_BaudRateCfg(buad); R8_UART2_FCR = RB_FCR_FIFO_TRIG | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 14 bytes R8_UART2_LCR = RB_LCR_WORD_SZ; R8_UART2_IER = RB_IER_TXD_EN; UART2_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_THR_EMPTY); NVIC_EnableIRQ(UART2_IRQn); memset(&g_uart[UART_2],0,sizeof(UART_t)); Set_Uart_recvTimeout(&g_uart[UART_2],buad); g_uart[UART_2].send_data_cf = UART2_SendString; g_uart[UART_2].set_baud_cf = UART2_ChangeBaud; break; case UART_3: UART3_Reset(); GPIO_PinRemapConfig(GPIO_PartialRemap1_UART3,ENABLE); GPIOB_ModeCfg(GPIO_Pin_19, GPIO_ModeOut_PP); GPIOB_ModeCfg(GPIO_Pin_18, GPIO_ModeIN_Floating); UART3_BaudRateCfg(buad); R8_UART3_FCR = RB_FCR_FIFO_TRIG | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 14 bytes R8_UART3_LCR = RB_LCR_WORD_SZ; R8_UART3_IER = RB_IER_TXD_EN; UART3_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_THR_EMPTY); NVIC_EnableIRQ(UART3_IRQn); memset(&g_uart[UART_3],0,sizeof(UART_t)); Set_Uart_recvTimeout(&g_uart[UART_3],buad); g_uart[UART_3].send_data_cf = UART3_SendString; g_uart[UART_3].set_baud_cf = UART3_ChangeBaud; break; } } void Set_Uart_recvTimeout(UART_t *set_uart,uint32_t baud) { if(baud == 115200) { set_uart->RecvTimeout = Recv_115200_TimeOut; }else if(baud == 9600) { set_uart->RecvTimeout = Recv_9600_TimeOut; }else if(baud == 2400) { set_uart->RecvTimeout = Recv_2400_TimeOut; }else if(baud == 512000) { set_uart->RecvTimeout = Recv_512000_TimeOut; }else { set_uart->RecvTimeout = 20; } } /********************************************************************* * @fn USART1_IRQHandler * * @brief USART1中断函数 * * @return none */ void UART0_IRQHandler(void) { switch( UART0_GetITFlag() ) { case UART_II_THR_EMPTY: break; case UART_II_RECV_RDY: case UART_II_RECV_TOUT: if( (g_uart[UART_0].RecvLen + 1) >= USART_BUFFER_SIZE ) g_uart[UART_0].RecvLen = 0x00; g_uart[UART_0].RecvBuffer[g_uart[UART_0].RecvLen] = UART0_RecvByte(); g_uart[UART_0].RecvLen += 1; g_uart[UART_0].Receiving = 0x01; g_uart[UART_0].RecvIdleTiming = SysTick_1ms; //当前处于繁忙状态 g_uart[UART_0].CommBusy |= UART_COMMBUSY_RECV_Flag; break; } } /********************************************************************* * @fn USART1_IRQHandler * * @brief USART1中断函数 * * @return none */ void UART1_IRQHandler(void) { switch( UART1_GetITFlag() ) { case UART_II_THR_EMPTY: break; case UART_II_RECV_RDY: case UART_II_RECV_TOUT: if( (g_uart[UART_1].RecvLen + 1) >= USART_BUFFER_SIZE ) g_uart[UART_1].RecvLen = 0x00; g_uart[UART_1].RecvBuffer[g_uart[UART_1].RecvLen] = UART1_RecvByte(); g_uart[UART_1].RecvLen += 1; g_uart[UART_1].Receiving = 0x01; g_uart[UART_1].RecvIdleTiming = SysTick_1ms; break; } } /********************************************************************* * @fn UART2_IRQHandler * * @brief USART2中断函数 * * @return none */ void UART2_IRQHandler(void) { switch( UART2_GetITFlag() ) { case UART_II_THR_EMPTY: break; case UART_II_RECV_RDY: case UART_II_RECV_TOUT: if( (g_uart[UART_2].RecvLen + 1) >= USART_BUFFER_SIZE ) g_uart[UART_2].RecvLen = 0x00; g_uart[UART_2].RecvBuffer[g_uart[UART_2].RecvLen] = UART2_RecvByte(); g_uart[UART_2].RecvLen += 1; g_uart[UART_2].Receiving = 0x01; g_uart[UART_2].RecvIdleTiming = SysTick_1ms; break; } } /********************************************************************* * @fn USART3_IRQHandler * * @brief USART3中断函数 * * @return none */ void UART3_IRQHandler(void) { switch( UART3_GetITFlag() ) { case UART_II_THR_EMPTY: break; case UART_II_RECV_RDY: case UART_II_RECV_TOUT: if( (g_uart[UART_3].RecvLen + 1) >= USART_BUFFER_SIZE ) g_uart[UART_3].RecvLen = 0x00; g_uart[UART_3].RecvBuffer[g_uart[UART_3].RecvLen] = UART3_RecvByte(); g_uart[UART_3].RecvLen += 1; g_uart[UART_3].Receiving = 0x01; g_uart[UART_3].RecvIdleTiming = SysTick_1ms; break; } } /********************************************************************* * @fn USART1_RECEIVE * * @brief USART1 * * @return none */ void UART0_RECEIVE(void) { if(g_uart[UART_0].Receiving == 0x01) { if(SysTick_1ms - g_uart[UART_0].RecvIdleTiming >= g_uart[UART_0].RecvTimeout) { g_uart[UART_0].RecvIdleTiming = SysTick_1ms; DBG_SYS_Printf("--UART0_RECEIVE--\r\n"); Launcher_Uart_Upgrade_Process(&g_uart[UART_0]); g_uart[UART_0].RecvLen = 0; g_uart[UART_0].Receiving = 0; } } } /********************************************************************* * @fn USART1_RECEIVE * * @brief USART1 * * @return none */ void UART1_RECEIVE(void) { if(g_uart[UART_1].Receiving == 0x01) { if(SysTick_1ms - g_uart[UART_1].RecvIdleTiming >= g_uart[UART_1].RecvTimeout) { g_uart[UART_1].RecvIdleTiming = SysTick_1ms; DBG_SYS_Printf("--UART1_RECEIVE--\r\n"); Launcher_Uart_Upgrade_Process(&g_uart[UART_1]); g_uart[UART_1].RecvLen = 0; g_uart[UART_1].Receiving = 0; } } } /********************************************************************* * @fn UART2_RECEIVE * * @brief USART2 * * @return none */ void UART2_RECEIVE(void) { if(g_uart[UART_2].Receiving == 1) { if(SysTick_1ms - g_uart[UART_2].RecvIdleTiming > g_uart[UART_2].RecvTimeout) { g_uart[UART_2].RecvIdleTiming = SysTick_1ms; DBG_SYS_Printf("--UART2_RECEIVE--\r\n"); Launcher_Uart_Upgrade_Process(&g_uart[UART_2]); g_uart[UART_2].RecvLen = 0; g_uart[UART_2].Receiving = 0; } } } /********************************************************************* * @fn USART3_RECEIVE * * @brief UART3 * * @return none */ void UART3_RECEIVE(void) { if(g_uart[UART_3].Receiving == 1) { if(SysTick_1ms - g_uart[UART_3].RecvIdleTiming > g_uart[UART_3].RecvTimeout) { g_uart[UART_3].RecvIdleTiming = SysTick_1ms; DBG_SYS_Printf("--UART3_RECEIVE--\r\n"); Launcher_Uart_Upgrade_Process(&g_uart[UART_3]); g_uart[UART_3].RecvLen = 0; g_uart[UART_3].Receiving = 0; } } } /********************************************************************* * @fn UART0_ChangeBaud * * @brief UART0切换波特率 * * @return none */ uint8_t UART0_ChangeBaud(uint32_t baudrate) { uint16_t delay_num = 0; while(1) { if( UART0_GetLinSTA() & RB_LSR_TX_ALL_EMP ) { /*发送为空*/ __disable_irq(); UART0_Reset(); GPIO_PinRemapConfig(GPIO_NoRemap_UART0,ENABLE); GPIOB_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP); GPIOB_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_Floating); UART0_BaudRateCfg(baudrate); R8_UART0_FCR = RB_FCR_FIFO_TRIG | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 14 bytes R8_UART0_LCR = RB_LCR_WORD_SZ; R8_UART0_IER = RB_IER_TXD_EN; UART0_CLR_RXFIFO(); UART0_CLR_TXFIFO(); UART0_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_THR_EMPTY); NVIC_EnableIRQ(UART0_IRQn); Set_Uart_recvTimeout(&g_uart[UART_0],baudrate); __enable_irq(); return 0; } Delay_Us(100); delay_num++; if(delay_num > 500) break; } return 1; } /********************************************************************* * @fn UART1_ChangeBaud * * @brief UART1切换波特率 * * @return none */ uint8_t UART1_ChangeBaud(uint32_t baudrate) { uint16_t delay_num = 0; while(1) { if( UART0_GetLinSTA() & RB_LSR_TX_ALL_EMP ) { /*发送为空*/ __disable_irq(); UART1_Reset(); GPIO_PinRemapConfig(GPIO_NoRemap_UART1,ENABLE); GPIOB_ModeCfg(GPIO_Pin_11, GPIO_ModeOut_PP); GPIOB_ModeCfg(GPIO_Pin_10, GPIO_ModeIN_Floating); UART1_BaudRateCfg(baudrate); R8_UART1_FCR = RB_FCR_FIFO_TRIG | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 14 bytes R8_UART1_LCR = RB_LCR_WORD_SZ; R8_UART1_IER = RB_IER_TXD_EN; UART1_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_THR_EMPTY); NVIC_EnableIRQ(UART1_IRQn); Set_Uart_recvTimeout(&g_uart[UART_1],baudrate); __enable_irq(); return 0; } Delay_Us(100); delay_num++; if(delay_num > 500) break; } return 1; } /********************************************************************* * @fn UART2_ChangeBaud * * @brief UART2切换波特率 * * @return none */ uint8_t UART2_ChangeBaud(uint32_t baudrate) { uint16_t delay_num = 0; while(1) { if( UART0_GetLinSTA() & RB_LSR_TX_ALL_EMP ) { /*发送为空*/ __disable_irq(); UART2_Reset(); GPIO_PinRemapConfig(GPIO_PartialRemap1_UART2,ENABLE); GPIOB_ModeCfg(GPIO_Pin_14, GPIO_ModeOut_PP); GPIOB_ModeCfg(GPIO_Pin_12, GPIO_ModeIN_Floating); UART2_BaudRateCfg(baudrate); R8_UART2_FCR = RB_FCR_FIFO_TRIG | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 14 bytes R8_UART2_LCR = RB_LCR_WORD_SZ; R8_UART2_IER = RB_IER_TXD_EN; UART2_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_THR_EMPTY); NVIC_EnableIRQ(UART2_IRQn); Set_Uart_recvTimeout(&g_uart[UART_2],baudrate); __enable_irq(); return 0; } Delay_Us(100); delay_num++; if(delay_num > 500) break; } return 1; } /********************************************************************* * @fn UART3_ChangeBaud * * @brief UART3切换波特率 * * @return none */ uint8_t UART3_ChangeBaud(uint32_t baudrate) { uint16_t delay_num = 0; while(1) { if( UART0_GetLinSTA() & RB_LSR_TX_ALL_EMP ) { /*发送为空*/ __disable_irq(); UART3_Reset(); GPIO_PinRemapConfig(GPIO_PartialRemap1_UART3,ENABLE); GPIOB_ModeCfg(GPIO_Pin_19, GPIO_ModeOut_PP); GPIOB_ModeCfg(GPIO_Pin_18, GPIO_ModeIN_Floating); UART3_BaudRateCfg(baudrate); R8_UART3_FCR = RB_FCR_FIFO_TRIG | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 14 bytes R8_UART3_LCR = RB_LCR_WORD_SZ; R8_UART3_IER = RB_IER_TXD_EN; UART3_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_THR_EMPTY); NVIC_EnableIRQ(UART3_IRQn); Set_Uart_recvTimeout(&g_uart[UART_3],baudrate); __enable_irq(); return 0; } Delay_Us(100); delay_num++; if(delay_num > 500) break; } return 1; } /* * RS485通讯避障检测 * 1、主动发送数据后,等待总线空闲(根据不同的波特率,等待时间不同),等待超时后,总线空闲 * 2、接收到数据后,等待数据接收完毕,总线为空闲状态 * 3、总线空闲可进行数据发送,总线繁忙,不可发送数据 * 4、数据发送需要在数据有效期内发送,每次数据需要发送前,需要记录当前时间,当超过数据有效期后,该数据便不在发送 * 5、在通讯发送完成后,切换通讯波特率 * * - 新增变量 * - 1、繁忙状态 * - 2、等待空闲时间戳 * - 3、发送数据有效时间 * * */ uint8_t MCU485_SendString_1(uint8_t *buff, uint16_t len) { uint32_t delay_num = 0; MCU485_EN1_H; UART0_SendString(buff,len); //等待发送完成 - 50ms while(1) { if((R8_UART0_LSR & RB_LSR_TX_ALL_EMP)) break; Delay_Us(1); delay_num++; if(delay_num > 50000) break; } MCU485_EN1_L; return 0x00; } uint8_t MCU485_SendString_2(uint8_t *buff, uint16_t len) { uint32_t delay_num = 0; MCU485_EN2_H; UART2_SendString(buff,len); //等待发送完成 - 50ms while(1) { if((R8_UART2_LSR & RB_LSR_TX_ALL_EMP)) break; Delay_Us(1); delay_num++; if(delay_num > 50000) break; } MCU485_EN2_L; return 0x00; } /******************************************************************************* * Function Name : Uart0_Add_Data_To_SendBuff * Description : Uart0 将数据填入发送缓冲区 * Input : buff:发送数据 len:发送数据长度 sendCount :发送次数 ValidDuration :数据有效时间,单位:ms sendInterval :发送间隔时间,单位:ms *******************************************************************************/ uint8_t Uart0_Add_Data_To_SendBuff(uint8_t *buff,uint16_t len,uint8_t sendCount,uint32_t ValidDuration,uint32_t sendInterval) { if( buff == NULL) return 0x01; if( len > USART_BUFFER_SIZE ) return 0x02; memset(g_uart[UART_0].SendBuffer,0,USART_BUFFER_SIZE); memcpy(g_uart[UART_0].SendBuffer,buff,len); g_uart[UART_0].SendLen = len; g_uart[UART_0].SendCount = sendCount; g_uart[UART_0].SendCnt = 0; g_uart[UART_0].SendValidDuration = ValidDuration; g_uart[UART_0].SendInterval = sendInterval; g_uart[UART_0].SendValidTick = SysTick_1ms; return 0x00; } /******************************************************************************* * Function Name : Uart0_Clear_SendBuff * Description : Uart0 清除发送缓冲区,同时取消发送 *******************************************************************************/ uint8_t Uart0_Clear_SendBuff(void) { memset(g_uart[UART_0].SendBuffer,0,USART_BUFFER_SIZE); g_uart[UART_0].SendLen = 0x00; return 0x00; } /******************************************************************************* * Function Name : Uart0_Avoid_Conflict_Send_Task * Description : Uart0 避免冲突 - 发送数据 *******************************************************************************/ uint8_t Uart0_Avoid_Conflict_Send_Task(void) { if( (g_uart[UART_0].SendLen == 0x00) || (g_uart[UART_0].SendLen > USART_BUFFER_SIZE) ) return 0x01; if( g_uart[UART_0].SendCnt >= g_uart[UART_0].SendCount ) { //发送次数,达到上限,不进行数据发送 g_uart[UART_0].SendLen = 0x00; return 0x02; } if( SysTick_1ms - g_uart[UART_0].SendValidTick >= g_uart[UART_0].SendInterval ){ //数据已过有效期,便不在进行数据发送 g_uart[UART_0].SendLen = 0x00; return 0x03; } if( g_uart[UART_0].CommBusy != UART_COMMBUSY_IDLE_Flag ) return 0x04; //通讯处于繁忙状态 //数据发送 if( ( g_uart[UART_0].SendCnt == 0x00 ) || ( SysTick_1ms - g_uart[UART_0].SendTick >= g_uart[UART_0].SendInterval ) ) { __disable_irq(); //关闭全局中断 g_uart[UART_0].CommBusy |= UART_COMMBUSY_SEND_Flag; g_uart[UART_0].SendIdleTick = SysTick_1ms; __enable_irq(); //开启全局中断 UART0_SendString(g_uart[UART_0].SendBuffer, g_uart[UART_0].SendLen); g_uart[UART_0].SendTick = SysTick_1ms; g_uart[UART_0].SendCnt++; if( g_uart[UART_0].SendCnt >= g_uart[UART_0].SendCount ) { memset(g_uart[UART_0].SendBuffer,0,USART_BUFFER_SIZE); g_uart[UART_0].SendLen = 0x00; return 0x05; //通讯结束 } } return 0x00; } void Uart0_Task(void) { UART0_RECEIVE(); Uart0_Avoid_Conflict_Send_Task(); if( g_uart[UART_0].CommBusy == UART_COMMBUSY_IDLE_Flag ) { /*当前处于总线空闲状态 - 可以进行切换波特率操作*/ if( g_uart[UART_0].ChangeBaudFlag == 0x01 ) { g_uart[UART_0].set_baud_cf(g_uart[UART_0].CommBaud); g_uart[UART_0].ChangeBaudFlag = 0x00; } }else { /*当前处于发送繁忙状态,等待总线空闲状态 - 判断使用超时时间与接收超时时间一致*/ if( ((g_uart[UART_0].CommBusy & UART_COMMBUSY_SEND_Flag) != 0x00 ) && ( SysTick_1ms - g_uart[UART_0].SendIdleTick >= g_uart[UART_0].RecvTimeout ) ) { g_uart[UART_0].SendIdleTick = SysTick_1ms; __disable_irq(); //关闭全局中断 g_uart[UART_0].CommBusy &= ~(UART_COMMBUSY_SEND_Flag); g_uart[UART_0].SendIdleTick = SysTick_1ms; __enable_irq(); //开启全局中断 } } }