/* * 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 /* Bootload 中规划两个串口 * 1、调试串口 - 串口1 * 2、主动端口 - 串口2 * - 这两个串口有串口升级功能, */ UART_t g_uart_1; UART_t g_uart_2; 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_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 1 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); 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_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 1 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_1,0,sizeof(UART_t)); Set_Uart_recvTimeout(&g_uart_1,buad); g_uart_1.send_data_cf = MCU485_SendString_1; g_uart_1.set_baud_cf = UART1_ChangeBaud; break; case UART_2: //RS485通讯引脚 GPIOB_ModeCfg(GPIO_Pin_15, GPIO_ModeOut_PP); //RS485引脚初始化 - 主动端口 RS485 使能引脚 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_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 1 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_2,0,sizeof(UART_t)); g_uart_2.CommBaud = buad; Set_Uart_recvTimeout(&g_uart_2,buad); g_uart_2.send_data_cf = MCU485_SendString_2; g_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_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 1 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); 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: 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_1.RecvLen + 1) >= USART_BUFFER_SIZE ) g_uart_1.RecvLen = 0x00; g_uart_1.RecvBuffer[g_uart_1.RecvLen] = UART1_RecvByte(); g_uart_1.RecvLen += 1; g_uart_1.Receiving = 0x01; g_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_2.RecvLen + 1) >= USART_BUFFER_SIZE ) g_uart_2.RecvLen = 0x00; g_uart_2.RecvBuffer[g_uart_2.RecvLen] = UART2_RecvByte(); g_uart_2.RecvLen += 1; g_uart_2.Receiving = 0x01; g_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: break; } } /********************************************************************* * @fn USART1_RECEIVE * * @brief USART1 * * @return none */ void UART0_RECEIVE(void) { if(g_uart_0.Receiving == 0x01) { if(SysTick_1ms - g_uart_0.RecvIdleTiming >= g_uart_0.RecvTimeout) { g_uart_0.RecvIdleTiming = SysTick_1ms; DBG_SYS_Printf("UART0_RECEIVE"); Launcher_Uart_Upgrade_Process(&g_uart_0); g_uart_0.RecvLen = 0; g_uart_0.Receiving = 0; } } } /********************************************************************* * @fn USART1_RECEIVE * * @brief USART1 * * @return none */ void UART1_RECEIVE(void) { if(g_uart_1.Receiving == 0x01) { if(SysTick_1ms - g_uart_1.RecvIdleTiming >= g_uart_1.RecvTimeout) { g_uart_1.RecvIdleTiming = SysTick_1ms; DBG_SYS_Printf("UART1_RECEIVE"); Launcher_Uart_Upgrade_Process(&g_uart_1); g_uart_1.RecvLen = 0; g_uart_1.Receiving = 0; } } } /********************************************************************* * @fn UART2_RECEIVE * * @brief USART2 * * @return none */ void UART2_RECEIVE(void) { if(g_uart_2.Receiving == 1) { if(SysTick_1ms - g_uart_2.RecvIdleTiming > g_uart_2.RecvTimeout) { g_uart_2.RecvIdleTiming = SysTick_1ms; DBG_SYS_Printf("UART2_RECEIVE"); Launcher_Uart_Upgrade_Process(&g_uart_2); g_uart_2.RecvLen = 0; g_uart_2.Receiving = 0; } } } /********************************************************************* * @fn USART3_RECEIVE * * @brief UART3 * * @return none */ void UART3_RECEIVE(void) { } /********************************************************************* * @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_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_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( UART1_GetLinSTA() & RB_LSR_TX_ALL_EMP ) { /*发送为空*/ __disable_irq(); NVIC_DisableIRQ(UART1_IRQn); 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_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 1 bytes R8_UART1_LCR = RB_LCR_WORD_SZ; R8_UART1_IER = RB_IER_TXD_EN; UART1_CLR_RXFIFO(); UART1_CLR_TXFIFO(); UART1_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_THR_EMPTY); NVIC_EnableIRQ(UART1_IRQn); Set_Uart_recvTimeout(&g_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; DBG_SYS_Printf("%s - %d",__func__,baudrate); while(1) { if( UART2_GetLinSTA() & RB_LSR_TX_ALL_EMP ) { /*发送为空*/ __disable_irq(); NVIC_DisableIRQ(UART2_IRQn); 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_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 1 bytes R8_UART2_LCR = RB_LCR_WORD_SZ; R8_UART2_IER = RB_IER_TXD_EN; UART2_CLR_RXFIFO(); UART2_CLR_TXFIFO(); UART2_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_THR_EMPTY); NVIC_EnableIRQ(UART2_IRQn); Set_Uart_recvTimeout(&g_uart_2,baudrate); __enable_irq(); DBG_SYS_Printf("%s - SUCC",__func__); 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( UART3_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_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 1 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_0(uint8_t *buff, uint16_t len) { uint32_t delay_num = 0; 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; } return 0x00; } uint8_t MCU485_SendString_1(uint8_t *buff, uint16_t len) { uint32_t delay_num = 0; UART1_SendString(buff,len); //等待发送完成 - 50ms while(1) { if((R8_UART1_LSR & RB_LSR_TX_ALL_EMP)) break; Delay_Us(1); delay_num++; if(delay_num > 50000) break; } 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 : * uart_info:对应串口数据 buff:发送数据 len:发送数据长度 sendCount :发送次数 ValidDuration :数据有效时间,单位:ms sendInterval :发送间隔时间,单位:ms *******************************************************************************/ uint8_t Uartx_Add_Data_To_SendBuff( UART_t *uart_info, uint8_t *buff, uint16_t len, uint8_t sendCount, uint32_t ValidDuration, uint32_t sendInterval) { if( uart_info == NULL ) return 0x01; if( buff == NULL ) return 0x01; if( len > USART_BUFFER_SIZE ) return 0x02; memset(uart_info->SendBuffer,0,USART_BUFFER_SIZE); memcpy(uart_info->SendBuffer,buff,len); uart_info->SendLen = len; uart_info->SendCount = sendCount; uart_info->SendCnt = 0; uart_info->SendValidDuration = ValidDuration; uart_info->SendInterval = sendInterval; uart_info->SendValidTick = SysTick_1ms; return 0x00; } /******************************************************************************* * Function Name : Uart0_Clear_SendBuff * Description : Uart0 清除发送缓冲区,同时取消发送 *******************************************************************************/ uint8_t Uartx_Clear_SendBuff(UART_t *uart_info) { if( uart_info == NULL ) return 0x01; memset(uart_info->SendBuffer,0,USART_BUFFER_SIZE); uart_info->SendLen = 0x00; return 0x00; } /******************************************************************************* * Function Name : Uart0_Avoid_Conflict_Send_Task * Description : Uart0 避免冲突 - 发送数据 *******************************************************************************/ uint8_t Uartx_Avoid_Conflict_Send_Task(UART_t *uart_info) { if( uart_info == NULL ) return 0x01; if( (uart_info->SendLen == 0x00) || (uart_info->SendLen > USART_BUFFER_SIZE) ) return 0x01; if( uart_info->SendCnt >= uart_info->SendCount ) { //发送次数,达到上限,不进行数据发送 uart_info->SendLen = 0x00; return 0x02; } if( SysTick_1ms - uart_info->SendValidTick >= uart_info->SendInterval ){ //数据已过有效期,便不在进行数据发送 uart_info->SendLen = 0x00; return 0x03; } if( uart_info->CommBusy != UART_COMMBUSY_IDLE_Flag ) return 0x04; //通讯处于繁忙状态 //数据发送 if( ( uart_info->SendCnt == 0x00 ) || ( SysTick_1ms - uart_info->SendTick >= uart_info->SendInterval ) ) { __disable_irq(); //关闭全局中断 uart_info->CommBusy |= UART_COMMBUSY_SEND_Flag; uart_info->SendIdleTick = SysTick_1ms; __enable_irq(); //开启全局中断 if( uart_info->send_data_cf != NULL ){ uart_info->send_data_cf(uart_info->SendBuffer, uart_info->SendLen); } uart_info->SendTick = SysTick_1ms; uart_info->SendCnt++; if( uart_info->SendCnt >= uart_info->SendCount ) { memset(uart_info->SendBuffer,0,USART_BUFFER_SIZE); uart_info->SendLen = 0x00; return 0x05; //通讯结束 } } return 0x00; } /******************************************************************************* * Function Name : Uartx_IDLE_State_Determination * Description : Uartx 空闲状态判断 *******************************************************************************/ void Uartx_IDLE_State_Determination(UART_t *uart_info) { if( uart_info->CommBusy == UART_COMMBUSY_IDLE_Flag ) { /*当前处于总线空闲状态 - 可以进行切换波特率操作*/ if( uart_info->ChangeBaudFlag == 0x01 ) { uart_info->set_baud_cf(uart_info->CommBaud); uart_info->ChangeBaudFlag = 0x00; } }else { /*当前处于发送繁忙状态,等待总线空闲状态 - 判断使用超时时间与接收超时时间一致*/ if( ((uart_info->CommBusy & UART_COMMBUSY_SEND_Flag) != 0x00 ) && ( SysTick_1ms - uart_info->SendIdleTick >= uart_info->RecvTimeout ) ) { uart_info->SendIdleTick = SysTick_1ms; __disable_irq(); //关闭全局中断 uart_info->CommBusy &= ~(UART_COMMBUSY_SEND_Flag); uart_info->SendIdleTick = SysTick_1ms; __enable_irq(); //开启全局中断 } } } void Uart0_Task(void) { // UART0_RECEIVE(); // // Uartx_Avoid_Conflict_Send_Task(&g_uart_0); // // Uartx_IDLE_State_Determination(&g_uart_0); } void Uart1_Task(void) { UART1_RECEIVE(); Uartx_Avoid_Conflict_Send_Task(&g_uart_1); Uartx_IDLE_State_Determination(&g_uart_1); } void Uart2_Task(void) { UART2_RECEIVE(); Uartx_Avoid_Conflict_Send_Task(&g_uart_2); Uartx_IDLE_State_Determination(&g_uart_2); }