单片机编程思想之消除阻塞

demi的头像

本人写单片机程序也有五六年了,其实在三年前我写的程序里几乎没有delay()了,如果你的程序没有delay那么整个程序执行起来会非常的快。下面我们来分析下平时写单片机程序中所遇到的阻塞,以及解决思路。

在讲之前我们的程序框架是main函数里先初始化,然后while(1),前台程序是各种中断。

阻塞有:

①按键程序判断会用到delay消抖,典型的消抖是5ms。

②动态显示时候显示一位数码管时候也会用到延时5ms左右。

③等待串口发送完成。

④好像就这些比较耗时的了。

解决方法:

①像这样的程序,我们可以在定时中断里面判断按键的状态

②解决方法同上

③串口中断发送估计很多人没有用过,也有很多人觉得没有必要,我想说的是你没有写过大型项目,对实时性要求不高,如果你的程序很大,需要服务的地方很多,那你用阻塞式发送很可能会降低整个程序的实时性了,例如9600波特率发送一个字符1ms时间,如果一次发送50个字符就是相当于执行delay(50);那怎么用中断发送呢?很简单,打开串口\发送中断,第一个字符你程序发送,剩余的在发送中断里面发送即可。

以上是比较单一的情况,大部分情况下我们遇到的是一个完整型操作里面有的执行很快,有的又必须阻塞。例如一个温度传感器,它要求先下发转换命令然后等待一定时间后才能进行下一步操作,这个时候你该怎么去写呢?

我想说的解决方法有很多种,你需要把这个任务分解成两个部分,一个是启动转换,另一个是读。

程序形式如下:

startcov();
delay();
read();

当然上述的delay并不是执行一些无关命令,而是在一个标志位。

那有人又说了我就想把上述的三个函数封装到一个函数里面该怎么去做呢?

例如取个名字叫GetCovResult(),下面给出我的参考:

void GetCovResult()
{
static u8 state=0;
switch(state)
{
case 0:
startcov();
state++;
break;
case 1:
if(flag_500ms)
state++;
break;
case 2:
read();
state=0;
break;
}
}

然后在while(1)里不断的调用GetCovResult()函数即可。

上述的例子里面用到了状态机的概念,裸机编程离不开灵活使用状态机。

因此以后我们的程序中只要没有了delay就会发现执行速度飞快,因为我们绝大部分程序都是赋值和if判断,因此执行速度会非常的快。那如果我的程序就全是计算该怎么办呢?请参考状态机的方法去解决.什么?你不会?给你再举个例子。

假如有8位数码管需要动态扫描,你不使用状态机话可能需要在一次while(1)里面八位都扫描一遍,当你使用状态机的时候你就可以每个while(1)循环之扫描其中之一的数码管,这样你的程序看起来就执行的很快。

单片机的世界编程是很简单的,只要你消除了阻塞,单片机也能出色表现。最后祝你们踏上高手之路~

来源: tq3101955