global(5516).c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /* includes ----------------------------------------------------------*/
  2. #include "global.h"
  3. /* typedef -----------------------------------------------------------*/
  4. /* define ------------------------------------------------------------*/
  5. /* macro -------------------------------------------------------------*/
  6. /* variables ---------------------------------------------------------*/
  7. global_par s_global_par;
  8. /* function prototypes -----------------------------------------------*/
  9. /**
  10. * @brief 中控板初始化
  11. * @param p_param_boot : 参数区指针
  12. * @param p_rs485RecDate:485接收数据区的指针
  13. * @note NONE
  14. * @retval 无
  15. */
  16. void centralCtrSys_Init(param_boot *p_param_boot, global_par *p_global_par){
  17. uint8_t recBack = 0;
  18. rs485RecDate *p_rs485RecDate = &s_rs485RecDate;
  19. // 1. 从flash中读出VIN
  20. Read_ParamArea(); // 读出参数区的所有数据
  21. // 2. 与车通信获取vin数据(读取所有寄存器的值)
  22. modbus_read_holding_registers(0x01, 0x0000, 67);
  23. HAL_Delay(3000); // 延时5s
  24. // 3. vin码比对
  25. if(s_comData.vinRecSuccess == 1){ // 成功获取到车辆数据
  26. if(memcmp(p_param_boot->vin, p_rs485RecDate->VIN, 26) != 0){ // 比对不成功
  27. // 备份新的VIN码
  28. memcpy(p_param_boot->vin, p_rs485RecDate->VIN, 26);
  29. Write_paramArea();
  30. // 置位中控板迁移事件
  31. BIT_SET(p_global_par->ctrEvent, CtrlPanelMigration);
  32. }
  33. }
  34. // 4. 初始化4g模块 4g模块在这里不好处理 放在任务中,围栏数据也一样
  35. // 5. 读取96位(或者说是3个32位的字)的唯一ID
  36. GetUniqueID(s_messageDate.devId);
  37. // 6. 陀螺仪的初始化
  38. recBack = atk_ms6050_init();
  39. if(recBack != 0){
  40. printf("ATK-MS6050 init failed!\r\n");
  41. BIT_SET(s_comData.Malfunction, gyroscope); // 置位陀螺仪数据异常故障
  42. }
  43. printf("ATK-MS6050 init\r\n");
  44. recBack = atk_ms6050_dmp_init();
  45. if(recBack != 0){
  46. printf("ATK-MS6050 DMP init failed!\r\n");
  47. BIT_SET(s_comData.Malfunction, gyroscope); // 置位陀螺仪数据异常故障
  48. }
  49. printf("ATK-MS6050 DMP init!\r\n");
  50. }
  51. // 电池故障判断
  52. void fault_bat(rs485RecDate *p_rs485RecDate, comData *p_comData){
  53. uint16_t errorLevel = 0;
  54. /* 尝试获取互斥量,等待无限长时间 */
  55. if(osMutexAcquire(mutex_rs485RecDateHandle, osWaitForever) == osOK)
  56. {
  57. errorLevel = p_rs485RecDate->alarmLevel;
  58. /* 访问完成,释放互斥量 */
  59. osMutexRelease(mutex_rs485RecDateHandle);
  60. }
  61. // 存在电池故障
  62. if(errorLevel != 0){
  63. BIT_SET(s_comData.Malfunction, batError); // 置位电池故障
  64. }else{
  65. BIT_CLEAR(s_comData.Malfunction, batError); // 清除电池故障
  66. }
  67. }
  68. /**
  69. * @brief 中控板故障检测
  70. * @param p_global_par:global_par的全局参数指针
  71. * @note 周期为1s1次 清除除电池故障的其他故障
  72. * @retval 无
  73. */
  74. void faultDetection(global_par *p_global_par){
  75. // 参数定义
  76. uint8_t timesCnt_gps = 0; // gps记时
  77. uint8_t errorCnt_gyro = 0; // 陀螺仪数据故障滤波次数
  78. uint16_t timesOut_ota = 0; // OTA超时计数
  79. comData *p_comData = &s_comData;
  80. // 1. 电池故障判断
  81. fault_bat(&s_rs485RecDate, &s_comData); // 电池故障判断
  82. // 开启超级权限 不判断除电池故障的其他故障
  83. if(p_global_par->superUser == 1){
  84. BIT_CLEAR(s_comData.Malfunction, fence);
  85. BIT_CLEAR(s_comData.Malfunction, positionError);
  86. BIT_CLEAR(s_comData.Malfunction, errorMqtt);
  87. BIT_CLEAR(s_comData.Malfunction, errorMqtt);
  88. BIT_CLEAR(s_comData.Malfunction, init_4G_error);
  89. BIT_CLEAR(s_comData.Malfunction, com485);
  90. BIT_CLEAR(s_comData.Malfunction, gyroscope);
  91. BIT_CLEAR(s_comData.Malfunction, OTA_fault);
  92. return;
  93. }
  94. // 2. 超出围栏故障判断
  95. if(p_comData->fenceStatus == 1){
  96. BIT_SET(s_comData.Malfunction, fence);
  97. }else{
  98. BIT_CLEAR(s_comData.Malfunction, fence);
  99. }
  100. // 3. GPS信号丢失
  101. // 获取gps失败,但陀螺仪数据正常的情况下,一分钟之后置位gps故障
  102. // 获取gps失败,陀螺仪数据异常,直接置位gps故障
  103. if((p_global_par->positionErrorCnt >= 3) && (BIT_CHECK(s_comData.Malfunction, fence) == 0)){
  104. if(timesCnt_gps < 60){
  105. timesCnt_gps++;
  106. }else{
  107. timesCnt_gps = 60;
  108. BIT_SET(s_comData.Malfunction, positionError);
  109. }
  110. }else if((p_global_par->positionErrorCnt >= 3) && (BIT_CHECK(s_comData.Malfunction, fence) == 1)){
  111. timesCnt_gps = 0;
  112. BIT_SET(s_comData.Malfunction, positionError);
  113. }else{
  114. timesCnt_gps = 0;
  115. }
  116. if(p_global_par->positionErrorCnt == 0){ // 清除gps故障
  117. BIT_CLEAR(s_comData.Malfunction, positionError);
  118. }
  119. // 4. MQTT通信异常
  120. if(p_global_par->mqttTimeoutCnt >= PUBLISH_TIME_MS){
  121. BIT_SET(s_comData.Malfunction, errorMqtt); // 置位MQTT故障
  122. }
  123. if(p_global_par->mqttTimeoutCnt == 0){ // 清除MQTT故障
  124. BIT_CLEAR(s_comData.Malfunction, errorMqtt);
  125. }
  126. // 5. 4G模块初始化故障
  127. if(p_global_par->InitFaultFlag_4G == 1){
  128. BIT_SET(s_comData.Malfunction, init_4G_error); // 置位4g模块初始化故障
  129. }else{
  130. BIT_CLEAR(s_comData.Malfunction, init_4G_error); // 清除4g模块初始化故障
  131. }
  132. // 6. 485通信故障
  133. if(p_global_par->timeoutCnt_485 >= TIMEOUT_485){
  134. BIT_SET(s_comData.Malfunction, com485); // 置位485通信故障
  135. }
  136. if(p_global_par->timeoutCnt_485 == 0){
  137. BIT_CLEAR(s_comData.Malfunction, com485); // 置位485通信故障
  138. }
  139. // 7. 陀螺仪数据故障-- 获取的姿态角数据全部为0
  140. if(p_global_par->gyroDataFaultFlag == 1){
  141. if(errorCnt_gyro < FILTER_TIME_gyro){
  142. errorCnt_gyro++;
  143. }else{
  144. errorCnt_gyro = FILTER_TIME_gyro;
  145. BIT_SET(s_comData.Malfunction, gyroscope); // 置位陀螺仪数据异常故障
  146. }
  147. }else{
  148. errorCnt_gyro = 0;
  149. BIT_CLEAR(s_comData.Malfunction, gyroscope);
  150. }
  151. // 8. 升级故障--开始升级后,开始记时,2分钟还未升级成功的话,置位升级故障,
  152. // 退出升级,此次升级失败,旧版本运行,清除升级状态变量、标志、数据,重启释放
  153. if(p_global_par->otaUpgradeStartFlag == 1){
  154. if(timesOut_ota < TIME_OUT_OTA){
  155. timesOut_ota++;
  156. }else{
  157. timesOut_ota = TIME_OUT_OTA;
  158. BIT_SET(s_comData.Malfunction, OTA_fault); // 置位OTA异常故障
  159. }
  160. }
  161. }
  162. /**
  163. * @brief 控制蜂鸣器响停
  164. * @param count 当前计数
  165. * @param on_threshold 响的阈值
  166. * @param off_threshold 停的阈值
  167. * @retval 无
  168. */
  169. void beep_control(uint8_t count, uint8_t on_threshold, uint8_t off_threshold) {
  170. if (count < on_threshold) {
  171. GPIO_BEEP(GPIO_PIN_SET);
  172. } else if (count < off_threshold) {
  173. GPIO_BEEP(GPIO_PIN_RESET);
  174. }
  175. }
  176. /**
  177. * @brief 控制蜂鸣器响应
  178. * @note 根据不同条件控制蜂鸣器的响停 进入周期为100ms
  179. * @param 无
  180. * @retval 无
  181. */
  182. void control_beep_response(void) {
  183. comData *p_comData = &s_comData;
  184. global_par *p_global_par = &s_global_par;
  185. // 蜂鸣器计数器
  186. static uint8_t beep_count_fence = 0;
  187. static uint8_t beep_count_fault = 0;
  188. static uint8_t beep_count_ota = 0;
  189. // 超出围栏 500ms频率响应
  190. if (p_comData->fenceStatus == 1) {
  191. beep_control(beep_count_fence, 5, 10);
  192. beep_count_fence = (beep_count_fence >= 10) ? 0 : beep_count_fence + 1;
  193. }
  194. // 运行中限制车速的故障 1s的频率响应
  195. else if ((BIT_CHECK(s_comData.Malfunction, fence))
  196. || (BIT_CHECK(s_comData.Malfunction, batError))
  197. || (BIT_CHECK(s_comData.Malfunction, positionError))){
  198. beep_control(beep_count_fault, 10, 20);
  199. beep_count_fault = (beep_count_fault >= 20) ? 0 : beep_count_fault + 1;
  200. }
  201. // OTA升级 2s的响应频率
  202. else if (p_global_par->otaUpgradeStartFlag == 1) {
  203. beep_control(beep_count_ota, 20, 40);
  204. beep_count_ota = (beep_count_ota >= 40) ? 0 : beep_count_ota + 1;
  205. }
  206. }