写在前面:以下涉及到的程序及电路图不保证为最优方案,会存在很多不足之处,望谅解。另外,C51的内容是在整理很久之前所学的知识,可能会存在错误,欢迎指正。
正文
学习目标:利用51单片机在数码管上模拟时钟的功能。
学习内容:
- 在8位数码管上同时使用其中的3位并显示不同的数字、字母或字符
- 在数码管上模拟时钟的功能
程序一:数码管简单应用
本次所使用的数码管为8位共阴数码管
源程序
#include "reg52.h"
typedef unsigned char uchar;
typedef unsigned int uint;
#define display_duan P0 //定义数码管段选端口为P0
#define display_wei P2 //定义数码管位选端口为P2
uchar code smg[16] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //定义数码管显示内容0~15(F);
void delay1ms(void) //误差 0us
{
unsigned char a,b;
for(b=199;b>0;b--)
for(a=1;a>0;a--);
}
void main()
{
while(1)
{
display_wei = 0xfe; //选择数码管最右边一位
display_duan = smg[1]; //显示数字1
delay1ms(); //短暂延时,用于刷新数码管
display_wei = 0xfb; //选择数码管从右往左第三位
display_duan = 0x40; //显示字符“-”
delay1ms(); //短暂延时,用于刷新数码管
display_wei = 0x7f; //选择数码管最左边一位
display_duan = smg[7]; //显示数字7
delay1ms(); //短暂延时,用于刷新数码管
}
}
仿真图
如图所示,当运行程序后,数码管将按照程序设定的位置以及内容进行显示。
程序二:数码管显示时钟
源程序
#include "reg52.h"
typedef unsigned char uchar;
typedef unsigned int uint;
#define display_duan P0 //定义数码管段选端口为P0
#define display_wei P2 //定义数码管位选端口为P2
uchar code smg[16] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //定义数码管显示内容0~15(F)
uchar temp_hour = 12,temp_min = 34,temp_sec = 25; //数码管变量-时分秒
uchar temp; //1s计时
void delay1ms(void) //误差 0us
{
unsigned char a,b;
for(b=199;b>0;b--)
for(a=1;a>0;a--);
}
void Init(void) //单片机定时器定义
{
TMOD |= 0X01; //选择定时器0模式1,16位,TR0控制
TH0 = 0X3c; //定时50ms,高8位
TL0 = 0xb0; //定时50ms,低8位
TR0 = 1; //允许计时
ET0 = 1; //溢出中断允许位,置1允许
EA = 1; //打开总中断
}
void Display() //数码管显示函数
{//8位数码管从右往左,位数从低到高
display_wei = 0xfe; //低位第0位,显示秒的个位
display_duan = smg[temp_sec%10]; //除10取余取个位
delay1ms(); //短暂延时,用于刷新数码管
display_wei = 0xfd; //低位第1位,显示秒的十位
display_duan = smg[temp_sec/10]; //除10取整取十位
delay1ms();
display_wei = 0xfb; //低位第2位
display_duan = 0x40; //显示“-”
delay1ms();
display_wei = 0xf7; //低位第3位,显示分钟的个位
display_duan = smg[temp_min%10]; //取余显示个位
delay1ms();
display_wei = 0xef; //低位第4位,显示分钟的十位
display_duan = smg[temp_min/10]; //取整显示十位
delay1ms();
display_wei = 0xdf; //低位第5位
display_duan = 0x40; //显示“-”
delay1ms();
display_wei = 0xbf; //低位第6位,显示小时的个位
display_duan = smg[temp_hour%10]; //取余显示个位
delay1ms();
display_wei = 0x7f; //低位第7位,显示小时的十位
display_duan = smg[temp_hour/10]; //取整显示十位
delay1ms();
}
void main()
{
Init(); //调用定时器定义函数
while(1)
{
Display(); //调用数码管显示函数
}
}
void timer0() interrupt 1 //定时器0中断程序,定时器0优先级为1
{
TH0 = 0X3c; //定时50ms,高8位
TL0 = 0xb0; //复位TH0和TL0
temp++;
{
if(temp > 19) //计时1s后
{
temp = 0; //temp归零
temp_sec++; //同时秒变量自增
if(temp_sec > 59) //秒变量计时60秒
{
temp_sec = 0; //秒变量归零
temp_min++; //同时分钟变量自增
if(temp_min > 59) //分钟变量计时60分
{
temp_min = 0; //分钟变量归零
temp_hour++; //同时小时变量自增
if(temp_hour > 23) //小时变量计时24小时
{
temp_hour = 0; //小时变量归零
}
}
}
}
}
}
仿真图
如图所示,当程序运行时,初始显示为12时34分25秒,并且该时钟会随时间的推移自动计时,以实现时钟的功能。
当然,该时钟还可以在加上年月日的功能,具体的实现方式与时分秒的实现方式相同,当然如果想要将年月日时分秒显示在1个8位数码管上,还需要加上切换功能,可以加一个自动切换功能,具体可以像这样做:将年月日写在函数1里,比如命名为Time1(),将时分秒写在函数2里,比如命名为Time2(),此时同时将两个函数放入主函数的while(1)循环中,并且在两函数中间加上一个时间稍微长一点的延时,比如10s,这样就可以实现1个数码管既显示年月日,又显示时分秒。当然这只是建议,具体还要各位自己实验。