单片机学习笔记---按键控制LED流水灯模式&定时器时钟

目录

代码讲解

初始化函数

1.定时器部分的配置步骤

第一步,对TMOD的赋值

第二步,给TF0赋值

第三步,给TR0赋值开启定时器

第四步,给TL0和TH0赋初值

2.中断系统部分的配置步骤

第一步,给ET0赋值

第二步,给EA赋值

第三步,给PT0赋值

中断函数

定时器计算器生成代码工具

按键控制流水灯代码演示

时钟代码演示


看这一节之前一定要先依次看完这前三节:

单片机学习笔记---中断系统(含外部中断)-CSDN博客

单片机学习笔记---定时器/计数器(简述版!)-CSDN博客

单片机学习笔记---定时器和中断系统如何连起来工作-CSDN博客

代码讲解

这一节开始代码演示。

本节代码主要演示的是这个工作路线:

新创建一个工程,写上框架:

一,初始化函数

现在来写一个配置定时器和中断系统的函数

1.定时器部分的配置步骤

第一步,对TMOD的赋值

首先是对TMOD的赋值,TMOD的寄存器,我们前面已经说了,它是用来确定我们定时器的工作方式,像里面包含了T0和T1这两个定时器的工作方式,那你使用的是T0或者是T1,那就对这个TMOD的高4位或者是低4位进行赋值。

我们给TMOD赋值0x01,高四位它是0,说明我们现在使用的是低4位,它低四位是用于定时器0的管控,定时机1是高四位来控制的。

我们先不管定时器1,先看定时器0,所以高四位赋值0,低四位赋值1,也就是T1=0,T0=1的意思

那定时器0低4位是0001,对应的寄存器的值是0001

最后八位赋值成0000 0001

以上GATE设置为0,说明定时器的启动是通过TR0来控制的;

然后这个C/T设置为0,说明它的工作与T模式,也就是定时器模式;

然后,M1和M0=01,01的话是工作方式1,也就是16位定时计数器。

于是写TMOD=0x01

所以,我们通过这种设置可以知道我们定时器它处于定时器0,并且是16位,方式1,而且GATE是0可以直接通过TCON中的TR0来进行启动。

                

这样我们就完成了工作流程图中的这一部分的配置:

第二步,给TF0赋值

根据流程图,我们现在需要给TF0赋值:

先补充一个概念知识:

不可位寻址VS可位寻址:

不可位寻址的寄存器只能整体赋值;

可位寻址的寄存器可以对它其中的每一位单独赋值。

由于TCON是可位寻址的,所以我们可以单独赋值。

上图中TF1和TR1是定时器1的,我们不管。

我们可以单独看定时器0中的TF0和TR0。

TF0是定时器T0溢出中断标志,我们给它赋值0,因为一旦等于1之后,它就产生中断。我们先给TF0清零是为了防止还没有配置好就产生中断。这一步没有的话也不会产生特别大的影响。

第三步,给TR0赋值开启定时器

根据流程图,我们要配置TR0

由于GATE位等于0了,所以开启定时器主要取决于TR0,所以就写TR0=1;如果不知道为什么TR0=1的话请看上一节解释。

第四步,给TL0和TH0赋初值

之前第一步的时候我们只是选择了方式1,即选择16个位的寄存器存放初值,现在我们要来给这16个位的寄存器赋初值。

我们怎么让它每隔1毫秒产生中断呢?怎么定时呢?

我们前几节提到过,这个计数器的计数范围是0~65535,每隔一微秒(前面定时器那节已经说过12Mhz的晶振机器周期是1微秒),计数加1,总共定时时间是65535微秒,那我们怎样让它计1秒呢?

每隔1毫秒,让它产生中断每一次中断之后,我们再来计数,中断1000次的时候,就是1s。

时间换算:

       1s【秒】 = 1000ms【毫秒】
  1ms【毫秒】 = 1000μs【微秒】
   1μs【微秒】 = 1000ns【纳秒】
  1ns 【纳秒】= 1000ps【皮秒】

首先我们先给它定一毫秒产生中断。

如果一开始给它赋值64535,那64535离计数器溢出差值1000(微秒),所以计时时间为1ms。

那么我们想要64535这个初值给T0定时器,首先将64535换算成二进制给到T0的高八位TH0和低八位TL0(TH0和TL0都是八个位的寄存器,只能存放256

所以我们可以这样赋值:

为什么这样写就可以把64535的高八位和低八位取出来呢?

因为64535在寄存器当中的数据是十六位的,

我们可以类比一下十进制,十进制的取值范围是0~99,正好100个数,比如说123这个数,我们想要取出它的最高位和它的余数,那么我们就可以123/100=1,123%100=23。

同理,八个位的寄存器的存放数值是256,想要取出64535十六进制的高八位和低八位和就可以写成64535/256=高八位,64535%256=低八位。

现在整个定时器部分就配置好了。

2.中断系统部分的配置步骤

第一步,给ET0赋值

ET0=1就打开开关

第二步,给EA赋值

把总中断打开EA=1

第三步,给PT0赋值

PT0默认等于0,但我们要写上

以上这样就配置完了,

这个子函数也就完成了,我们来调用一下。

到这里这个定时器就可以工作了,那定时器溢出之后,也就是闹钟响了之后,我们要干嘛呢?

二,中断函数

我们还要写一个子函数,让闹钟响了之后,要跳转到这个子函数来,执行中断任务。

为什么要写一个中断函数呢?

也就是定时器初始化之后,

过了一个毫秒while(1){},中断一过来,程序就会从while(1){}跳转到中断函数里面来,等中断函数执行完之后,程序再回到while(1)里面去。

其实我们是根据这个程序流程图的逻辑来写程序的:

主程序在执行的过程中来了一个中断,主程序就跳转到中断函数,等执行完中断再跳转会主函数中。

这个中断函数的形式是这样的:

前面定时器那一节讲过这个子函数的书写规则了,不懂的话可以去看看。

这里我们需要记住对应的中断号,芯片手册上也列出了中断号:

现在我们把这整个程序下载到单片机里面来验证一下。

现在看还是什么现象都没有的

怎么证明它的确是在执行这个函数了呢?

可以在中断函数里点亮一个灯看看

可以发现,到目前为止我们的主程序中还没有调用这个函数的。

如果中断真的过来了,那P2_0=0;这句代码肯定执行,它一执行,开发板上的这个灯就会点亮,所以我们先这样验证主程序是不是过来了,稍后再验证时间。

我们看到D1的确亮了。

这个中断函数根本没有执行,只是跟了一个尾巴(interrupt 1)定时器过来之后,它就点亮了,就说明程序真的跳转到这个地方来执行了。

定时器计算器生成代码工具

这里我们的代码还没有结束,先介绍一个非常好的方法可以省去我们的敲代码的时间!

在STC上找到定时器计算器。

可以看到这里有已经写的框架,我们只需要选择参数即可

根据我们选择的工作模式和开发板的资源设置正确的参数:

为什么选择定时器时钟是12T呢?

这里就是我们前面几节说的这里,我们这节主要选择的工作流程是12T。

怎么让它拨到6T呢?

只要在这里打勾就是6T模式,没有打勾就是12T模式,但是我们一般是用12T模式。

最后把设置好的代码复制下来

改造一下:

因为89系列没有AUXR这个寄存器,所以删掉这一行

然后这两句代码是因为TMOD=0x01这种写法只适合用TMOD的高四位或者低四位时。

当高四位和低四位同时应用的时候,因为TMOD是不可位寻址,最好是优化成:

TMOD&=0xF0;//表示把TMOD的低四位清零,高四位保持不变,TMOD&1111 0000

TMOD|=0x01;//表示把TMOD最低位置1,其他位保持不变

然后这两句写的和我们自己写的这两句不一样

我们自己写是这样:

其实我们写成的这样会有一微秒的差别。

可以验证一下它生成的这种写法是不是跟我们写的结果一样,

用计算机算一下

取整是252,转换成16进制就是FC

说明我们的写的和它生成的结果是一样的

再验证一下低四位:

余23

23换成16进制是17

说明我们配置的低四位比它生成的低四位少了1微秒

所以我们可以把自己写的这句代码改成+1这样:

可以直接用它生成的形式也可以!

然后他还缺少这三句,我们把自己写的加上

最后我们把代码优化成这样(分模块化来写),每一行代码几乎都有注释了,这里就不再赘述:

main.c文件:

Timer0.c文件:

Timer0.h文件:

下载后的效果:

D1在以1秒为间隔在闪烁

说明我们的定时器程序已经没有错误了。

按键控制流水灯代码演示

接下来开始演示按键控制流水灯的程序:

同样分文件来写,创建Key.c和Key.h文件

然后把之前矩阵键盘那一节写好的Delay.c和Delay.h文件复制到本节的程序文件中

然后再添加进来

然后main.c文件改成:

Timer0.h文件没变:

Timer0.c文件也没变:

Key.h文件

Key.c文件

运行后的效果:

LED正在以500ms位间隔向右移动,随便按下一个独立按键后,移动方向变为向左移动。

时钟代码演示

最后开始演示时钟的程序:

新创建一个工程

写上框架

然后把LCD1602调试工具那一节的Delay.c,Delay.h,LCD1602.c,LCD1602.h文件复制到刚刚新创建的工程文件里面来,然后点击添加。

添加进来

同样操作,再把本节前面按键控制流水灯的Timer.c和Timer.h文件添加进来

编译后无错误,但是有9个警告

嫌警告碍眼可以点击这里忽略警告

再次编译,无错误,无警告

然后怎么调用这些函数的话都在之前相关章节讲过了,不懂的伙伴去翻我的单片机专栏里的文章看看。这里就不再赘述。

添加进来的文件不用修改什么,直接看本节主程序main.c调用写好的代码,每一行代码基本都有注释。这里就不再赘述。

看看效果:

观察23:59:59再计一秒后开始进位,全部变成00:00:00

然后从1开始计:

以上就是本节全部的代码演示。

本节全部的源码都放在评论区了,自取!

有问题的欢迎评论区留言或者私信。

  • 14
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vera工程师养成记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值