51单片机定时器用法之1秒定时程序设计
动画演示
在我们的DIY电子时钟里,需要用到单片机定时器来做秒的显示,说是显示,其实就是实现数码管上“:”点的闪烁。这里初步定义为每秒亮1次,亮0.5秒,灭0.5秒。实现显示秒的功能。这里也可以用DS1302的秒数据来做,但是实现起来麻烦,达到一样的效果,我们追求的是程序越简单越好,所以在此我们用单片机定时器来实现。
我们DIY时钟板子上的单片机为STC15W408AS,单片机自带IRC可调时钟和搞可靠复位,为了降低功耗(工作频率越低,功耗越小),本时钟采用12M的工作频率(烧写程序是在软件上选择),那当定时器工作在12T模式下时,一个机械周期就是1us。
接下来我们就该看看单片机的数据手册了。以下是今天我们需要关注的寄存器:
TCON位定义
TMOD寄存器位定义
T0工作方式设置
TCON为定时器T0和T1的控制寄存器,可以位寻址(直接操作位);TMOD是T0、T1工作方式控制寄存器,不可以位寻址(只能操作寄存器),高四位控制T1,低四位控制T0;定时器的工作方式由TOMD寄存器中的M1和M0选择,具体如上图。
本例中我们要用T0实现1秒的定时时间,这里我们用T0工作在方式0,也就是16位的自动重载方式(传统的51单片机只有8位的自动重载,需要做高精度的定时时最好用自动重载方式)。我们不需要外部中断来开启定时器,所以GATE位=0,T0工作在定时模式,CT=0,所以我们TMOD寄存器的值为0x00;在TCON寄存器里和T0相关的位有TF0和TR0;TF0=0:T0中断标志位,当定时器中断产生是,TF0自动置位,CPU相应中断后硬件自动清零;TR0=1:开启定时器,相当于定时器的开关。
除了这些寄存器外,定时器溢出后,也会产生中断,所以还需要去设置中断部分:
EA=1:,开启总中断,相当于中断总开关;ET0=1;开启定时器T0中断,相当于中断的子开关,只有中断的总开关和相应的子开关都开启后,CPU才能相应中断信号,具体请看中断部分数据手册。我们用的STC15W系列单片机属于增强型单片机,为了和传统51单片机兼容,还专门设有一个寄存器AUXR,此寄存器可设置T 0工作在1T还是12T模式,此处我们让T0工作在12T模式下,AUXR=0x00。最后就是定时器的初值寄存器了,我们需要定时的时间是500ms,16位的定时器再12M频率下最大定时时间为65535us,而我们需要的是500ms,明显达不到,那我们就需要做组合定时的方式,这里我们设定定时器的中断频率为10ms,那我们中断1次后在中断函数里将某个变量加1,当变量加到50的时候就是500ms,当变量加到100的时候就是1s了。这就是我们实现1s定时的思路。
具体实现程序如下:(因头条原因,代码图片无法加入,需要请移步关注微信公众号)
如上图中程序所示,定时器初始化时设置T0位16位自动重载模式,工作在12T模式,初值10ms,开启定时器,开启中断。这样定时器就工作了;在定时器中断函数里,每次进入中断后我们就给变量T_a自加1,当变量小于50的时候(小于500ms),让D=1(D即为我们电路中控制秒显示的那两个点,高电平有效),大于50小于100的时候D=0,关闭秒显示。这样一来就实现了秒显示在1秒内亮500ms,灭50ms了。上图中中断函数名后面的interrupt 1这是中断函数的入口地址,C语言中叫中断号(为小白说明,老司机略过),具体的个中断对应的入口地址对照表如下图(部分):
中断号对照表
单片机实例分享,自定义提醒闹钟
图14.1 电子钟
想起那时刚学习单片机,仅仅会写几段汇编代码。后来的几个月,自己也学写了一个电子钟程序,不过做得非常简陋,也没使用什么时钟芯片,仅仅通过单片机的定时器来累计计时,功能上实现了时、分、秒的显示以及简单的闹钟功能。不过,我还真是怀念以前学习单片机的美好时光,也很高兴那时自己能专心学习单片机。后面我也做了一款像样的电子钟(见图14.1),在下面的内容里,我会和大家分享制作它的过程。
零件清单
零件清单是制作这款电子钟的基本元件,还有一些边角料,不再列出。从零件列表(见表14.1)中大家可以看出,整体的成本不超过80元。不过,最近这段时期,AVR单片机涨价厉害,在网上也要18元左右才能买到。如果液晶屏在淘宝网上购买的话,建议以关键字ST7565搜索,这样才能搜索到ST7565控制器的128×64液晶屏。至于其他零件比较常用,一般电子市场都能购买得到。
图14.2 零件全家福
表14.1 材料表
电路原理
如图14.3所示,微控制器(MCU)我选择了AVR单片机的Atmega8,因为比较熟悉。它的程序存储器大小为8KB,数据RAM大小为1KB,工作电源电压范围为2.7~5.5V,最大工作温度为+85℃,最小工作温度为-40℃。时钟芯片选择DS1302,DS1302是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5~5.5V。采用三线接口与MCU进行同步通信。最后,通过使用SD卡的SPI模式和单片机的SPI接口连接,进行数据交换。SD卡相当于容量很大的SPI接口的FLASH,在制作过程中,也可以替换成大容量的FLASH芯片。128×64液晶仅仅需要4根线和单片机连接。由于使用的控制器是ST7565,它不带中文、英文字库,因此需要自己建立字库。但这种液晶屏价格便宜,外观也很小巧。我购买的这款液晶屏,背光是橘黄色的,到了晚上会发出迷人的光泽。
图14.3 电路原理图
工作原理
在制作之前,我先介绍一下它的工作原理。控制芯片使用的是AVR的atmega8单片机,简称M8。大家也可以使用熟悉的51单片机(程序可以到本书配套光盘中下载,大家根据需要自己修改或移植)。程序通过读取SD卡内的TXT文件,显示每天需要提醒的内容。因此,可以通过电脑,方便地修改提醒的内容,如节日、生日、纪念日等。不必再为了修改液晶屏上的提醒内容而特意修改程序代码,仅仅通过编辑TXT文件即可。SD卡是通过它的SPI接口和单片机进行数据交换。液晶屏使用的是串口128×64的黑白液晶屏,控制器是ST7565,它和单片机连接也仅仅需要4个I/O口。时钟芯片使用的是DS1302,大家对它应该不陌生吧。时钟芯片通过3个I/O口和单片机连接,电源使用USB接口的5V电源,经过1117-3.3电源稳压芯片转换成3.3V电压,供给单片机、液晶和SD卡使用,大家也可以使用3.3V的电源直接供电。这款电子钟通过两个按钮实现时间和闹钟的设置。当时钟正常运行时,第2个按钮可以单独开启闹钟或关闭闹钟。
使用方法
(1)在计算机的WinXP系统下把SD卡格式化成FAT文件系统。
(2)先复制字体到SD卡内,这样才能在液晶上显示中文。
(3)在根目录下新建“提醒.txt”文本文件。
(4)在文件内写入一行内容,如下:****-02-13"明天是情人节",这样每年的2月13号,电子钟就会提醒你明天是情人节了。
大家会发现,这款电子钟没有农历的显示,如果要显示农历怎么办呢?如果朋友的生日是按农历来算的怎么办呢?其实也挺简单的,通过在文件中写入公历和农历的对应时间关系即可。如:2010-02-13"农历2009-12-30"。注意:*号是通配符,表示任意的意思。例如:2010-**-**"虎年",表示2010年的任意日期,都会显示虎年。
字库的制作及使用
这是本次制作的知识要点之一。GB2312是中国国家标准简体中文字符集,全称《信息交换用汉字编码字符集·基本集》,又称GB0,由中国国家标准总局发布,1981年5月1日实施。GB2312编码通行于中国大陆,新加坡等也采用此编码。中国大陆绝大多数中文系统和国际化的软件都支持GB2312。
GB2312标准共收录6763个汉字,其中一级汉字3755个,二级汉字3008个;同时收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个字符。GB2312的出现,基本满足了汉字的计算机处理需要。GB2312中对所收汉字进行了“分区”处理,每区含有94个汉字/符号。这种表示方式也称为区位码。
01~09区为特殊符号。
16~55区为一级汉字,按拼音排序。
56~87区为二级汉字,按部首/笔画排序。
10~15区及88-94区则未有编码。
举例来说,“啊”字是GB2312之中的第一个汉字,它的区位码就是1601。
在电脑上的TXT文本文件中,每个汉字及符号以两个字节来表示。第一个字节称为“高位字节”,第二个字节称为“低位字节”。为了和原有的ASCII码兼容,“高位字节”使用了0xA1~0xF7(把01~87区的区号加上0xA0),“低位字节”使用了0xA1~0xFE(把01-94加上0xA0)。由于一级汉字从16区起始,汉字区的“高位字节”的范围是0xB0~0xF7,“低位字节”的范围是0xA1~0xFE,占用的码位是72×94=6768。其中,有5个空位是D7FA~D7FE。例如,“啊”字在文件中会以两个字节“0xB0(第一个字节)0xA1(第二个字节)”储存。
制作步骤
1 按图在洞洞板上安插好各个元件,并插上已经烧录好程序的芯片。
2 根据电路原理图,依次连接导线
3 将各个组件准备好了后,就可以组装起来。
4 最后插上USB电源,就可正常工作了。
DIY的过程不仅仅是制作过程,还是一个让作品更美好的过程,为此,我又开始了这个自定义提醒闹钟的美化过程。
将钢丝弯曲成如图的形状,在钢丝上拧上螺丝,在万用板上也拧上螺丝。
用内六角扳手、普通扳手拧紧螺丝。
那么如何定位字库中的点阵数据呢?文件编码的区码范围是从0xA1(十六进制)开始,对应区位码中区码的第一区,第二个字节为汉字的位码,范围也是从0xA1(十六进制)开始,对应某区中的第一个位码。就是说,将汉字编码减去0xA0A0就得到该汉字的区位码。例如,汉字“啊”的机内码是十六进制的“0xB0A1”,其中前两位“0xB0”表示编码的区码,后两位“0xA1”表示编码的位码。所以“啊”的区位码为0xB0A1-0xA0A0=0x1001,将区码和位码分别转换为十进制16和01,得到汉字“啊”位于第16区的第1个字的位置,那么点阵数据在文件中的位置为第“32×[(16-1)×94+(1-1)]=45120”以后的32个字节。这就是“啊”的显示点阵需要的字节数据了。其中,32为16×16点阵的取模字节数,表示32字节大小。单片机通过取这连续的32个字节,送到LCD的相应位置,就能正确显示汉字、图形符号了。
最后,使用字库生成工具,就能生成自己需要的字库了。这样的工具软件在网上有许多,请自行选择。我使用未注册的“汉字取模字库生成”小工具,使用次数有一定的限制,但偶尔用于生成字库还是够用的。由于这款液晶显示数据是1列(8个点)为一个地址单位的,而不是1行(8个点)或点地址为单位。因此,取模时需使用纵向(列)取模方式取模,这样方便后期程序的编写。当然也可以直接选择“@宋体”这类字体。通过工具预览后,你会发现,这种字体旋转了90°。点击生成字库,在弹出的菜单中输入的路径和文件名。按“确认”后就会生成需要的字库了,注意后缀名为.dot。程序读取经过旋转后的32字节字体数据,即点阵列数据,就能显示一个汉字了。
存储整个字库数据是个难点,GB2312汉字库有200多字节的大小,单片机的FLASH可是没有足够的空间用来保存它。那么怎么办呢?其实,方法也挺多的。有一种实用、简单、方便的方法就是外接FLASH存储芯片。如SST25VF020、AT45DB161等,它们都是串行接口,可以节省许多I/O,读取速度也够快,但增加了制作成本。还有一种方法,可以直接放在SD卡内,但程序会复杂很多。同时,显示字体的速度也没外接FLASH快。不过最后我还是选择了第2种方法,以后的小制作中再试试第1种方法。
为了让电脑和单片机互相交换数据容易些,需要把SD卡格式化成FAT文件系统,然后单片机解读SD卡格式化后FAT文件系统,在此基础上再读取txt文件,最后调用相应的字库数据在液晶屏上显示。具体如何实现,请读者朋友自行分析源代码。源代码可到本书配套光盘上下载。
编程说明
当我烧录完程序后,迫不及待地要运行这个电路了。把电子钟插上电源后,程序会先初始化硬件(液晶、SD卡和时钟芯片)。之后会读取单片机EEPROM里的闹钟信息,没有的话会新建初始化内容,并写入EEPROM。最后,液晶就会分4行显示时间、日期、星期和闹钟。当有提醒信息时,闹钟时间和提醒的内容会交替闪烁。在程序的循环体内,程序会定时读取SD卡内的TXT文件,如果TXT文件内定义的日期和时钟芯片的日期一致,那么单片机会读取文本文件内对应的显示内容,并在液晶的第4行显示。如果没有相等的日期,单片机会显示默认的字符串“MADEBYZBJ”,大家可以改成自己定义的字符串。
电子钟的右侧有4个按钮,但是本次制作只使用了上面2个按钮,另外2个按钮功能未用。这4个按钮的一端都连到了单片机的中断引脚,并把这个中断引脚设置为上拉,在程序中等待下降沿中断。按钮的另一端和单片机的4个普通I/O连接,这4个I/O设置为低电平。当按钮按下时,就会引发下降沿中断,此时程序修改中断,引为低电平,并把4个普通I/O口上拉,再分别读取4个引脚的电平状态。如果,某个引脚读到低电平,就可以判断对应的这个按钮按下了。最后,等待按钮的释放,不断循环此过程。
当时钟在运行状态时,按第1个按钮,将会进入时钟设置状态,再次按下第1个按钮,就会进入下一个设置选项,以此类推,直到退出最后一个选项(注意闹钟关闭状态,不会进入闹钟设置选项),这样电子钟就会退出设置状态,再次进入运行状态了。电子钟在设置状态下,设置的项目会反显,可以通过按第2个按钮,改变设置的数值。
当时钟在运行状态时,按下第2个按钮,闹钟将会开启或关闭,这取决于原来的状态。在液晶屏上会显示相应的闹钟状态信息。闹钟数据虽然保存在M8单片机的EEPROM中,但不会直接使用。当单片机上电运行时,会自动载入RAM中使用,这样是为了延长EEPROM的使用寿命。但当RAM中的闹钟数据改变时,修改的数据才会同步更新,写入EEPROM。程序会比较RAM中的闹钟时间和时钟芯片的时钟是否一致,当两者一致时,闹钟就会“嘀嘀”地叫了。至于鸣叫多久,大家可以根据自己的需要修改程序中的设置。
更多源程序可以到qq群657864614进行下载!
有没有因为想买一本书,因为价格偏高而犹豫?现在我来帮你解决这个问题,把书名作者直接告诉我,我来帮你找,通常价格均为1元,难一点的也就几块钱,先查询,后付款,诚信经营! 代找各种电子书电子图书教材文献查找代查代找中文pdf格式-淘宝网
相关问答
51 单片机 30秒倒 计时 ,用数码管显示的,c程序,元件只有at89c51和数码管,没有其他的?数码管一般是电流驱动,跟电压关系不大,但是电压在数码管灭了时候会加到IO口上(即此时电压和IO口电压一致或略高),而IO口是不能提供10V电压的,可以找找双电...
51 单片机 秒表程序[回答]这个程序写的太乱了执行的顺序是先定义秒等一些寄存器,然后清零,并定义定时初值,开显示。再打开定时器中断,定时到,中断秒寄存器加1,加到10时清...
用51 单片机 做秒表,按钮按下停止 计时 ,再按一次接着 计时 -ZOL问答定时器0.01秒刷新,数码管动态显示。用一个变量存当前时间的数据,点开始键打开定时器,暂停关闭定时器就行了。有用(0)回复isacguan很基础的单片机知识,自己...
单片机 倒 计时 秒表程序由什么组成?主要由定时器控制程序组成。主要由定时器控制程序组成。
如何知道 单片机 程序运行一周时间?进入DEBUG状态,右下角有显示。你需要开始计时时,右击选择reset,然后执行你需要测试的程序部分就可以了。进行软件仿真前需要设置正确你的晶振频率,在option,...
51 单片机 t1定时方式是um有误差吗?你好,51单片机的T1定时方式是通过定时器1来实现的,可以使用两种模式:方式1和方式2。无论是哪种方式,都会存在一定的误差。在方式1中,T1定时器使用内部时钟...
keil写程序 单片机 二位数码管显示倒 计时 ?管显示,就应该先画仿真图,或用...其实,这与keil没什么关系,主要是取决于用什么语言写程序,是汇编还是C语言,keil不过是用来编译的软件。其次,既然是用数码...
老表们,谁清楚,用51 单片机 做电子钟,自动校时方面最简单的...[回答]如果是调时间用个2个按钮就好了。校时的话51就是走不准的一天有误差难免的。这个晶振有关系的,当然你觉得一天误差1-2秒没关系那是可以用51的。推...
c51 单片机 编程 计时 器时为什么要停止 计时 ?如果不停止计时,会出现死循环。如果不停止计时,会出现死循环。
关于MCS-51 单片机 、你们懂得!以下是是MCS-51 单片机 的数字时...[最佳回答]51.h"unsignedcharcodedisptab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83...