自己怎么建设一个网站,wordpress上传都图片不显示图片,购物网站建设推进表,泉州最专业手机网站建设开发工业产品好像都要写自检函数接口。
自检一般就需要对板子上的东西做一个测试调用。
比如你的板子有led#xff0c;传感器#xff0c;显示屏。我们就需要在这个自检时间里去检查led闪烁是否正常#xff0c;传感器通信成果与否#xff0c;失败了就要通过后续的显示屏显示出…工业产品好像都要写自检函数接口。
自检一般就需要对板子上的东西做一个测试调用。
比如你的板子有led传感器显示屏。我们就需要在这个自检时间里去检查led闪烁是否正常传感器通信成果与否失败了就要通过后续的显示屏显示出来。自检一般伴随一个倒计时根据你传感器全部掉线且通信完成的时间去设置这个自检时间间隔应该会好一些反正就是如果你的传感器是坏的那自检结束应该显示故障或掉线等标志如果是好的应该显示示值。如果是好的自检完毕还没上线这岂不是很难说的过去。
于是我们分解一下自检函数应该办的事首先刷一下屏吧都有软件版本号吧显示一下吧。流水灯该有吧展示你的灯的好坏。然后就是去跟传感器通信争取在自检时间结束之前通信完毕。
这个时间如何去获得呢我们可以通过软件定时器获得。软件定时器的时间来源可以是任一个硬件定时器硬件定时器选择一个最小时间计数值。比如1ms或1us。一般都是1ms。
于是我们就可以如下代码
// 系统自检传感器预热、倒计时等都放在这个函数
void SysSelf (void) {uint8_t_t pre_heat_cnt 0,first_run 0;static uint16_t timecnt 0, oled_brush 0;uint32_t time;uint8_t_t led_sta 0;uint8_t_t buf[5] {0}CpuRstType SelRest();if (CpuRstType ! RES_SOFT||close_dev0x5AA5){led_set (LED_ALL, LED_M_LOOP, systick_1ms_cnt());while (1) {
#ifndef DIS_WDG_DBG_EN // AnalogWDGFeed();//WDGFeed();
#endifif (SoftTimerCheck (SYS_SELF_TIM) 0) {timecnt;SoftTimerSet (SYS_SELF_TIM, SYS_SELF_TIMOUT);}if (timecnt 10) // 1秒的屏幕自检{lcd_disp_all();} else if (timecnt 10 ti{if (oled_brush 0 ) {lcd_clear_disp();oled_brush 1;}lcd_display_CHAR(V,1);lcd_display_NUMBER(0,2,1);lcd_display_NUMBER(1,3,0);} else if ((timecnt 20 timecnt 270) ((timecnt % 10) 0{buf[0] -;buf[3] -;buf[1] ((270 - timecnt) / 100) 0;buf[2] ((270 - timecnt) % 100 / 10) 0;lcd_display_CHAR(buf[1],1);lcd_display_CHAR(buf[2],2);lcd_display_CHAR(buf[0],0);lcd_display_CHAR(buf[3],3);}led_update_loop(); if (timecnt 270) // 27s 结束自检{timecnt 0;break;}pre_heat_cnt timecnt/10;// 开机自检阶段查询传感参数if(first_run 0){first_run 1;sen1_self_flag 1;sen2_self_flg 1;sen1_sensor_comm();sen2_sensor_comm();}if(pre_heat_cnt 8 first_run 1){if(Get_sen1_state() ! STA_LP){sen1_sensor_comm();}}if(first_run 1){if(get_sen2_state() ! STA_LP_){press_sen2_comm();}}}sen1_self_flg 0;sen2_self_flag 0;led_switch(Disable);}clear_close_flg();led_set (LED_ALL, LED_M_OFF, systick_1ms_cnt());led_set (LED_RUN, LED_M_BLINK_FAST, systick_1ms_cnt());led_update();wakeup_Reinit();power_state 1;
}
大致流程是什么呢1s的lcd全显示看lcd是否正常然后就是1s的版本号然后就是流水灯。在2s后进行传感器通信并不断的倒计时传感通信利用有限状态机实现在这里进行不断的调用如果到最后一个状态了它会将状态机状态转换会第一状态为了避免重复通信就取消进入再次进入通信状态机。通信完成无论传感器在不在线都要把自检标志清零因为在状态机里用到了这些标志。然后就是标志已经开机了。软件定时器的实现很简单给出一个示例利用滴答定时器来进行计数以后再更新软件定时器的实现。
void SysTick_Handler (void) //滴答定时器中断服务函数分为两部分一部分是延时状态的处理另一部分是时间片的处理时间片内任务没有进行滴答延时所以不参与从延时列表的操作
{tNode *node;tTask *task;uint32_t statustTaskEnterCritical(); //进入临界区for(nodetTaskDelayedList.firstnode; node! (tTaskDelayedList.headNode); nodenode-nextNode) //遍历延时表的所有节点{tasktNodeParent(node, tTask, delayNode); //根据宏定义计算该延时节点的任务节点首地址if(--task-delayTicks0) //如果该任务的延时计数值为0 表示可以加入就绪列表{tTimeTaskWakeUp(task); //将该任务的延时节点从延时列表删除并将延时状态取消tTaskSchedRdy(task);// 把该任务加入就绪列表位图置1}}if(--(currentTask-slice)0) //Time slice round-robin 如果该任务的时间片计数值为0 表示可以切换到该优先级的下一个任务{if(tListCount(taskTable[currentTask-prio])0) //如果该有限级任务数大于0 {tListRemoveFirst(taskTable[currentTask-prio]); //把该任务与链表从头部断开连接tListAddLast(taskTable[currentTask-prio], (currentTask-linkNode)); //把该任务重新连接到链表尾部currentTask-sliceTINYOS_SLICE_MAX;//重新设置任务的时间片 以便下一次再次减到0设置完之后就可以开启调度切换到下一个时间片任务}}
#if TINYOS_ENABLE_CPUUSAGE_STAT 1tickCount;//每10ms进入一次中断查询 tick达到100次算1s 一个周期checkCpuUsage();//进入一次滴答中断就检查一次CPU
#endiftTaskExitCritical(status);
#if TINYOS_ENABLE_TIMER 1tTimerModuleTickNotify(); // 每经过10ms进入中断一次标志着一次硬定时
#endif
#if TINYOS_ENABLE_HOOKS 1tHooksSysTick();
#endiftTaskSched(); //Schedule the task
}这里跟软件定时器相关的就是tickCount这里去计数软件定时器的接口去哪些定时项有没有到时间当然这还涉及一个计数值满了回滚到0的情况要另外考虑。
个人心得体会如有错误还请指正。