裸机软件架构的实践
对于一些应用场景要求不高的场合,跑裸机也是能够彻底知足需求,虽然如今的单片机性能愈来愈好,可是8bit的单片机,像stc8051/stc8052这些仍是应用在不少消费电子的领域,主要是成本便宜,操做简单,只要软件架构设计的合理,也是能够知足大部分应用需求的,下面就来聊一聊裸机的软件架构设计。架构
架构的组成
时间片轮询法函数
时间片轮询,是裸机中经常采用的一个软件架构,顾名思义是在某一个时间段调用一个子任务,经过定时器定时来不停的轮询。首先须要将一个大而杂的任务集,按照不一样的功能来划分红不一样的子任务,而后须要占用MCU一个Timer资源,用于定时轮询,依据具体的需求,来给每个子任务来分配不一样的Task_Flag(即实时性较高的子任务,能够设置10ms调用一次,实时性较低的子任务,能够设置1000ms调用一次)。时间片轮询法的好处是能够合理的利用MCU的资源,不会让一些实时性较低的子任务频繁占用MCU的资源,从而提升软件系统的总体实时性。性能
分层设计思想ui
咱们先来看看通常分哪几个层,这里画了一个UML图,大体分为如下几个层:硬件驱动层、功能模块层、业务逻辑处理层、应用层,层与层应该是相互独立的,经过相应的调用接口来调用下一层的函数,从而实现层与层之间的解耦。spa
必备的C语言知识架构设计
函数指针、指针函数、结构体、位域、枚举、指针、函数调用、函数传参等设计
架构的实现
时间片轮询法的伪代码实现3d
typedef unsigned char uint8_t; typedef enum { Timer1ms_Cnt = 1, Timer10ms_Cnt = 10, Timer20ms_Cnt = 20, }eTimerCnt; volatile struct TimFlg { uint8_t TimFlg; uint8_t Timer1ms_Flg; uint8_t Timer10ms_Flg; uint8_t Timer20ms_Flg; }sTimFlg; void TimFlgInit(void) { uint8_t *pTimFlg = (uint8_t*)&sTimFlg; for(uint8_t i = 0; i < sizeof(sTimFlg)/sizeof(uint8_t); i++) { pTimFlg[i] = 0x00; } } void TaskFunc(void) { static uint8_t cnt1 = 0; static uint8_t cnt2 = 0; static uint8_t cnt3 = 0; if(1 == sTimFlg.TimFlg) { if(++cnt1 >= Timer1ms_Cnt) { sTimFlg.Timer1ms_Flg = 0x01; cnt1 = 0; } else { //do nothing; } if(++cnt2 >= Timer10ms_Cnt) { sTimFlg.Timer10ms_Flg = 0x01; cnt2 = 0; } else { //do nothing; } if(++cnt3 >= Timer20ms_Cnt) { sTimFlg.Timer20ms_Flg = 0x01; cnt3 = 0; } else { //do nothing; } sTimFlg.TimFlg = 0x00; } else { //do nothing; } } void TimerInit(void) { //programming code; } void TimerISR(void) { if(TRUE == InterruptEvent()) { sTimFlg.TimFlg = 0x01; //1ms的定时器 clear(InterruptFlg); } else { //do nothing; } }
分层设计的伪代码实现指针
这里用ADC采集来举一个例子吧,玩过单片机的同窗应该都知道,ADC是单片机一个经常使用的外设资源,用来采集其余设备输入的电压,若是涉及到几路电压同时采集的状况,此时就须要开启单片机的DMA功能,才能同时将几个通道的电压值存入到ADC的数据寄存器中,这里就不过多描述,不懂的能够去了解下,下面主要来看看软件如何分层,在C语言程序设计中主要是用函数指针来实现层与层之间的解耦,分层设计的好处是当涉及到某一层代码的变动,咱们只须要改当前层的函数,对其余层的调用并无任何影响。code
/********************************Hw Driver Layer************************/ void HwCallBack(void); void AdcDmaInit(void); void AdcConvert(void); void HwCallBack(void) { AdcConvert(); } void AdcModuleInit(void) { AdcInit(); AdcDmaInit(); } void AdcInit(void) { ADC_GPIO_Init(); ADC_DMA_Enable(); ADC_Enable(); ADC_Calib(); } void AdcDmaInit(void) { DMA_Init(); DMA_Enable(); } void AdcConvert(void) { ADC_StartConvert(); while(!DMA_Trans()) { clear(DMA_Flg); } } /****************************************************************/ ---------------------------------------------------------------------------- /********************************Func Module Layer************************/ #define OK 1 #define ERR 0 void ReadBatCallBack(void); void ReadSenrCallBack(void); uint8_t ReadBatVol(void); uint8_t ReadSenrVol(void); void FmHanderFunc((void)(*CallBack)(void)) { if(NULL != CallBack) { CallBack(); } else { //do nothing; } } void ReadBatCallBack(void) { ReadBatVol(); } void ReadSenrCallBack(void) { ReadSenrVol(); } uint8_t ReadBatVol(void) { uint8_t BatVolSts; FmHanderFunc(HwCallBack); //do something; return BatVolSts; } uint8_t ReadSenrVol(void) { uint8_t SerVolSts; FmHanderFunc(HwCallBack); //do something; return SerVolSts; } /****************************************************************/ ---------------------------------------------------------------------------- /********************************Logical Business Layer************************/ #define LOWVOL 1 void WarningEvent(void); uint8_t LbHanderFunc(void (*CallBack)(void)) { uint8_t res; if(NULL != CallBack) { res = CallBack(); } else { res = ERR; } return res; } void WarningEvent(void) { uint8_t BatVolSts = 0; if(ERR != LbHanderFunc(ReadBatCallBack)) { BatVolSts = LbHanderFunc(ReadBatCallBack); if(LOWVOL == BatVolSts) { WarningLamp(); } else { //do nothing; } } else { //do nothing; } } /****************************************************************/ ---------------------------------------------------------------------------- /*********************************Application Layer*************************/ void AppHanderFuc(void (*CallBack)(void), uint8_t* TimerFlg) { if(NULL != CallBack) { if(1 == (*TimerFlg)) { CallBack(); *TimerFlg = 0; } else { //do nothing; } } else { //do nothing; } } int main(void) { SystemInit(); while(1) { AppHanderFuc(WarningEvent, (uint8_t*)&sTimFlg.Timer10ms_Flg); //... } } /****************************************************************/