如何突破单片机教学中简易数字钟教学难点
2017-04-26张桂铭
张桂铭
摘 要:本项目教学难点是:1、定时器的应用;2、时、分、秒如何计数及怎样显示在数码管上。本例没有应用时钟芯片,而是利用51系列单片机的定时器T1的自动重装的方式1功能实现了精确的1ms和1s的定时基准的产生,其中1ms为最基本的定时时基,用于6位共阴动态LED的扫描刷新之外,还通过sCounter软计数变量用于1000次的1ms计数产生1s 精确的秒定时时基,用于基本计数时钟源。本例采用云龙单片机实验板及C语言编程实现。
关键词:数字电子钟;精确定时;数码管动态扫描;时钟显示的原理
在中职生单片机教学中需要突破的教学难点很多,而且涉及C语言编程,电子元件及模块的应用,电路原理等多项问题,相对于中职生来说,在兴趣的培养教学方面和简单易懂的原则教学问题上都有着较大的挑战,是比较值得钻研的教学难题,固此在这阐述一下我在教学中遇到的问题,为进一步探讨和简化中职生单片机教法吸取经验。
本例学生用到的实验板原理图如下:
一、数码管图块
二、单片机图块
三、数码管段选和位选控制的锁存器图块
实例中单片机晶振选择的频工作频率为12MHz,定时器的最小计数时间为1us,调试参考程序如下:
#include
sfr P0M1 = 0x95; //--- 新增的功能寄存器地址声明 ---
sfr P0M0 = 0x96;
unsigned char code LEDSEG[] =
{0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00,};//--- 显示0~9,A~F笔段代码表 ---
unsigned char code LEDDIG[] =
{ 0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,};
unsigned char LEDBuffer[6];//--- 定义的显示缓冲区 ---
unsigned char LEDPointer; //--- 定义的扫描计数变量 ---
unsigned int sCount; //--- 定义的秒计数器变量 ---
unsigned char Second; //--- 定义的秒变量 ---
unsigned char Minute; //--- 定义的分变量 ---
unsigned char Hour; //--- 定义的时变量 ---
void main(void)
{
P0M1 = 0x00; //--- 配置P5端口的P0.0~P0.7为推挽输出模式 ---
P0M0 = 0xFF;
TMOD = 0x10; //--- 配置T1为定时模式,工作于方式1,16位装载模式 ---
TH1 = (65536 - 1000) / 256; //--- 初始化T1定时1mS ---
TL1 = (65536 - 1000) % 256;
TR1 = 1; //--- 啟动T1工作 ---
ET1 = 1; //--- 使能T1中断 ---
EA = 1; //--- CPU开中断 ---
while(1)
{
}
}
sbit dula=P2^6;
sbit wela=P2^7;
//--------------------------------------------------------------------------------------
//--- 定时器T1溢出中断服务程序 ---
void T1_ISR(void) interrupt 3
{
TH1 = (65536 - 1000) / 256; //--- 初始化T1定时1mS ---
TL1 = (65536 - 1000) % 256;
dula=1;
P0 = LEDSEG[LEDBuffer[LEDPointer]];//数码管显示段选码
dula=0;
wela=1; //--- 显示数字 ---
P0 = LEDDIG[LEDPointer];
wela=0; //--- 数码管的位选段选择 ---
LEDPointer++; //--- 动态扫描计数变量加1 ---
if(sizeof(LEDBuffer)==LEDPointer)LEDPointer = 0; //--- 所有数码管扫描完,计数归0 ---
sCount ++; //--- 秒计数变量加1 ---
if(1000 == sCount)
//--- 定时1秒时间到 ---
{
sCount = 0; //--- 秒计数变量清0
Second ++; //--- 秒变量加1 ---
if(60 == Second //--- 计满60秒 ---
{
Second = 0; //--- 秒变量清0 ---
Minute ++; //--- 分变量加1 ---
if(60 == Minute)//--- 分计满60 ---
{
Minute = 0; //--- 分变量清0 ---
Hour ++; //--- 时变量加1 ---
if(24 == Hour)
Hour = 0;
//--- 时计满24则时变量清0 ---
}
}
LEDBuffer[5] = Second % 10;
//--- 秒变量装显示缓冲区 ---
LEDBuffer[4] = Second / 10;
LEDBuffer[3] = Minute % 10;
//--- 分变量装显示缓冲区 ---
LEDBuffer[2] = Minute / 10;
LEDBuffer[1] = Hour % 10;
//--- 时变量装显示缓冲区 ---
LEDBuffer[0] = Hour / 10;
}
}
其中定时器中断初始化程序应完成如下工作:
1.对TMOD赋值,以确定T0和T1的工作方式。
2.计算初值,并将其写入TH0、TL0或TH1、TL1。
3.使TR0或TR1置位,启动定时/计数器定时或计数。
4.中断方式时,则对IE赋值,开放中断。
5.开总中断。
TMOD = 0x10; //---对TMOD赋值,配置使用定时器T1,工作于方式1,因为单片机使用12MHz 晶振,机器周期为1us。
TH1 = (65536 - 1000) / 256; //定时器装初值,1000us=1ms
TL1 = (65536 - 1000) % 256;
TR1 = 1; //--- 启动定时器T1
ET1 = 1; //--- 使能定時器T1中断
EA = 1; //--- CPU开中断(开总中断)
以上是定时器初始化在程序的编写上的5个步骤, 在C语言程序的编写中是按这5个对应的步骤实现的,其中对特殊功能寄存器的设置及特殊功能寄存器中相应位的开启请注意查阅相关知识点。例于对TMOD的赋值
是对上面表格的各位的设置实现的。而开定时器是对下表TCON寄存器TR1的设置。
因此关于单片机定时器的应用我本人认为还要利用多媒体投影,边复习前面的内容,边编写相应的程序,否则学生也许越听越感觉困难,谈不上突破这一难点了。
关于数字时钟的时、分、秒如何计数并显示在数码管上也是本例的难点,例 LEDBuffer[5] = Second % 10;
LEDBuffer[4] = Second / 10;
//--- 秒变量装显示缓冲区 ---,是因为这是最后两个数码管,LEDBuffer[4]是秒的十分位,LEDBuffer[5]是秒的个位,所以个位要求余,十分位要求模得以实现。可让学生反复实训调试让该难点得到突破。
单片机原理与应用是对中职学生来说是比较深奥的学科,需要反得实践,反得学习编程和调试,并要结合电子器件的工作原理一步步学习,才能突破一个个难点,从而使知识技能获得一定的进阶。
参考文献:
[1]MCS-51单片机C语言编程100例 孙安青编著;2、云龙单片机 网络教程.