制作过程:利用现有的电子元器件,参数选择上可能不是最优的,程序和软件来源于互联网,整理后上传主要是为初学者了解单片机。
在自学单片机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中断 }
复制代码