51单片机几乎是单片机入门的必经之路,一般的思路就是引导学生尽快入门,控制外设,只有极少的书本会提到一些设计思想,基于这个想法,这篇文章我就和大家一起分享下我学习过程中对于裸机代码的一些思考和总结。
1.轮询系统
轮询系统就是在主函数main()中不停循环执行各个任务,没有中断,伪代码如下
void main(){ Systerm_Init(); while(1) { DoTask1(); Delay_ms(100); DoTask2(); Delay_ms(100); DoTask3(); Delay_ ms(100) }}
这种代码一般是刚刚入门的学生所写,可能定时器都没有学,实际工程中几乎不会用到。
实际代码在STC89C52单片机通过Keil进行仿真,定义三个任务,每个任务是分别把LED翻转。
结果如下,可以看出我如果要独立设置LED1/LED2/LED3的翻转频率,是比较难以实现的,上述3个延时函数的时间都会对每一个task中的LED翻转频率都会有影响响。
2.前后台系统
中断称为前台,main中的while循环称为后台。相比于第一种的轮询系统,这种方式相对可以提高外部事件的实时响应能力。示意图如下所示
后台伪代码如下:
main函数死循环中通过判断各个任务task的标志位来看是否需要执行该task,需要注意的是一定要清除标志位。
void main(){ Systerm_Init(); while(1) { if(flag1 ) { flag1 = 0;//清除标志位 DoTask1(); } if(flag2 ) { flag2 = 0;//清除标志位 DoTask2(); } if(flag3 ) { flag3 = 0;//清除标志位 DoTask3(); } }}
前台伪代码如下
中断函数中将各个任务task的标志位置1,表示有效,如下是伪代码,不同的任务对应标志位有可能是多个不同中断函数中,也可以是同一个中断函数中。
void ISR1(){ flag1 = 1;}void ISR2(){ flag2 = 1;}void ISR3(){ flag3 = 1;}
这种代码很常见,当任务不复杂,这种做法也是比较推荐的,看起来比较直观,通俗易懂。
对应到本次范例中,可以在定时器中断函数里来对各个任务的标志位置位,仿真结果和源码如下
通过定时器1的定时时间来置任务标志位,定时器1的每隔5ms会进一次中断,
那么task1执行的频率是5ms*100=500ms,即LED1每隔500ms翻转一次;
task2执行的频率是5ms*200=1000ms,即LED2每隔1000ms翻转一次;
task3执行的频率是5ms*300=1500ms,即LED3每隔1500ms翻转一次
从这里可以看出比轮询要好看多,每个任务执行的频率都可以单独设定,即各个LED翻转频率可以任意指定,不会相互影响。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.