|
时钟显示时、分、秒,程序和制作较简单,误差每天小于1秒。缺点是断电后不能保存时间。
制作过程:利用现有的电子元器件,参数选择上可能不是最优的,程序和软件来源于互联网,整理后上传主要是为初学者了解单片机。
在自学单片机C语言程序有问题时,可以利用互联网免费的Chat GPT
提问“你是单片机C语言专家,再提出编程或解释程序等问题”。
1、调整时间快慢时,用手机时钟比照,从大往小数值调整,调至个位数时,增加数值1,单片机时钟跑慢;
减少数值减1,单片机时钟跑快,这时误差能控制在两天差1秒左右。
2、整机测试耗电5V,90ma左右,建议用5V充电头供电。
3、按键P1.3确认键,没利用,可用P1.0键代替。
电子元器件:
1、一寸六个共阳数码管LG10016BH。
2、P0是8个段脚;P2是6个位脚。
3、三个按键开关(P1.0调整时间;P1.1调整时间增;P1.2调整时间减)、六个1K电阻、六个S8550三极管和一片STC89C51RC。
附:1、加光敏电阻原理图:利用原程序,加光敏电阻是解决晚上时钟显示太亮。加半可调电阻(因没有现成大的半可调电阻,用5K的半可调电阻
和10K电阻串联代替)解决光线太暗时,数码管不会全灭,调整半可调电阻显示最低亮度。
制作出来的实物图如下:
单片机源程序如下:
- //采用8位数码管动态显示程序
- //使用AT89C51单片机,12MHz晶振,P0输出字段码,P2口输出位选码
- //用共阳极LED数码管,key0为调时分位选择键,key1为加1键,key2为减1键,key3为确定键
- #include "reg51.h"
- //包含头文件
- #define char unsigned char
- //定义无符号字符型
- //char code dis_7[12]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0xff}; //共阴极
- char code dis_7[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf}; //共阳极LED数码管"0~9","-"的字段码
- //char code scan_con[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
- char code scan_con[8] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f}; // P2口
- //位选择码
- char data dis[8]={0x00,0x00,0x0a,0x00,0x00,0x0a,0x00,0x00}; //00-00-00
- //显示缓冲区,时、分、秒初始为0,0x0a为"-"的编码
- char data timedata[3]={0x00,0x00,0x00}; //初始化
- //分别为秒、分和小时的值
- char data ms50=0x00,con=0x00,con1=0x00,con2=0x00;
- //定义四个按键
- sbit dian=P0^7;
- sbit key0=P1^0;
- sbit key1=P1^1;
- sbit key2=P1^2;
- sbit key3=P1^3;
- //1ms延时函数
- delay1ms(int t)
- {
- int i,j;
- for (i=0;i<t;i++)
- {
- for(j=0;j<120;j++);
- }
- }
- keyscan()//按键处理函数
- {
- EA=0; //关总中断
- if (key0==0)//判断第一个按键是否按下
- { //按键消抖
- delay1ms(10);
- while (key0==0);//再次判断按键是否按下
- con++;
- TR0=0;
- ET0=0; //关定时/计数器,关T0中断
- if (con>=3)
- {
- con=0;
- TR0=1;
- ET0=1;
- }
- }
- if (con!=0)
- {
- if (key1==0) //如果第二个按键按下
- {
- delay1ms(10);
- while (key1==0);
- timedata[con]++;//加一功能
- if (con==2)
- con1=24;
- else con1=60;
- if (timedata[con]>=con1)
- {timedata[con]=0;}
- }
- }
- if (con!=0)
- {
- if (key2==0)
- //如果第三个按键按下
- {
- delay1ms(10);
- while (key2==0);
- timedata[con]--;
- //减一功能
- if (con==2)
- con2=23;
- else con2=59;
- if (timedata[con]<=0)
- {
- timedata[con]=con2;
- }
- }
- }
- if(key3==0)//如果第四个按键按下
- {
- delay1ms(10);
- while(key3==0);
- EA=1;
- TR0=1;
- ET0=1;
- }
- EA=1;//开总中断
- }
- //数码管显示函数
- scan()
- {
- char k;
- dis[0]=timedata[0]%10;
- dis[1]=timedata[0]/10;
- dis[2]=timedata[1]%10;
- dis[3]=timedata[1]/10;
- dis[4]=timedata[2]%10; //【1】显示"分";【2】显示"时";【0】显示"秒"
- dis[5]=timedata[2]/10; //【1】显示"分";【2】显示"时";【0】显示"秒"
- for (k=0;k<8;k++)
- {
- P0=dis_7[dis[k]];
- if (k==1|k==2|k==3|k==4)
- {
- dian=0;
- }
- else
- {
- dian=1;
- }
- P2=scan_con[k];
- delay1ms(1);
- P2=0x00; //数码管消隐
- P2=0xff; //数码管消隐
- }
- }
-
- //主函数
- main()
- {
- //TH0=0x4c;
- //TL0=0xb0;
- TH0=(65536-52615)/256; //12M,52615数值越大,走时越慢;数值越小,走时越快。
- TL0=(65536-52615)%256; //12M,52615数值越大,走时越慢;数值越小,走时越快?
- TMOD=0x01;
- //选择工作方式1
- ET0=1;
- TR0=1;
- EA=1;
- while (1)
- {
- scan();
- //调用数码管显示scan()子函数
- keyscan();
- //调用按键处理keyscan()子函数
- }
- }
- //定时器/计数器T0中断服务函数
- void time_intt0(void) interrupt 1
- {
- ET0=0;
- TR0=0;
- //TH0=0x4c; //12M 应该是TH00=0x4c
- //TL0=0xb0; //11.0592M 应该是TL00=0x00
- TH0=(65536-52615)/256; //12M,52615数值越大,走时越慢;数值越小,走时越快?
- TL0=(65536-52615)%256; //12M,52615数值越大,走时越慢;数值越小,走时越快?
- TR0=1;
- ms50++;
- if (ms50==19)
- {
- ms50=0x00;
- timedata[0]++;
- if (timedata[0]==60)
- {
- timedata[0]=0;
- timedata[1]++;
- if (timedata[1]==60)
- {
- timedata[1]=0;
- timedata[2]++;
- if (timedata[2]==24)
- {
- timedata[2]=0;
- }
- }
- }
- }
- ET0=1;
- //开T0中断
- }
复制代码
|
评分
-
查看全部评分
|