#include "includes.h" #include #include #include /** * Bootload 串口使用情况 * UART0 没有使用 * UART2 用与调试信息输出 - 512000 * UART1 用于Bootload 升级使用 * */ UART_t g_uart; //目前该项目只使用串口2 进行双向通讯 MULIT_t m_send; void UARTx_Init(UART_IDX uart_id, Uart_prt prt_cf) { switch(uart_id){ case UART_1: memset(&g_uart,0,sizeof(UART_t)); memset(&m_send,0,sizeof(MULIT_t)); //串口1-RX接收中断,用于串口1的通讯总线繁忙状态判断,2025-04-16 // GPIO_PullHigh_Init(GPIOA0,15); // GPIO_IntGroup_Set(PA0,15,Selete_EXI_PIN15); //EXI0 set PB0.2 // GPIOA0_EXI_Init(EXI15); //PB0.2 as input // EXTI_trigger_CMD(ENABLE,EXI_PIN15,_EXIFT); //ENABLE falling edge // EXTI_trigger_CMD(ENABLE,EXI_PIN15,_EXIRT); // EXTI_interrupt_CMD(ENABLE,EXI_PIN15); //enable EXI // GPIO_EXTI_interrupt(GPIOA0,0b1000000000000000); //enable GPIOB02 as EXI // EXI4_Int_Enable(); // // UART1_DeInit(); //clear all UART Register // UART_IO_Init(IO_UART1,2); //use PA0.13->RXD1, PB0.0->TXD1 // UARTInitRxTxIntEn(UART1,20000,UART_PAR_NONE); //baudrate=sysclock 48M/20000=2400 tx rx int enabled // UART1_Int_Enable(); // // m_send.BusState_Tick = SysTick_1ms; // m_send.HighBit_Flag = 0x01; // // g_uart.RecvTimeout = Recv_2400_TimeOut; // g_uart.processing_cf = prt_cf; // // //485使能引脚初始化 // GPIO_Init(GPIOA0,UART485_DR_PIN,Output); // GPIO_DriveStrength_EN(GPIOA0,UART485_DR_PIN); // WRITE_LOW_DR; break; case UART_2: //2026-02-06 使用串口2作为Bootload 升级使用 memset(&g_uart,0,sizeof(UART_t)); memset(&m_send,0,sizeof(MULIT_t)); //串口RX接收中断 GPIO_PullHigh_Init(GPIOB0,5); GPIO_IntGroup_Set(PB0,5,Selete_EXI_PIN5); //EXI0 set PB0.5 GPIOB0_EXI_Init(EXI5); //PB0.5 as input EXTI_trigger_CMD(ENABLE,EXI_PIN5,_EXIFT); //ENABLE falling edge EXTI_trigger_CMD(ENABLE,EXI_PIN5,_EXIRT); EXTI_interrupt_CMD(ENABLE,EXI_PIN5); //enable EXI GPIO_EXTI_interrupt(GPIOB0,0b0000000000100000); //enable GPIOB05 as EXI EXI3_Int_Enable(); //EXI4~EXI9 INT Vector UART2_DeInit(); //clear all UART Register UART_IO_Init(IO_UART2,2); //use PA0.13->RXD1, PB0.0->TXD1 UARTInitRxTxIntEn(UART2,20000,UART_PAR_NONE); //baudrate=sysclock 48M/416=115200 tx rx int enabled UART2_Int_Enable(); m_send.BusState_Tick = SysTick_1ms; m_send.HighBit_Flag = 0x01; g_uart.RecvTimeout = Recv_2400_TimeOut; g_uart.processing_cf = prt_cf; //485使能引脚初始化 GPIO_Init(GPIOB0,3,Output); GPIO_DriveStrength_EN(GPIOB0,3); WRITE_LOW_DR; break; } } /******************************************************************************* * Function Name : Get_Uart_BaudCnt * Description : Uart 获取串口波特率对于设置值 *******************************************************************************/ U16_T Get_Uart_BaudCnt(U32_T baud) { switch(baud){ case 2400: return 20000; case 4800: return 10000; case 9600: return 5000; case 19200: return 2621; case 56000: return 898; case 115200: return 416; case 512000: return 98; } return 0x00; } /******************************************************************************* * Function Name : Get_Uart_Recv_Timeout * Description : Uart 获取串口接收超时时间 *******************************************************************************/ U32_T Get_Uart_Recv_Timeout(U32_T baud) { switch(baud){ case 2400: return Recv_2400_TimeOut; case 4800: return Recv_2400_TimeOut; case 9600: return Recv_9600_TimeOut; case 19200: return Recv_9600_TimeOut; case 56000: return Recv_9600_TimeOut; case 115200: return Recv_115200_TimeOut; case 512000: return Recv_115200_TimeOut; } return Recv_115200_TimeOut; } /******************************************************************************* * Function Name : UARTx_ChangeBaud * Description : Uart 切换串口波特率 *******************************************************************************/ U8_T UARTx_ChangeBaud(uint8_t uart_id,uint32_t baud) { U16_T set_para = Get_Uart_BaudCnt(baud); if(set_para == 0x00) return 0x01; //设置的波特率不支持 switch(uart_id){ case UART_1: #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS, "UART ID %d", uart_id); Dbg_Println(DBG_BIT_SYS_STATUS,"UART baud %d",baud); #endif UARTClose(UART1); UART1_Int_Disable(); UART1_DeInit(); //clear all UART Register UART_IO_Init(IO_UART1,2); //use PA0.13->RXD1, PB0.0->TXD1 UARTInitRxTxIntEn(UART1,set_para,UART_PAR_NONE); //baudrate=sysclock 48M/416=115200 tx rx int enabled UART1_Int_Enable(); g_uart.RecvTimeout = Get_Uart_Recv_Timeout(baud); break; case UART_2: UARTClose(UART2); UART2_Int_Disable(); UART2_DeInit(); //clear all UART Register UART_IO_Init(IO_UART2,2); //use PA0.13->RXD1, PB0.0->TXD1 UARTInitRxTxIntEn(UART2,set_para,UART_PAR_NONE); //baudrate=sysclock 48M/416=115200 tx rx int enabled UART2_Int_Enable(); g_uart.RecvTimeout = Get_Uart_Recv_Timeout(baud); break; } } /******************************************************************************* * Function Name : UART1_RecvINT_Processing * Description : 串口1 接收中断处理函数 - 接收中断调用 *******************************************************************************/ //void UART1_RecvINT_Processing(char data){ // if((g_uart.RecvLen + 1) >= USART_BUFFER_SIZE) g_uart.RecvLen = 0; // g_uart.RecvBuffer[g_uart.RecvLen++] = (U8_T)data; // // g_uart.RecvIdleTiming = SysTick_1ms; // g_uart.Receiving = 0x01; //} // // //void UART1_TASK(void){ // U8_T ret = 0x00; // if(g_uart.Receiving == 0x01){ // if(SysTick_1ms - g_uart.RecvIdleTiming > g_uart.RecvTimeout){ // // SYSCON_Int_Disable(); // g_uart.RecvIdleTiming = SysTick_1ms; // memcpy(g_uart.DealBuffer,g_uart.RecvBuffer,g_uart.RecvLen); // g_uart.DealLen = g_uart.RecvLen; // g_uart.RecvLen = 0; // g_uart.Receiving = 0; // SYSCON_Int_Enable(); // //#if DBG_LOG_EN // Dbg_Println(DBG_BIT_SYS_STATUS, "UART recv Len %d", g_uart.DealLen); // Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"UART buff",g_uart.DealBuffer,g_uart.DealLen); //#endif // // if(g_uart.processing_cf != NULL){ // ret = g_uart.processing_cf(g_uart.DealBuffer,g_uart.DealLen); // } // // } // } //} /******************************************************************************* * Function Name : UART2_RecvINT_Processing * Description : 串口2 接收中断处理函数 - 接收中断调用 *******************************************************************************/ void UART2_RecvINT_Processing(char data){ if((g_uart.RecvLen + 1) >= USART_BUFFER_SIZE) g_uart.RecvLen = 0; g_uart.RecvBuffer[g_uart.RecvLen++] = (U8_T)data; g_uart.RecvIdleTiming = SysTick_1ms; g_uart.Receiving = 0x01; } void UART2_TASK(void){ U8_T ret = 0x00; if(g_uart.Receiving == 0x01){ if(SysTick_1ms - g_uart.RecvIdleTiming > g_uart.RecvTimeout){ SYSCON_Int_Disable(); g_uart.RecvIdleTiming = SysTick_1ms; memcpy(g_uart.DealBuffer,g_uart.RecvBuffer,g_uart.RecvLen); g_uart.DealLen = g_uart.RecvLen; g_uart.RecvLen = 0; g_uart.Receiving = 0; SYSCON_Int_Enable(); #if DBG_LOG_EN Dbg_Println(DBG_BIT_SYS_STATUS, "UART recv Len %d", g_uart.DealLen); Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"UART buff",g_uart.DealBuffer,g_uart.DealLen); #endif if(g_uart.processing_cf != NULL){ ret = g_uart.processing_cf(g_uart.DealBuffer,g_uart.DealLen); } } } } /*因为开启了UART_TX_DONE_S 中断,发送完成需要清楚该中断标志位,因此每次调用串口输出后,需调用该函数,否则会在中断出不来 * 已取消 * */ void UART_Waiting_For_Send(CSP_UART_T *uart){ unsigned int Dataval = 0,delay_cnt = 0; do{ Dataval = CSP_UART_GET_ISR(uart); Dataval = Dataval & UART_TX_DONE_S; delay_cnt ++; if(delay_cnt >= 50000){ break; } }while(Dataval == 0x00); //发送完成 uart->ISR=UART_TX_DONE_S; } volatile int RS485_Comm_Flag = 0,RS485_Comm_Start = 0,RS485_Comm_End = 0,RS485_Comming = 0; void MCU485_SendData(U8_T *buff,U16_T len){ unsigned int Dataval = 0,delay_cnt = 0; //等待通讯发送完成 while(RS485_Comming == 0x01){ delay_nus(100); delay_cnt ++; if(delay_cnt >= 100){ break; } REVERISE_DR;//GPIO_Reverse(GPIOB0,3); } WRITE_HIGH_DR;//GPIO_Write_High(GPIOB0,3); RS485_Comm_Flag = 0x01; RS485_Comm_Start = 0x00; RS485_Comm_End = 0x00; UARTTransmit(UART2,buff,len); do{ delay_nus(100); delay_cnt ++; if(delay_cnt >= 100){ break; } }while((RS485_Comm_Start < len) || (RS485_Comm_End < len)); //发送完成 WRITE_LOW_DR;//GPIO_Write_Low(GPIOB0,3); RS485_Comm_Flag = 0x00; } /********************************************************** * @brief BUS485 数据发生函数 - 检测总线是否繁忙,空闲状态下,才发生数据;繁忙状态下,直接退出 * @retval None * */ U8_T BUS485_Send(U8_T *buff,U16_T len) { unsigned int Dataval = 0,delay_cnt = 0; //等待通讯发送完成 while(RS485_Comming == 0x01){ delay_nus(100); delay_cnt ++; if(delay_cnt >= 100){ break; } REVERISE_DR;//GPIO_Reverse(GPIOB0,3); } if(m_send.BusState_Flag == UART_BUSIDLE){ //总线空闲 CK_CPU_DisAllNormalIrq(); WRITE_HIGH_DR;//GPIO_Write_High(GPIOB0,3); RS485_Comm_Flag = 0x01; RS485_Comm_Start = 0x00; RS485_Comm_End = 0x00; m_send.BusState_Flag = UART_BUSBUSY;//发送前总线置位繁忙 m_send.BUSBUSY_LOCK = 0x01; //锁定总线状态 CK_CPU_EnAllNormalIrq(); UARTTransmit(UART2,buff,len); do{ delay_nus(100); delay_cnt ++; if(delay_cnt >= 100){ break; } }while((RS485_Comm_Start < len) || (RS485_Comm_End < len)); //发送完成 CK_CPU_DisAllNormalIrq(); WRITE_LOW_DR;//GPIO_Write_Low(GPIOB0,3); RS485_Comm_Flag = 0x00; m_send.BusState_Tick = SysTick_1ms; m_send.BUSBUSY_LOCK = 0x00; //解锁总线状态 CK_CPU_EnAllNormalIrq(); return UART_BUSIDLE; //发送成功 } else{ //总线繁忙 return UART_BUSBUSY; //发送失败 } return 0x02; //传入状态无效 } /********************************************************** * @brief 重发、数据有效期、超时发送判断,2025-03-25 * buff:发送数据 * len:数据长度 * DatSd:发送标记,0x00:无发送,0x01:有数据发送 * * @retval 0x00:发送成功 0x01:等待发送 0x02:数据无效 * */ U8_T MultSend_Task(U8_T *buff,U16_T len,U8_T DatSd) { if( (len == 0)||(len > USART_BUFFER_SIZE) ) return LEN_ERR; if(DatSd == 0x01) { if( m_send.ResendCnt < m_send.TotalCnt) //判断数据是否还在有效期,是否还有发送次数 { if(SysTick_1ms - m_send.BusbusyTimeout < m_send.DataValid_Time) { if( (m_send.ResendCnt == 0x00) || (SysTick_1ms - m_send.ASend_Tick >= m_send.DataWait_Time) ){//数据发送间隔 if(BUS485_Send(buff,len) == UART_BUSIDLE){ //发送数据 m_send.ASend_Tick = SysTick_1ms; m_send.ResendCnt++; #if DBG_LOG_EN Dbg_Println(DBG_BIT_Debug_STATUS,"SendCnt:%d success",m_send.ResendCnt); #endif return BUSSEND_SUCC;//数据发送成功 } } }else{ #if DBG_LOG_EN Dbg_Println(DBG_BIT_Debug_STATUS,"data end"); #endif return DATA_END;//数据有效期结束 } }else{ #if DBG_LOG_EN Dbg_Println(DBG_BIT_Debug_STATUS,"retry end,%d",m_send.ResendCnt ); #endif return RETRY_END;//没有重发次数 } } return BUSSEND_WAIT;//等待 } /********************************************************** * @brief 设置发送标志、组包、选择数据有效期档位,2025-03-25 * data: 发送数据 * sled: 数据长度 * SCnt: 设置数据发送次数 * indate: 设置数据有效期 * tim_val: 发送时间间隔 * @retval None * */ void Set_GroupSend(U8_T *data,U16_T sled,U8_T SCnt,U32_T indate,U32_T tim_val) { if((sled == 0x00)|| (sled > USART_BUFFER_SIZE)) return; memset(m_send.SendBuffer,0, USART_BUFFER_SIZE); memcpy(m_send.SendBuffer,data,sled); m_send.SendLen = sled; m_send.DataValid_Time = indate;//数据有效期 m_send.TotalCnt = SCnt; //数据发送次数 m_send.DataWait_Time = tim_val;//发送数据间隔 m_send.ASend_Flag = 0x01; m_send.ResendCnt = 0x00; m_send.BusbusyTimeout = SysTick_1ms; } //清除发送标志 //void Clear_SendFlag(void) //{ // m_send.ASend_Flag = 0x00; //} void BUS485_SetBaud(U32_T baud) { m_send.SetBaudFlag = 0x01; m_send.SetBaud = baud; } /********************************************************** * @brief 检测总线空闲,在While(1)里调用 2025-03-25 * @retval None * */ void BUS485Send_Task(void) //2025-03-29 { U8_T ret = 0xFF; //空闲等待 if(m_send.ASend_Flag == 0x01)//初始化发送 { ret = MultSend_Task(m_send.SendBuffer,m_send.SendLen,m_send.ASend_Flag); if( (ret == DATA_END)||(ret == RETRY_END) )//判断发送数据是否有效 { #if DBG_LOG_EN Dbg_Println(DBG_BIT_Debug_STATUS,"send end"); #endif m_send.ASend_Flag = 0x00; /*设置波特率*/ if( m_send.SetBaudFlag == 0x01 ){ UARTx_ChangeBaud(UART_2,m_send.SetBaud); m_send.SetBaudFlag = 0x00; m_send.SetBaud = 0x00; } } } } /********************************************************** * @brief 检测总线空闲,在定时器中断里调用 * @retval None * */ void BusIdle_Task(void) { if(m_send.BusState_Flag != UART_BUSIDLE && m_send.BUSBUSY_LOCK != 0x01) { CK_CPU_DisAllNormalIrq(); if( ( m_send.HighBit_Flag == 0x01 )&&( ( SysTick_1ms - m_send.BusState_Tick ) >= ( g_uart.RecvTimeout + m_send.Bus_DelayTime )) ) { m_send.BusState_Flag = UART_BUSIDLE; } CK_CPU_EnAllNormalIrq(); } } /******************************************************************* * @brief 检测总线繁忙,在串口接收RX引脚的外部中断服务函数里调用 * @retval None * */ void BusBusy_Task(void) { CK_CPU_DisAllNormalIrq(); m_send.BusState_Flag = UART_BUSBUSY; m_send.BusState_Tick = SysTick_1ms; m_send.Bus_DelayTime = (SysTick_1ms - m_send.ASend_Tick)%10;//随机延时 if(READ_RXLEVEL_STATE == 0x01){ m_send.HighBit_Flag = 0x01; //高电平标志置位 }else if(READ_RXLEVEL_STATE == 0x00){ m_send.HighBit_Flag = 0x00; //低电平 } CK_CPU_EnAllNormalIrq(); } /*调试信息输出接口*/ U32_T Dbg_Switch = (DBG_OPT_Debug_STATUS << DBG_BIT_Debug_STATUS) + (DBG_OPT_DEVICE_STATUS << DBG_BIT_DEVICE_STATUS) + (DBG_OPT_SYS_STATUS << DBG_BIT_SYS_STATUS); #if DBG_LOG_EN char Dbg_Buffer[512] = {0}; U32_T SysTick_Now = 0, SysTick_Last = 0, SysTick_Diff = 0; #endif void Dbg_Print(int DbgOptBit, const char *cmd, ...){ #if DBG_LOG_EN U16_T str_offset = 0; if (Dbg_Switch & (1 << DbgOptBit)) { SysTick_Now = SysTick_1ms; SysTick_Diff = SysTick_Now - SysTick_Last; //上一次打印时间差 SysTick_Last = SysTick_Now; str_offset = snprintf(Dbg_Buffer, sizeof(Dbg_Buffer),"%8d [%6d]: ", SysTick_Now, SysTick_Diff); DBG_Printf((U8_T *)Dbg_Buffer,str_offset); va_list args; //定义一个va_list类型的变量,用来储存单个参数 va_start(args, cmd); //使args指向可变参数的第一个参数 str_offset = vsnprintf(Dbg_Buffer, sizeof(Dbg_Buffer) ,cmd, args); //必须用vprintf等带V的 va_end(args); //结束可变参数的获取 DBG_Printf((U8_T *)Dbg_Buffer,str_offset); } #endif } void Dbg_Println(int DbgOptBit, const char *cmd, ...){ #if DBG_LOG_EN U16_T str_offset = 0; if (Dbg_Switch & (1 << DbgOptBit)) { SysTick_Now = SysTick_1ms; SysTick_Diff = SysTick_Now - SysTick_Last; //上一次打印时间差 SysTick_Last = SysTick_Now; str_offset = snprintf(Dbg_Buffer, sizeof(Dbg_Buffer) , "%8ld [%6ld]: ", SysTick_Now, SysTick_Diff); DBG_Printf((U8_T *)Dbg_Buffer,str_offset); va_list args; //定义一个va_list类型的变量,用来储存单个参数 va_start(args, cmd); //使args指向可变参数的第一个参数 str_offset = vsnprintf(Dbg_Buffer, sizeof(Dbg_Buffer) ,cmd, args); //必须用vprintf等带V的 va_end(args); //结束可变参数的获取 DBG_Printf((U8_T *)Dbg_Buffer,str_offset); DBG_Printf((U8_T *)"\r\n",2); } #endif } void Dbg_Print_Buff(int DbgOptBit, const char *cmd, U8_T *buff,U16_T len){ #if DBG_LOG_EN U16_T str_offset = 0; if (Dbg_Switch & (1 << DbgOptBit)) { SysTick_Now = SysTick_1ms; SysTick_Diff = SysTick_Now - SysTick_Last; //上一次打印时间差 SysTick_Last = SysTick_Now; str_offset = snprintf(Dbg_Buffer, sizeof(Dbg_Buffer) , "%8ld [%6ld]:%s ", SysTick_Now, SysTick_Diff,cmd); DBG_Printf((U8_T *)Dbg_Buffer,str_offset); for (uint32_t i = 0; i < len; i++) { SYSCON_IWDCNT_Reload(); str_offset = snprintf(Dbg_Buffer, sizeof(Dbg_Buffer) , "%02X ", buff[i]); DBG_Printf((U8_T *)Dbg_Buffer,str_offset); } DBG_Printf((U8_T *)"\r\n",2); } #endif }