💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
【88.1 四区一线。】 提出“四区一线”理论,主要方便初学者理解单片机程序大概的“空间分区”。 “四区”代表四大主流函数,分别是:系统初始化函数,外设初始化函数,主程序的任务函数,定时中断函数。 “一线”是指“系统初始化函数”与“外设初始化函数”的“分割线”,这个“分割线”是一个delay的延时函数。 “四区一线”的布局如下: void main() { SystemInitial(); //“四区一线”的“第一区” Delay(10000); //“四区一线”的“一线” PeripheralInitial(); //“四区一线”的“第二区” while(1) //主循环 { LedTask(); //“四区一线”的“第三区” KeyTask(); //“四区一线”的“第三区” UsartTask(); //“四区一线”的“第三区” ... //凡是在主循环里的函数都是属于“第三区” } } void T0\_time() interrupt 1 //“四区一线”的“第四区” { } “第一区”的函数SystemInitial(),是一个系统的初始化函数,专门用来初始化单片机自己的寄存器以及个别外围要求响应速度快的输出设备,防止刚上电之后,由于输出IO口电平状态不确定而导致外围设备误动作,比如驱动继电器的误动作等等。 “一线”的函数Delay(10000),是一个延时函数,为什么这里要插入一个延时函数?主要目的是为接下来的PeripheralInitial()做准备的。上电后先延时一段时间,再执行PeripheralInitial()函数,因为PeripheralInitial()函数专门用来初始化不要求上电立即处理的外设芯片和模块。比如液晶模块,AT24C02存储芯片,DS1302时钟芯片,等等。这些芯片在上电的瞬间,内部自身的复位需要一点时间,以及外部电压稳定也需要一点时间,只有过了这一点时间,这些芯片才处于正常的工作状态,这个时候单片机才能跟它正常通信,所以“一线”函数Delay(10000)的意义就在这里。 “第二区”的函数PeripheralInitial(),是一个外设的初始化函数。专门用来初始化不要求上电立即处理的外设芯片和模块。 “第三区”的函数LedTask(),KeyTask(),UsartTask(),等等,是一些在主循环里不断扫描的任务函数。 “第四区”的函数void T0\_time() interrupt 1,是一个定时中断函数,一个系统必须标配一个定时中断函数才算完美齐全,这个中断函数提供系统的节拍时间,以及处理扫描一些跟IO口消抖动相关的函数,以及跟蜂鸣器驱动相关的函数。 【88.2 switch外加定时中断。】 提出“switch外加定时中断”理论,主要方便初学者理解单片机程序大概的“逻辑框架”。 switch是一个万能语句,它外加while与for循环就可以做任何复杂的算法,比如,搜索算法,运动算法,提取关键词算法,等等。它外加定时中断,就可以搭建一个系统的基本框架。比如,做通信的程序框架,人机界面的程序框架,按键服务的程序框架,等等。switch的精髓在于“根据条件进行步骤的灵活切换”。具体内容请看本节的练习程序。 【88.3 练习例程。】 根据上述的两大核心框架理论,编写1个LED灯闪烁的程序。 ![](https://img.kancloud.cn/0f/49/0f49cc4e7b34f0e8c13dd7e514906c88_214x279.png) 图88.3.1 灌入式驱动8个LED \#include "REG52.H" void T0\_time(); void SystemInitial(void) ; void Delay(unsigned long u32DelayTime) ; void PeripheralInitial(void) ; void LedTask(void); \#define BLINK\_TIME\_1 1000 sbit P0\_0=P0^0; volatile unsigned char vGu8TimeFlag\_1=0; volatile unsigned int vGu16TimeCnt\_1=0; void main() { SystemInitial(); //“四区一线”的“第一区” Delay(10000); //“四区一线”的“一线” PeripheralInitial(); //“四区一线”的“第二区” while(1) //主循环 { LedTask(); //“四区一线”的“第三区” } } void T0\_time() interrupt 1 //“四区一线”的“第四区” { if(1==vGu8TimeFlag\_1&&vGu16TimeCnt\_1>0) { vGu16TimeCnt\_1--; } TH0=0xfc; TL0=0x66; } void SystemInitial(void) { TMOD=0x01; TH0=0xfc; TL0=0x66; EA=1; ET0=1; TR0=1; } void Delay(unsigned long u32DelayTime) { for(;u32DelayTime>0;u32DelayTime--); } void PeripheralInitial(void) { } void LedTask(void) { static unsigned char Su8Step=0; //加static修饰的局部变量,每次进来都会保留上一次值。 switch(Su8Step) { case 0: if(0==vGu16TimeCnt\_1) //时间到 { P0\_0=0; vGu8TimeFlag\_1=0; vGu16TimeCnt\_1=BLINK\_TIME\_1; //重装定时的时间 vGu8TimeFlag\_1=1; Su8Step=1; //切换到下一个步骤,精髓语句! } break; case 1: if(0==vGu16TimeCnt\_1) //时间到 { P0\_0=1; vGu8TimeFlag\_1=0; vGu16TimeCnt\_1=BLINK\_TIME\_1; //重装定时的时间 vGu8TimeFlag\_1=1; Su8Step=0; //返回到上一个步骤,精髓语句! } break; } }