diff --git a/Project/HC32F460/MDK/HC32F460.uvoptx b/Project/HC32F460/MDK/HC32F460.uvoptx index bcc9096..c2bfcaf 100644 --- a/Project/HC32F460/MDK/HC32F460.uvoptx +++ b/Project/HC32F460/MDK/HC32F460.uvoptx @@ -145,7 +145,7 @@ 0 CMSIS_AGDI - -X"Any" -UAny -O206 -S9 -C0 -P00000000 -N00("") -D00(00000000) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO31 -FD1FFF8000 -FC1000 -FN2 -FF0HC32F460_512K.FLM -FS00 -FL080000 -FP0($$Device:HC32F460JETA$FlashARM\HC32F460_512K.FLM) -FF1HC32F460_otp.FLM -FS13000C00 -FL13FC -FP1($$Device:HC32F460JETA$FlashARM\HC32F460_otp.FLM) + -X"Any" -UAny -O206 -S9 -C0 -P00000000 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO31 -FD1FFF8000 -FC1000 -FN2 -FF0HC32F460_512K.FLM -FS00 -FL080000 -FP0($$Device:HC32F460JETA$FlashARM\HC32F460_512K.FLM) -FF1HC32F460_otp.FLM -FS13000C00 -FL13FC -FP1($$Device:HC32F460JETA$FlashARM\HC32F460_otp.FLM) 0 @@ -263,50 +263,30 @@ 21 1 - App.aaa,0x0A + App.ADTrack.LeftUpVPT,0x0A 22 1 - App.bbb,0x0A + App.ADTrack.LeftLowVPT,0x0A 23 1 - App.ccc,0x0A + App.ADTrack.RightUpVPT,0x0A 24 1 - App.ddd,0x0A + App.ADTrack.RightLowVPT,0x0A 25 1 - App.ADTrack.LeftUpVPT,0x0A - - - 26 - 1 - App.ADTrack.LeftLowVPT,0x0A - - - 27 - 1 - App.ADTrack.RightUpVPT,0x0A - - - 28 - 1 - App.ADTrack.RightLowVPT,0x0A - - - 29 - 1 App.ADTrack.Stop_VPT,0x0A - 30 + 26 1 App.MotorPara.Current_height,0x0A @@ -389,7 +369,7 @@ 0 1 - 0 + 1 0 0 0 diff --git a/Project/HC32F460/MDK/HC32F460.uvprojx b/Project/HC32F460/MDK/HC32F460.uvprojx index 8a765fa..d3a3ca2 100644 --- a/Project/HC32F460/MDK/HC32F460.uvprojx +++ b/Project/HC32F460/MDK/HC32F460.uvprojx @@ -338,7 +338,7 @@ 0 0 - + --multibyte_chars __DEBUG,HC32F460,USE_DEVICE_DRIVER_LIB,JEUA ..\..\..\mcu\common;..\source\User\Inc;..\source\User\Src;..\..\..\driver\src;..\..\..\driver\inc;..\source\Module\CS1237;..\source\Module\dc_motor;..\source\Module\BeepAndLed @@ -1026,7 +1026,7 @@ 0 0 - --diag_suppress=186,66 + --diag_suppress=186,66 --multibyte_chars HC32F460,USE_DEVICE_DRIVER_LIB ..\..\..\..\..\mcu\common;..\source;..\..\..\..\..\driver\inc;..\..\..\..\..\bsp\ev_hc32f460_lqfp100_v2 diff --git a/Project/HC32F460/source/User/Inc/Debug.h b/Project/HC32F460/source/User/Inc/Debug.h index 7c4ef94..69b942b 100644 --- a/Project/HC32F460/source/User/Inc/Debug.h +++ b/Project/HC32F460/source/User/Inc/Debug.h @@ -31,6 +31,10 @@ typedef struct{ DebugExec DBGExec; }DBGFunType; +/* 控制盒信息帧→复位→恢复 观测打印: ISR推事件, 主循环打印完整时间线(未知帧全记录用于捕捉过热报错) */ +void Uart3ErrLog_Push(uint8_t type, const uint8_t *pFrame, uint16_t height); /* type:0首次信息帧 1复位中回应 2复位完成 3未知帧 */ +void Uart3ErrLogLoopHandler(void); /* 主循环调用: 打印报错/复位事件 */ + void DebugUartIRQ(char Data); void DebugLoopHandler(void); void Dbg1msRoutine(void); @@ -38,8 +42,11 @@ void Dbg1msRoutine(void); #define DBG_LOG2(x, y) #define DBG_LOG(...) -#define DBG_LOG_F(fmt,arg...) -#define DBG_ARRAY(ARRAY,SIZE) +#define DBG_LOG_F(fmt,arg...) +#define DBG_ARRAY(ARRAY,SIZE) + +#define Uart3ErrLog_Push(type, pFrame, height) (0) +#define Uart3ErrLogLoopHandler() (0) #endif #endif diff --git a/Project/HC32F460/source/User/Inc/main.h b/Project/HC32F460/source/User/Inc/main.h index 8a48ae5..0dcefc4 100644 --- a/Project/HC32F460/source/User/Inc/main.h +++ b/Project/HC32F460/source/User/Inc/main.h @@ -33,8 +33,8 @@ #define PEAK 1430 //最高高度mm #define VALLEY 1000 //最低高度mm -/*高度转应力表索引: 补偿表431点覆盖1000~1430mm(430个步进), 接收范围已保证不越界*/ -#define HEIGHT_TO_IDX(h) ((h) - 1000) +/*高度转应力表索引: 补偿表431点覆盖1000~1430mm(430个步进), h<1000时钳位到0防止越界*/ +#define HEIGHT_TO_IDX(h) ((h) < 1000 ? 0 : ((h) - 1000)) #define BDC_STOP() (SET_TWIN_BIT0(),SET_TWIN_BIT1()) #define BDC_DOWN() (SET_TWIN_BIT0(),CLR_TWIN_BIT1()) @@ -76,6 +76,7 @@ typedef struct{ typedef struct{//电机参数 bool InitialFlag;//初始标志位 bool RestFlag; + bool OverheatFlag;//过热标志: 收到过热帧后置true, 持续下降触发控制盒复位 bool CaliFlag; bool LoopOne;//循环一次标志位 int16_t Current_height;//当前高度mm(控制盒上报1000~1430) @@ -150,6 +151,7 @@ typedef struct { uint32_t SlopeCollDelay1mSCnt; uint32_t CailUp1mSCnt; uint32_t HeightContRolCnt; + uint32_t RestStop1mSCnt;//复位停顿计时: 收到复位帧后先停止电机, 计时结束再下降触发复位 uint8_t FeedDogDlyCnt; bool CaliZeroFlag;//校零标志位 diff --git a/Project/HC32F460/source/User/Src/Debug.c b/Project/HC32F460/source/User/Src/Debug.c index 8273d5c..dd9c94d 100644 --- a/Project/HC32F460/source/User/Src/Debug.c +++ b/Project/HC32F460/source/User/Src/Debug.c @@ -400,6 +400,208 @@ const DBGFunType DebugFun[DEBUG_CMD_CNT] = { "wave", DBGWave_on_off, }; +/*========================================================================================= +* 函数名称: Uart3ErrLog_xxx +* 功能描述: 控制盒报错(01 04)→复位→恢复 观测打印。接收中断中仅推事件入环形缓冲(不打印), +* 由主循环Uart3ErrLogLoopHandler()统一打印, 完整呈现"触发报错→置复位标志→ +* 复位过程多包回应→复位完成恢复正常"的时间线。 +* 协议: 01 04 d2 d3 = 报错帧(d2/d3为错误码, 如过热); 01 01 h_hi h_lo = 高度帧(清除复位标志) +*=========================================================================================*/ +#define U3ERR_EVT_MAX 16 /* 事件缓冲条数 */ +#define U3ERR_STATUS_NUM 12 /* 主状态机状态个数 */ + +/* 事件类型 */ +#define U3ERR_T_FIRST 0 /* 首次信息帧(复位标志 0→1) */ +#define U3ERR_T_REPLY 1 /* 复位中回应信息帧(复位标志已置位) */ +#define U3ERR_T_DONE 2 /* 复位完成(收到高度帧, 复位标志 1→0) */ +#define U3ERR_T_UNKNOWN 3 /* 未知帧(非高度/信息帧, 用于捕捉过热等其它报错) */ + +typedef struct{ + uint8_t Type; /* 事件类型 */ + uint8_t Bits; /* BIT0/BIT1 输出电平(bit0/bit1) */ + uint8_t Status; /* 事件时刻主状态机状态 */ + uint8_t Frame[4]; /* 原始4字节帧 */ + uint16_t Height; /* type2: 高度帧数值(mm) */ + uint16_t Repeat; /* 连发合并的重复包数(不含首包) */ + uint32_t Tick; /* 事件时刻(ms, 上电起) */ +}U3ErrEvt_t; + +/* 连发合并状态: 相同帧500ms内只计数不重复入队, 防止过热帧持续广播刷爆缓冲 */ +static uint8_t m_U3ErrLastType = 0xFF; /* 上一帧类型(0xFF=无) */ +static uint8_t m_U3ErrLastFrame[4]; /* 上一帧内容 */ +static uint16_t m_U3ErrLastHeight = 0; /* 上一帧高度(type2) */ +static uint32_t m_U3ErrLastTick = 0; /* 上一帧时刻 */ +static uint16_t m_U3ErrRepeat = 0; /* 上一帧已合并的重复包数 */ + +static const char *m_U3ErrStatusName[U3ERR_STATUS_NUM] = { + "IDLE", "ON", "OFF", "START_BEEP", "MOTOR_INIT", "ZERO_MARKING", + "WAIT_MOTOR_INIT", "WAIT_MOTOR_CALI_UP", "WAIT_MOTOR_CALI_DOWN", + "WAIT_STEADY", "END_BEEP", "HEIGHT_CONTROL" +}; + +static U3ErrEvt_t m_U3ErrEvt[U3ERR_EVT_MAX]; /* 事件环形缓冲 */ +static volatile uint16_t m_U3ErrWr = 0; /* 写指针(中断) */ +static volatile uint16_t m_U3ErrRd = 0; /* 读指针(主循环) */ +static volatile uint32_t m_U3ErrLostCnt = 0; /* 缓冲满时丢弃条数 */ + +/* 函数名称: Uart3ErrLog_Enqueue +* 功能描述: 将事件落入队列(内部使用, 关中断保护) */ +static void Uart3ErrLog_Enqueue(uint8_t type, const uint8_t *pFrame, uint16_t height, uint32_t tick, uint16_t repeat) +{ + U3ErrEvt_t evt; + evt.Type = type; + evt.Bits = (uint8_t)((GET_BIT0_DOUT() ? 0x01u : 0u) | (GET_BIT1_DOUT() ? 0x02u : 0u)); + evt.Status = (uint8_t)App.Status; + evt.Frame[0] = pFrame[0]; + evt.Frame[1] = pFrame[1]; + evt.Frame[2] = pFrame[2]; + evt.Frame[3] = pFrame[3]; + evt.Height = height; + evt.Repeat = repeat; + evt.Tick = tick; + + uint32_t primask = __get_PRIMASK(); + __disable_irq(); + uint16_t next = (uint16_t)((m_U3ErrWr + 1U) % U3ERR_EVT_MAX); + if(next != m_U3ErrRd){ /* 未满则入队 */ + m_U3ErrEvt[m_U3ErrWr] = evt; + m_U3ErrWr = next; + } + else{ /* 满则丢弃当前条并计数 */ + m_U3ErrLostCnt++; + } + if(primask == 0U){ + __enable_irq(); + } +} + +/* 函数名称: Uart3ErrLog_Push +* 功能描述: 记录一条报错/复位事件(在USART3接收中断中调用)。相同帧500ms内连发只合并计数, +* 由主循环在连发结束(超时)或出现新帧时落一条带"连发N包"的事件, 避免缓冲溢出 */ +void Uart3ErrLog_Push(uint8_t type, const uint8_t *pFrame, uint16_t height) +{ + uint32_t tick = SysTick_GetTick(); + /* 连发合并: 与上一帧类型/内容相同且间隔<500ms(type2复位完成除外), 只计数 */ + if((m_U3ErrLastType != 0xFF) && (type == m_U3ErrLastType) && (type != U3ERR_T_DONE) && + (pFrame[0] == m_U3ErrLastFrame[0]) && (pFrame[1] == m_U3ErrLastFrame[1]) && + (pFrame[2] == m_U3ErrLastFrame[2]) && (pFrame[3] == m_U3ErrLastFrame[3]) && + ((tick - m_U3ErrLastTick) < 500U)) + { + m_U3ErrRepeat++; + m_U3ErrLastTick = tick; + return; + } + /* 与上一帧不同: 先把滞留的上一帧连同连发计数落队 */ + if(m_U3ErrLastType != 0xFF){ + Uart3ErrLog_Enqueue(m_U3ErrLastType, m_U3ErrLastFrame, m_U3ErrLastHeight, m_U3ErrLastTick, m_U3ErrRepeat); + m_U3ErrRepeat = 0; + } + /* 本帧记为新的滞留帧, 待其连发结束或下一帧到来时落队 */ + m_U3ErrLastType = type; + m_U3ErrLastFrame[0] = pFrame[0]; + m_U3ErrLastFrame[1] = pFrame[1]; + m_U3ErrLastFrame[2] = pFrame[2]; + m_U3ErrLastFrame[3] = pFrame[3]; + m_U3ErrLastHeight = height; + m_U3ErrLastTick = tick; +} + +/* 函数名称: Uart3ErrLog_BitsName +* 功能描述: BIT0/BIT1输出电平转"升/降/停"描述(ASCII, 避免AC5源码集问题) */ +static const char *Uart3ErrLog_BitsName(uint8_t bits) +{ + if((bits & 0x01u) && (bits & 0x02u)) return "STOP"; + if(bits & 0x02u) return "UP"; + if(bits & 0x01u) return "DOWN"; + return "?"; +} + +/* 函数名称: Uart3ErrLog_CodeName +* 功能描述: 已知帧内容转义(发现新帧格式后在此扩充) */ +static const char *Uart3ErrLog_CodeName(const uint8_t *pFrame) +{ + if(pFrame[0] == 0x01 && pFrame[1] == 0x02 && pFrame[2] == 0x00 && pFrame[3] == 0x10) return "(OVERHEAT)"; + if(pFrame[2] == 0x01 && pFrame[3] == 0xAA) return "(RESET)"; + return ""; +} + +/* 函数名称: Uart3ErrLog_StatusName +* 功能描述: 主状态机状态值转可读名 */ +static const char *Uart3ErrLog_StatusName(uint8_t status) +{ + if(status < U3ERR_STATUS_NUM){ + return m_U3ErrStatusName[status]; + } + return "?"; +} + +/* 函数名称: Uart3ErrLogLoopHandler +* 功能描述: 主循环中调用, 打印报错→复位→恢复的完整事件时间线(连发帧合并为一条并显示包数) */ +void Uart3ErrLogLoopHandler(void) +{ + uint8_t cnt; + /* 连发已结束(超时500ms无同帧)且有滞留帧 → 先落队一条 */ + if((m_U3ErrLastType != 0xFF) && (m_U3ErrRepeat > 0U) && + ((SysTick_GetTick() - m_U3ErrLastTick) >= 500U)) + { + Uart3ErrLog_Enqueue(m_U3ErrLastType, m_U3ErrLastFrame, m_U3ErrLastHeight, m_U3ErrLastTick, m_U3ErrRepeat); + m_U3ErrLastType = 0xFF; + m_U3ErrRepeat = 0; + } + for(cnt = 0; cnt < 8U; cnt++){ + char rep[20]; + if(m_U3ErrRd == m_U3ErrWr){ + break; + } + U3ErrEvt_t evt = m_U3ErrEvt[m_U3ErrRd]; + m_U3ErrRd = (uint16_t)((m_U3ErrRd + 1U) % U3ERR_EVT_MAX); + uint32_t s = evt.Tick / 1000U; + uint32_t ms = evt.Tick % 1000U; + if(evt.Repeat > 0U){ + sprintf(rep, ",burst %u", evt.Repeat + 1U); + } + else{ + rep[0] = '\0'; + } + switch(evt.Type){ + case U3ERR_T_FIRST: /* 首次信息帧: 置复位标志 */ + DBG_LOG("[T+%3u.%03us][%s|OUT:%s] INFO: code=0x%02X%02X%s -> SetRestFlag%s\r\n", + s, ms, Uart3ErrLog_StatusName(evt.Status), + Uart3ErrLog_BitsName(evt.Bits), + evt.Frame[2], evt.Frame[3], + Uart3ErrLog_CodeName(evt.Frame), rep); + break; + case U3ERR_T_REPLY: /* 复位中回应信息帧 */ + DBG_LOG("[T+%3u.%03us][%s|OUT:%s] INFO-REPLY: code=0x%02X%02X%s (RestFlag set%s)\r\n", + s, ms, Uart3ErrLog_StatusName(evt.Status), + Uart3ErrLog_BitsName(evt.Bits), + evt.Frame[2], evt.Frame[3], + Uart3ErrLog_CodeName(evt.Frame), rep); + break; + case U3ERR_T_DONE: /* 复位完成: 收到高度帧 */ + DBG_LOG("[T+%3u.%03us][%s|OUT:%s] Height=%dmm -> RestFlag cleared, normal\r\n", + s, ms, Uart3ErrLog_StatusName(evt.Status), + Uart3ErrLog_BitsName(evt.Bits), evt.Height); + break; + case U3ERR_T_UNKNOWN: /* 未知帧: 过热等其它报错可能在此 */ + DBG_LOG("[T+%3u.%03us][%s|OUT:%s] UNKNOWN: %02X %02X %02X %02X %s(ATTENTION)%s\r\n", + s, ms, Uart3ErrLog_StatusName(evt.Status), + Uart3ErrLog_BitsName(evt.Bits), + evt.Frame[0], evt.Frame[1], evt.Frame[2], evt.Frame[3], + Uart3ErrLog_CodeName(evt.Frame), rep); + break; + default: + break; + } + } + if((m_U3ErrRd == m_U3ErrWr) && (m_U3ErrLostCnt > 0U)){ /* 缓冲曾溢出 */ + uint32_t tick = SysTick_GetTick(); + DBG_LOG("[T+%3u.%03us] NOTE: ErrLog buf overflow, lost %u events\r\n", + tick / 1000U, tick % 1000U, m_U3ErrLostCnt); + m_U3ErrLostCnt = 0; + } +} + #endif diff --git a/Project/HC32F460/source/User/Src/main.c b/Project/HC32F460/source/User/Src/main.c index de93113..0774d36 100644 --- a/Project/HC32F460/source/User/Src/main.c +++ b/Project/HC32F460/source/User/Src/main.c @@ -1132,11 +1132,30 @@ static void AppLoopHandler(void) break;} case APP_STATUS_HEIGHT_CONTROL:{ - if(App.MotorPara.Current_height <= 1005 - && App.MotorPara.RestFlag == false - && App.HeightContRolCnt >= 500 - && GET_BIT0_DOUT() == 1 - && GET_BIT1_DOUT() == 1) + if(App.MotorPara.OverheatFlag == true) + { + if(App.MotorPara.Current_height <= 1005) + { + BDC_DOWN();//过热+低位: 继续下降触发控制盒复位(SupportControlHandle在<=1005时不执行BDC_DOWN) + } + //过热+高位(>1005): 由SupportControlHandle根据传感器正常判断下降 + } + else if(App.MotorPara.RestFlag == true) + { + if(App.RestStop1mSCnt > 0) + { + BDC_STOP();//复位停顿: 先停止电机, 让控制盒进入复位流程 + } + else + { + BDC_DOWN();//停顿结束: 再次下降, 触发控制盒完成复位(收到高度帧后RestFlag清除) + } + } + else if(App.MotorPara.Current_height <= 1005 + && App.MotorPara.RestFlag == false + && App.HeightContRolCnt >= 500 + && GET_BIT0_DOUT() == 1 + && GET_BIT1_DOUT() == 1) { App.HeightContRolCnt = 0; BDC_UP(); @@ -1167,6 +1186,8 @@ static void App1mSRoutine(void) App.Uart1Delay1mSCnt--; if(App.Uart3RxTimeOut1mSCnt > 0) App.Uart3RxTimeOut1mSCnt--; + if(App.RestStop1mSCnt > 0) + App.RestStop1mSCnt--; if(App.StopCollDelay1mSCnt > 0) App.StopCollDelay1mSCnt--; if(App.RunCollDelay1mSCnt > 0) @@ -1206,6 +1227,7 @@ int main(void) FeedDogHandler(); #endif DebugLoopHandler(); + //Uart3ErrLogLoopHandler(); //调试观测日志(复位流程已验证, 关闭打印, 需要时取消注释) #if(USE_CS1237_LEFTUP == 1) LEFTUP_CS1237DataLoopCollect(); #endif @@ -1301,13 +1323,25 @@ void Usart3RxIrqCallback(void) { if(App.RxUart3Data.RxBuff[0] == 0x01 && App.RxUart3Data.RxBuff[1] == 0x04) { + uint8_t firstErr = (App.MotorPara.RestFlag == false) ? 0 : 1; //0:首次信息帧 1:复位中回应 App.MotorPara.RestFlag = true; + App.MotorPara.OverheatFlag = false;//收到复位帧, 过热状态解除 + if(firstErr == 0) + { + App.RestStop1mSCnt = 2000;//首次收到复位帧: 启动停顿计时, 先停止电机让控制盒进入复位流程, 计时结束再下降触发复位 + } + //Uart3ErrLog_Push(firstErr, App.RxUart3Data.RxBuff, 0);//调试观测日志(关闭打印, 需要时取消注释) } else if(App.RxUart3Data.RxBuff[0] == 0x01 && App.RxUart3Data.RxBuff[1] == 0x01) { - App.MotorPara.RestFlag = false; int16_t h = ((App.RxUart3Data.RxBuff[2]<<8) & 0xff00) + (App.RxUart3Data.RxBuff[3] & 0x00ff); - if(h >= 1000 && h <= 1430) + if(App.MotorPara.RestFlag == true) + { + //Uart3ErrLog_Push(2, App.RxUart3Data.RxBuff, (uint16_t)h);//调试观测日志(关闭打印, 需要时取消注释) + } + App.MotorPara.RestFlag = false; + App.MotorPara.OverheatFlag = false;//收到高度帧, 确认复位完成 + if(h >= 990 && h <= 1430) { App.MotorPara.Current_height = h; } @@ -1326,6 +1360,16 @@ void Usart3RxIrqCallback(void) App.MotorPara.RL_HeightStress[HEIGHT_TO_IDX(App.MotorPara.Current_height)] = App.ADTrack.RightLow_Org_AdZero - App.RightLowCS1237_TrendArray[0]; } } + else + { //未知帧(帧头非01 04/01 01): 过热等其它报错可能是任意组合, 全部记录供分析 + /* 过热帧(01 02 00 10): 置OverheatFlag, HEIGHT_CONTROL跳过限位纠偏, 由SupportControlHandle判断下降触发控制盒复位 */ + if(App.RxUart3Data.RxBuff[0] == 0x01 && App.RxUart3Data.RxBuff[1] == 0x02 + && App.RxUart3Data.RxBuff[2] == 0x00 && App.RxUart3Data.RxBuff[3] == 0x10) + { + App.MotorPara.OverheatFlag = true; + } + //Uart3ErrLog_Push(3, App.RxUart3Data.RxBuff, 0);//调试观测日志(关闭打印, 需要时取消注释) + } memset(App.RxUart3Data.RxBuff, 0, sizeof(App.RxUart3Data.RxBuff)); App.RxUart3Data.RxLen = 0; App.Uart3RxTimeOut1mSCnt = 0;