单片机常被称作 MCU,MCU 的全称是 Micro Control Unit,就是微型控制器的意思。顾名思义,单片机常被用于控制一些器件工作,因此物联网的终端,或者其他一些智能机器,都是离不开单片机的。
小到手机,大到汽车飞机,现在几乎只要是电子器件,就有单片机的身影。
精确计时的重要性
传感器能够感知外界环境,可以说是一切智能机器的基础。实际工程中,常常使用单片机或者控制传感器工作,或者采集传感器的数据。但是不管是控制还是采集,单片机都需要与传感器通信,这样才能将控制命令发送到传感器,或者将传感数据接收到单片机内部。
为了实现器件与器件之间的通信,人们制定了一些通信协议。通信协议其实就是一系列约定,比如约定总线先输出低电平 10us,再输出高电平 30us 表示 0;总线先输出低电平 10us,再输出高电平 100us 表示 1。
可以看出,如果单片机要解析通信协议,就只需要处理电信号与时间的关系就可以了。
假设单片机在与某个传感器通信时,需要拉低总线 50us,这就需要一个精确的定时器。在读传感器数据时,需要判断总线究竟被传感器拉高了 30us 还是 100us,这就需要一个精确的计时器。
不精确的定时器
那么单片机怎样才能精确的定时和计时呢?本节就以 51 单片机为例,来说一下这个问题。
在第三节制作呼吸灯时,用到的延时函数C语言代码是如下定义的:
void delay(unsigned int n)
{
unsigned int x;
while(n--){
x = 50;
while(x--);
}
}
[video width="544" height="960" mp4="https://blog.popkx.com/usr/uploads/2019/01/1-1.mp4"][/video]
但这只是粗略的定时,因为软件每次执行需要花费的时间都有所差异。所以上面的 delay() 函数,只能用在对时间精确度要求不高的“呼吸灯”小项目中。
精确的定时器
相当一部分单片机内部都有计数器资源。计数器内部有一个寄存器,这个寄存器的值每经过一个机器周期就会自动加 1,而机器周期仅与单片机的晶振有关。
我使用的这款 51 单片机有两个计数器,它的晶振固定为 11.0592MHz,一个机器周期等于 12 个时钟周期。所以,计数器每加1,就表示时间过去了 n 秒,n 的计算公式如下:
n = 12 * ( 1/11.0592MHz )
这款单片机计数器的寄存器宽为 16 位,因此最大能够表示到 0xffff 即 65535。计数器计满(溢出)一次,就会将寄存器 TFx 置 1,所以检测 TFx 寄存器就能够知道计数器是否计满。
如此一来,设计精确的定时器思路就有了,请看如下 C语言代码:
static unsigned int timer_cnt = 0;
void set_timer0(unsigned int tus)
{
timer_cnt = (unsigned int)((float)tus * 11.0592 / 12.0);
timer_cnt = 65535 - timer_cnt;
TH0 = (timer_cnt>>8) & 0xff;
TL0 = timer_cnt & 0xff;
TMOD |= 0x01;
}
假设定时器计数 timer_cnt 次消耗 tus 微秒,那么让计数器计数 65535-timer_cnt 次就溢出,我们就可以检测 TF0 寄存器的值判断是否已经过去 tus 微秒。请看如下 C语言代码:
void start_timer0()
{
TF0 = 0;
TR0 = 1;
}
void wait_timer0()
{
while(!TF0);
TR0 = 0;
TH0 = (timer_cnt>>8) & 0xff;
TL0 = timer_cnt & 0xff;
}
TR0 寄存器为高电平时,计数器才开始计数。如此一来,可以定义精确的延时函数,它的C语言代码如下:
set_timer0(10);
void delay_10us(unsigned int n)
{
while(n--){
start_timer0();
wait_timer0();
}
}
现在写如下控制程序,测试我们实现的精确定时器,请看如下C语言代码:
void main()
{
init_uart(9600);
set_timer0(10); // 10us
prints("program start...\n");
while(1){
delay_10us(50000);delay_10us(50000);
prints("1s past ...\n");
}
}
两句delay_10us(50000);表示延时 100万微秒(即 1秒)。编译程序并烧写到单片机,在电脑端打开串口调试工具,发现的确每隔 1秒打印一次 "1s past ...":
精确计时器
思路与设计精确定时器是一样的。因为暂时不方便测试,所以放入下一节再讨论。下一节将介绍一款温度、湿度传感器,并使用单片机采集之,发送到电脑端。这样一来,就可以点击鼠标知道室内的温度和湿度了。敬请关注!!!