基于C51单片机的电子表(内附完整程序源码)
- 格式:doc
- 大小:6.17 MB
- 文档页数:35
基于51单片机的数码管时钟(带闹钟调时秒表)/**************************************************************** ************ ** *********************************************************** ** * * ** * * ** * 基于51单片机的数码管时钟程序* ** ** * * ** * * *********************************************************** ** ** ************************************************************ ****************/#include<stdio.h>#define uint unsigned int#define uchar unsigned charsbit dula=P2^6; //申明u1锁存器的锁存端sbit wela=P2^7; //申明u2锁存器的锁存端sbit key1=P3^0; //功能键sbit key2=P3^1;//增大键sbit key3=P3^2;//减小键sbit key4=P3^3;//秒表查看键sbit beep=P2^3;//蜂鸣端uchar num,num1,num2,numm;uchar numf,num,nums,num;uchar s,s1,f,f1,m,m1;uchar ns,ns1,nf,nf1;uchar numns,numnf;uchar dingshi;void display(uchar m,uchar m1,ucharf,uchar f1,uchar s,uchar s1);void display1(uchar nf,uchar nf1,uchar ns,uchar ns1);void key();void key1();void alram();void di();void delayms(xms);void T0_time() interrupt 1;void miaobiao();uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x77,0x7c,0x39,0x5e,0x79,0x71};/*********************************************************主函数void main()*********************************************************/int main(){TMOD=0X01;TH0=(65536-46080)/256;TL0=(65536-46080)%256;EA=1;ET0=1;TR0=1;nums=12;numf=0;num2=0;num=0;while(1){if(dingshi==0){keyscan();display(m,m1,f,f1,s,s1);alarm();}else{miaobiao();keyscan1();display1(nf,nf1,ns,ns1);}}return 0;}/********************************************************* 蜂鸣器函数di()*********************************************************/ void di(){beep=0;delayms(100);beep=1;}/********************************************************** 按键调时函数key()**********************************************************/ void keyscan(){if(key1==0){delayms(10);display(m,m1,f,f1,s,s1);}}}/********************************************** 按键设定闹钟函数keyscan1();***********************************************/ void keyscan1(){if(key1==0){delayms(10);if(key1==0){ numns++;if(numns==24);numns=0;while(!key1);di();display1(nf,nf1,ns,ns1);}}if(key2==0){delayms(10);if(key2==0){ numnf++;if(numnf==24);numnf=0;while(!key2);di();display1(nf,nf1,ns,ns1);}}if(key3==0){delayms(10);if(key3==0){dingshi=0;while(!key1);di();display1(nf,nf1,ns,ns1);}}}/********************************************************* 闹钟函数alram()*********************************************************/ void alram(){if((nums==numns)&&(numnf==numf))beep=0;}/*********************************************************秒表函数miaobiao()*********************************************************/ void miaobiao(){if(key4==0){delayms(100);if(key4==0){while(!key4);di();displaym(uchar m,uchar m1);}}}/********************************************************* 正常显示函数display()*********************************************************/ void display(uchar m,uchar m1,ucharf,uchar f1,uchar s,uchar s1){dula=1;P0=table[m1]//秒位第1位dula=0;PO=0xff;// 送入位选信号前关闭所有显示,防止打开位选锁存时wela=1;P0=0xef;wela=0;delayms(10);dula=1;P0=table[m]; //秒第2位dula=0;P0=0xff;wela=1;P0=0xdf;wela=0;delayms(100)dula=1;P0=table[f1]; //分第1位dula=0;P0=0xff;wela=1;P0=0xfb;wela=0;delayms(100)dula=1;P0=table[f]; //分第2位dula=0;P0=0xff;wela=1;P0=0xf7;wela=0;delayms(10)dula=1;P0=table[s1]; //时第1位dula=0;P0=0xff;wela=1;P0=0xfe;wela=0;delayms(100)dula=1;P0=table[s]; //时第2位dula=0;P0=0xff;wela=1;P0=0xfd;wela=0;delayms(10)}/********************************************************** ***调时闹钟显示函数display1()*********************************************************** **/void display1(uchar nf,uchar nf1,uchar ns,uchar ns1){nf1=numnf/10;nf=numnf%10;ns1=nums/10;ns=nums%10;dula=1;P0=table[nf1];//分第1位dula=0;P0=0xff;wela=1;P0=0xfb;//待改参数wela=0;delayms(10);dula=1;P0=table[nf];//分第2位dula=0;P0=0xff;wela=1;P0=0xf7;//待改参数wela=0;delayms(10);P0=table[ns1];//时第1位dula=0;P0=0xff;wela=1;P0=0xfe;//待改参数wela=0;delayms(10);dula=1;P0=table[ns];//时第2位dula=0;P0=0xfd;wela=1;P0=0xff;//待改参数wela=0;delayms(10);}/********************************************************** ***秒表显示函数displaym()*********************************************************** **/void displaym(uchar m,uchar m1){dula=1;P0=table[m1];//秒位第一位P0=0xff;wela=1;P0=0Xbf;wela=0;delayms(10);dula=1;P0=table[m];dula=0;P0=0xff;wela=1;P0=0X7f;wela=0;delayms(10);}/**************************************************** 中断服务函数void T0_time() interrupt 1****************************************************/ void T0_time() interrupt 1{TH0=(65536-45872)/256; //46080TL0=(65536-45872)%256;num2++;if(num2==20){num++;num2=0;m=num%10;m1=num/10;f=numf%10;f1=numf/10;s=nums%10;s1=nums/10;if(num==59){num=0;numf++;if(numf==59){numf=0;nums++;}if(nums==24)nums=0;}}}/*************************************************** 延时函数delayms()***************************************************/ void delayms(xms){uint i,j;for(i=xms;i>0;i--)for(j=110;j>0;j--); }。
电子跑表电路元件说明
一、显示部分
显示部分采用两片四位一体和两位一体的共阴数码管作为电路的显示时间信息和跑表的计时信息,显示部分驱动采用一片74HC04作为数码管的驱动芯片,如下图:
74HC04为六组反相器我们用来驱动六位数码管的共阴端,1A-6A为输入端,1Y-6Y为输出端。
二、复位电路
此复位电路为单片机上电的瞬间提供复位信号供单片机复位,在上电的瞬间
电容C1相当于同路,电压信号通过电容给单片机复位引脚提供一个高电平的复位信号,在电容充满电之后复位结束单片机进入正常工作状态,电阻R1为电容的放电电阻,用于在单片机掉电后快速将电容C1中的电量消耗掉方便下次单片机上电复位。
按键直接接在单片机VCC和单片机复位引脚端,当按下按键后单片机复位引脚通过按键短接到VCC实现复位,松开按键复位结束。
三、晶振电路
如中X1为单片机晶振,为单片机提供时钟信号,晶振值在仿真时设定为12MHZ,C2和C3为晶振起振电容。
四、时钟电路部分
单片机走时时钟信号使用一片DS1302作为计时基准,从1302中读取时分秒信息并实时显示在数码管,设定的时间信息可在按下确认键后保存到DS1302。
电池BT1为DS1302的掉电走时电池,方便单片机系统掉电后能继续走时。
五、按键部分
一共使用9个按键来作为电路的设定和切换键,按键功能及分布如下图
六、 单片机
单片机使用STC89系列51单片机作为主控芯片。
1 绪论电子表是20世纪50年代才开始出现的新型计时器。
最早的一款电子表被称做“摆轮游丝电子表”,它诞生于1955年。
这种手表用电磁摆轮代替发条驱动,以摆轮游丝作为振荡器,微型电池为能源,通过电子线路驱动摆轮工作。
它的走时部分与机械手表完全相同,被称为第一代电子手表。
1960年,美国布洛瓦公司最早开始出售“音叉电子手表”。
这种手表以金属音叉作为振荡器,用电子线路输出脉冲电流,使机械音叉振动。
它比摆轮式电子手表结构简单,走时更精确,被称为第二代电子手表。
1969年,日本精工舍公司推出了世界上最早的石英电子表。
石英电子表的出现,立刻成为了钟表界主流产品,它走时精确,结构简单,轻松地将一、二代电子表,甚至机械表淘汰出局。
石英表又称“水晶振动式电子表”,因为它是利用水晶片的“发振现象”来计时的。
当水晶受到外部的加力电压,就会产生变形和伸缩反应;如果压缩水晶,便会使水晶两端产生电力。
这样的性质在很多结晶体上也可见到,称为“压电效果”。
石英表就是利用周期性持续“发振”的水晶,为我们带来准确的时间。
单片机是一种集成电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计时器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到一块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域的广泛应用。
从上世纪80年代,由当时的4位、8为单片机,发展到现在的32位300M的高速单片机。
1.1 单片机的介绍单片微型计算机简称单片机,是典型的嵌入式微控制器(Microcontroller Unit),常用英文字母的缩写MCU表示单片机,单片机又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。
相当于一个微型的计算机,和计算机相比,单片机只缺少了I/O设备。
概括的讲:一块芯片就成了一台计算机。
51单片机c语言电子钟(已加入调时、闹铃、整点报时功能)效果图:程序如下://51单片机c语言电子钟(已加入调时、闹铃、整点报时功能)#include<reg51.h>#include<absacc.h>#define uchar unsigned char#define uint unsigned int/*七段共阴管显示定义*///此表为LED 的字模,共阴数码管0-9 -uchar code dispcode[] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //段码控制/*定义并初始化变量*/uchar seconde=0;//秒uchar minite=0;//分uchar hour=12; //时uchar shi=0;//闹铃功能uchar fen=0;uchar bjcs;//报警次数sbit P1_0=P1^0; //second 调整定义sbit P1_1=P1^1; //minite调整定义sbit P1_2=P1^2; //hour调整定义sbit P1_5=P1^5; //整点报时sbit P1_3=P1^3; //闹铃功能,调整时间sbit P1_6=P1^6; //调整时sbit P1_7=P1^7; //调整分sbit P1_4=P1^4; //关闭闹铃/*函数声明*/void delay(uint k ); //延时子程序void time_pro( ); //时间处理子程序void display( ); //显示子程序void keyscan( ); //键盘扫描子程序/*xx子程序*/void delay (uint k){uchar j;while((k--)!=0){for(j=0;j<125;j++){;}}}/*时间处理子程序*/void time_pro(void){if(seconde==60){seconde=0;minite++;if(minite==60){minite=0;hour++;if(hour==24){hour=0;}}}}/*显示子程序*/void display(void){if(P1_3==1){P2=0XFE; P0=dispcode[seconde%10];//秒个位delay(1);P2=0XFD;P0=dispcode[seconde/10];//秒十位delay(1);P2=0XFB;P0=dispcode[10];//间隔符-delay(1);P2=0XF7;P0=dispcode[minite%10];//分个位delay(1);P2=0XEF;P0=dispcode[minite/10];//分十位delay(1);P2=0XDF;P0=dispcode[10];//间隔符-delay(1);P2=0XBF;P0=dispcode[hour%10];//时个位delay(1);P2=0X7F;P0=dispcode[hour/10];//时十位delay(1);}}/*键盘扫描子程序*/void keyscan(void){if(P1_0==0)//秒位的调整{delay (30);if(P1_0==0){seconde++;if(seconde==60){seconde=0;}}delay(250);}if(P1_1==0)//分位的调整{delay(30);if(P1_1==0){minite++;if(minite==60){minite=0;}}delay(250);}if(P1_2==0)//时位的调整{delay(30);if(P1_2==0){hour++;if(hour==24){hour=0;}}delay(250);}}/*整点报警*/void zhengdian (void){if((seconde==0)&(minite==0))//整点报时{P1_5=0;delay(1000);P1_5=1;}}/*定时闹钟*/void dingshi(void){if(P1_3==0)//按住P1_3BU不松,显示闹铃设置界面,分别按P1_6、P1_7设置闹铃时间。
功能最全的电子钟【单片机】c51数字时钟(带年月日显示)摘要:本设计以单片机为核心,lcd1602显示。
采用独立键盘输入能任意修改当前时间日期和设定闹钟时间。
具有显示年月日(区分闰年和二月),闹钟报警和整点报时功能主程序:/********************************************************************************************************************************************************************************* ****************************************** lcd1602电子钟********************************************************************************************************************************** *************************************************************************************************** ********************/# include <reg52.h># include "lcd16024.h"sbit key1 = P2^0; //调整sbit key2 = P2^1; //加1sbit key3 = P2^2; //减1sbit speaker = P2^3; //蜂鸣器sbit key4 = P2^4; //闹钟设计bit cal_year = 1; //进入判断闰年标志位bit leap_year; //闰年标志位bit calculate = 0; //日加一标记bit run = 0; //闹钟标志bit beep = 0; //整点报时标志//uint8 num = 0; //调整是给的脉冲uint8 code str1[] = "D: ";uint8 code str2[] = "T: ";uint8 code str3[] = "Wek";uint8 daystr[]="2013-07-29 "; //年月日格式uint8 timestr[]="21:30:59 N"; //时分秒格式uint8 daystr1[]="2013-07-29 "; //闹钟年月日格式uint8 timestr1[]="21:30:59 N"; //闹钟时分秒格式uint8 numweek = 0; //星期加1标记char week = 1; //星期char sec = 53; //秒char min = 50; //分char hour = 23; //时uint8 day = 30; // 日uint8 month = 9; //月uint16 year = 2013; //年char week1 = 1; //闹钟星期char sec1 = 58; //闹钟秒char min1 = 50; //闹钟分char hour1 = 23; //闹钟时uint8 day1 = 30; //闹钟日uint8 month1 = 9; //闹钟月uint16 year1 = 2013; //闹钟年uint8 WeekData1; //闹钟星期标记uint8 number = 0; //定时uint8 WeekData; //星期标记uint8 speaker_num; //整点报时次数uint8 scan_key(void); //函数声名/****************************************************************************** ***************************** 更新LCD时间分离读取******************************************************************************************************************* *******/void TimeChange(){//时分秒timestr[7] = sec%10+'0';timestr[6] = sec/10+'0';timestr[4] = min%10+'0';timestr[3] = min/10+'0';timestr[1] = hour%10+'0';timestr[0] = hour/10+'0';//年月日daystr[9] = day%10+'0';daystr[8] = day/10+'0';daystr[6] = month%10+'0';daystr[5] = month/10+'0';daystr[3] = year%10+'0';daystr[2] = year/10%10+'0';daystr[1] = year/100%10+'0';daystr[0] = year/1000+'0';//星期WeekData = week+'0';}/****************************************************************************** ***************************** 闹钟更新LCD时间分离读取******************************************************************************************************************* *******/void TimeChange1(){//时分秒timestr1[7] = sec1%10+'0';timestr1[6] = sec1/10+'0';timestr1[4] = min1%10+'0';timestr1[3] = min1/10+'0';timestr1[1] = hour1%10+'0';timestr1[0] = hour1/10+'0';//年月日daystr1[9] = day1%10+'0';daystr1[8] = day1/10+'0';daystr1[6] = month1%10+'0';daystr1[5] = month1/10+'0';daystr1[3] = year1%10+'0';daystr1[2] = year1/10%10+'0';daystr1[1] = year1/100%10+'0';daystr1[0] = year1/1000+'0';//星期WeekData1 = week1+'0';}/****************************************************************************** ***************************** 初始化系统定时器0 ******************************************************************************************************************* *******/void systimer0_init(void){TMOD |=0x01;//设置为1时用或(|)TMOD &=0xfd;//设置为0时用与(&)TH0 = 0xDC; // 定时10msTL0 = 0x00;EA = 1;ET0=1;TR0=1;EX0 = 1;}/****************************************************************************** ***************************** 闹钟时间设置*************************************************************************************************************** *******/void naozhong(){uint8 number = 1;uint8 a = 0;uint8 b = 0;if(0 == key4){Delay1Ms(5);if(0 == key4){a = 1;LCD_write_command(0xc0+9);LCD_write_command(0x0f);}while(!key4);}while(a){if(0 == key4){Delay1Ms(5);if(0 == key4){a = 0;run = ~run;while(!key4);}}if(run){timestr[9] = 'Y';}else{timestr[9] = 'N';}if(0 == key1){Delay1Ms(5);if(0 == key1){b = 1;}while(!key1);}while(b){if(0 == key1){Delay1Ms(5);if(0 == key1){number++;if(4 == number)b = 0;}while(!key1);if(number == 1){LCD_write_command(0xc0+9);LCD_write_command(0x0f);}if(number == 2){LCD_write_command(0xc0+6);LCD_write_command(0x0f);}if(number == 3){LCD_write_command(0xc0+3);LCD_write_command(0x0f);}}}switch(number){case 1:if(0 == key2) //闹钟秒加1的设置{Delay1Ms(5);if(0 == key2){sec1++;if(60 == sec1){sec1 = 0;}while(!key2);timestr1[7] = sec1%10+'0';timestr1[6] = sec1/10+'0';LCD_write_char(8,1,timestr1[6]);LCD_write_char(9,1,timestr1[7]);LCD_write_command(0xc0+9);}}if(0 == key3) //闹钟秒减1的设置Delay1Ms(5);if(0 == key3){sec1--;if(sec1 < 0){sec1 = 59;}while(!key3);timestr1[7] = sec1%10+'0';timestr1[6] = sec1/10+'0';LCD_write_char(8,1,timestr1[6]);LCD_write_char(9,1,timestr1[7]);LCD_write_command(0xc0+9);}}break;case 2:if(0 == key2) //闹钟分加1的设置{Delay1Ms(5);if(0 == key2){min1++;if(60 == min1){min1 = 0;}while(!key2);timestr1[4] = min1%10+'0';timestr1[3] = min1/10+'0';;LCD_write_char(5,1,timestr1[3]);LCD_write_char(6,1,timestr1[4]);LCD_write_command(0xc0+6);}}if(0 == key3) //闹钟分减1的设置{Delay1Ms(5);if(0 == key3){min1--;if(min1 < 0){min1 = 59;}while(!key3);timestr1[4] = min1%10+'0';timestr1[3] = min1/10+'0';;LCD_write_char(5,1,timestr1[3]);LCD_write_char(6,1,timestr1[4]);LCD_write_command(0xc0+6);}}break;case 3:if(0 == key2) //闹钟时加1的设置{Delay1Ms(5);if(0 == key2){hour1++;if(24 == hour1){hour1 = 0;}while(!key2);timestr1[1] = hour1%10+'0';timestr1[0] = hour1/10+'0';LCD_write_char(2,1,timestr1[0]);LCD_write_char(3,1,timestr1[1]);LCD_write_command(0xc0+3);}}if(0 == key3) //闹钟时减1的设置{Delay1Ms(5);if(0 == key3){hour1--;if(hour1 < 0){hour1 = 23;}while(!key3);timestr1[1] = hour1%10+'0';timestr1[0] = hour1/10+'0';LCD_write_char(2,1,timestr1[0]);LCD_write_char(3,1,timestr1[1]);LCD_write_command(0xc0+3);}}break;case 4:b = 0;LCD_write_command(0x0c);break;}}}LCD_write_command(0x0c);while(!key4);}/****************************************************************************** ***************************** 判断按键进入时间调整*************************************************************************************************************** *******/uint8 scan_key(void){uint8 number = 1;uint8 a = 0;if(0 == key1){Delay1Ms(5);if(0 == key1){while(!key1);a = 1;LCD_write_command(0xc0+9);LCD_write_command(0x0f);}}while(a){if(0 == key1){Delay1Ms(5);if(0 == key1){number++;while(!key1);TR0 = 0;if(number == 2){LCD_write_command(0xc0+6);LCD_write_command(0x0f);}if(number == 3){LCD_write_command(0xc0+3);LCD_write_command(0x0f);}if(number == 4){LCD_write_command(0x80+11);LCD_write_command(0x0f);}if(number == 5){LCD_write_command(0x80+8);LCD_write_command(0x0f);}if(number == 6){LCD_write_command(0x80+5);LCD_write_command(0x0f);}if(number == 7){LCD_write_command(0xc0+14);LCD_write_command(0x0f);}if(8 == number){LCD_write_command(0x0c);a = 0;number = 0;}}}switch(number){case 1:if(0 == key2) //秒加1的设置{Delay1Ms(5);if(0 == key2){sec++;if(60 == sec){sec = 0;}timestr[7] = sec%10+'0';timestr[6] = sec/10+'0';LCD_write_char(8,1,timestr[6]);LCD_write_char(9,1,timestr[7]);LCD_write_command(0xc0+9);while(!key2);}}if(0 == key3) //秒减1的设置{Delay1Ms(5);if(0 == key3){sec--;if(sec < 0){sec = 59;}timestr[7] = sec%10+'0';timestr[6] = sec/10+'0';LCD_write_char(8,1,timestr[6]);LCD_write_char(9,1,timestr[7]);LCD_write_command(0xc0+9);while(!key3);}}break;case 2:if(0 == key2) //分加1的设置{Delay1Ms(5);if(0 == key2){min++;if(60 == min){min = 0;}timestr[4] = min%10+'0';timestr[3] = min/10+'0';;LCD_write_char(5,1,timestr[3]);LCD_write_char(6,1,timestr[4]);LCD_write_command(0xc0+6);while(!key2);}}if(0 == key3) //分减1的设置{Delay1Ms(5);if(0 == key3){min--;if(min < 0){min = 59;}timestr[4] = min%10+'0';timestr[3] = min/10+'0';LCD_write_char(5,1,timestr[3]);LCD_write_char(6,1,timestr[4]);LCD_write_command(0xc0+6);while(!key3);}}break;case 3:if(0 == key2) //时加1的设置{Delay1Ms(5);if(0 == key2){hour++;while(!key2);if(24 == hour){hour = 0;}timestr[1] = hour%10+'0';timestr[0] = hour/10+'0';LCD_write_char(2,1,timestr[0]);LCD_write_char(3,1,timestr[1]);LCD_write_command(0xc0+3);}}if(0 == key3) //时减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);hour--;if(hour < 0){hour = 23;}timestr[1] = hour%10+'0';timestr[0] = hour/10+'0';LCD_write_char(2,1,timestr[0]);LCD_write_char(3,1,timestr[1]);LCD_write_command(0xc0+3);}}break;case 4:if(0 == key2) //日加1的设置{Delay1Ms(5);if(0 == key2){while(!key2);calculate = 1;if(calculate == 1){if(month==1|month==3|month==5|month==7|month==8|month==10|month==12){day++;if(day > 31){day=1;}}if(month==4|month==6|month==9|month==11){day++;if(day > 30){day=1;}}if(month == 2){cal_year = 1;while(cal_year == 1){leap_year = ((year % 4 == 0 && year % 100 != 0)||(year % 400 == 0));cal_year = 0;}if(leap_year==1){day++;if(day > 30){day=1;}}else{day++;if(day > 29){day=1;}}}calculate = 0;}daystr[9] = day%10+'0';daystr[8] = day/10+'0';LCD_write_char(10,0,daystr[8]);LCD_write_char(11,0,daystr[9]);LCD_write_command(0x80+11);}}if(0 == key3) //日减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);calculate = 1;if(calculate == 1){if(month==1|month==3|month==5|month==7|month==8|month==10|month==12){day--;if(day == 0){day=31;}}if(month==4|month==6|month==9|month==11){day--;if(day == 0){day=30;}}if(month == 2){cal_year = 1;while(cal_year == 1){leap_year = ((year % 4 == 0 && year % 100 != 0)||(year % 400 == 0));cal_year = 0;}if(leap_year==1){day--;if(day == 0){day=30;}}else{day--;if(day == 0){day=29;}}}calculate = 0;}daystr[9] = day%10+'0';daystr[8] = day/10+'0';LCD_write_char(10,0,daystr[8]);LCD_write_char(11,0,daystr[9]);LCD_write_command(0x80+11);}}break;case 5:if(0 == key2) //月加1的设置{Delay1Ms(5);if(0 == key2){while(!key2);month++;if(13 == month){month = 1;}daystr[6] = month%10+'0';daystr[5] = month/10+'0';LCD_write_char(7,0,daystr[5]);LCD_write_char(8,0,daystr[6]);LCD_write_command(0x80+8);}}if(0 == key3) //月减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);month--;if(month == 0){month = 12;}daystr[6] = month%10+'0';daystr[5] = month/10+'0';LCD_write_char(7,0,daystr[5]);LCD_write_char(8,0,daystr[6]);LCD_write_command(0x80+8);}}break;case 6:if(0 == key2) //年加1的设置{Delay1Ms(5);if(0 == key2){while(!key2);year++;}daystr[3] = year%10+'0';daystr[2] = year/10%10+'0';daystr[1] = year/100%10+'0';daystr[0] = year/1000+'0';LCD_write_char(2,0,daystr[0]);LCD_write_char(3,0,daystr[1]);LCD_write_char(4,0,daystr[2]);LCD_write_char(5,0,daystr[3]);LCD_write_command(0x80+5);}if (0 == key3) //年减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);year--;if(year == 0){year = 2020;}daystr[3] = year%10+'0';daystr[2] = year/10%10+'0';daystr[1] = year/100%10+'0';daystr[0] = year/1000+'0';LCD_write_char(2,0,daystr[0]);LCD_write_char(3,0,daystr[1]);LCD_write_char(4,0,daystr[2]);LCD_write_char(5,0,daystr[3]);LCD_write_command(0x80+5);}}break;case 7:if(0 == key2) //星期加1的设置{Delay1Ms(5);if(0 == key2){while(!key2);week++;if(7 == week){week = 0;}LCD_write_char(14,1,week+'0');LCD_write_command(0xc0+14);}}if (0 == key3) //星期减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);week--;if(week < 0){week = 6;}LCD_write_char(14,1,week+'0');LCD_write_command(0xc0+14);}}break;case 8:TR0 = 1;break;}}}/****************************************************************************** ***************************** 主函数******************************************************************************************************************* *******/void main(void){systimer0_init();LCD_init();LCD_write_str(0,0,str1);LCD_write_str(0,1,str2);LCD_write_str(13,0,str3);speaker = 0;while (1){TimeChange();scan_key();naozhong();LCD_write_str(2,0,daystr);LCD_write_str(2,1,timestr);LCD_write_char(14,1,WeekData);if(1 == run){if(sec==sec1 & month==month1 & hour==hour){speaker_num =30;beep = 1;}}else{speaker_num =0;beep = 0;}}}/****************************************************************************** ***************************** 定时中断0 ******************************************************************************************************************* *******/void time_0() interrupt 1{TH0 = 0xDC; // 定时10msTL0 = 0x00;number++;if(number ==100){sec++;if(beep){speaker=!speaker;speaker_num--;if(speaker_num == 0){beep=0;speaker = 0;}}if(sec == 60){sec = 0;min++;if(min == 60){min = 0;hour++; //小时加1speaker_num = hour%12; //蜂鸣器响的次数beep = 1;if(hour == 24){hour = 0;calculate = 1;if(calculate == 1) //判断这个月有多少天{if(month==1|month==3|month==5|month==7|month==8|month==10|month==12){day++;if(month==7|month==12){week++;if(7 == week){week = 0;}}else{if(day <= 31){week++;if(7 == week){week = 0;}}}if(day > 31){if(month==7|month==12){day = 1;}else{day=0;}month++;if(month > 12){month=1;year++;cal_year=1;}}}if(month==4|month==6|month==9|month==11) {day++;week++;if(7 == week){week = 0;}if(day > 30){day=1;month++;if(month > 12){month=1;year++;cal_year=1;}}}if(month == 2){while(cal_year == 1){leap_year = ((year % 4 == 0 && year % 100 != 0)||(year % 400 == 0));cal_year = 0;}if(leap_year==1){day++;if(day <= 30){week++;if(7 == week){week = 0;}}if(day > 30){day=1;month++;if(month > 12){month=1;year++;cal_year=1;}}}else{day++;week++;if(7 == week){week = 0;}if(day > 29){day=1;month++;if(month > 12){month=1;year++;cal_year=1;}}}}}calculate=0;}}}}}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Lcd1602.c子程序:////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /****************************************************************************** ***************************** lcd1602低层函数********************************************************************************************************************* *******/# include <reg52.h># include <intrins.h># include "lcd16024.h"# define LCD_DATA P0 //LCD1602的数据口定义sbit LCD_RS = P0^0; //LCD1602控制线的定义,4位控制方式sbit LCD_RW = P0^1;sbit LCD_EN = P0^2;/****************************************************************************** ***************************** 延时1MS********************************************************************************************************************* *******/void Delay1Us(uint16 n){for(;n>0;n--){_nop_();}}/****************************************************************************** ***************************** 延时1MS********************************************************************************************************************* *******/void Delay1Ms(uint16 n){while(n--){Delay1Us(1000);}}/****************************************************************************** ***************************** 延时1MS********************************************************************************************************************* *******/void LCD_en_write(void){LCD_EN=0;LCD_EN=1;Delay1Us(1);LCD_EN=0;}/****************************************************************************** ************************ LCD写一个字节命令函数************************************************************************************************************ *******/void LCD_write_command(uint8 command){Delay1Us(16);LCD_RS=0;LCD_RW=0;LCD_DATA&=0x0f;LCD_DATA|=command&0xf0;LCD_en_write();command=command<<4;LCD_DATA&=0x0f;LCD_DATA|=command&0xf0;LCD_en_write();}/****************************************************************************** ********************** LCD写一个字节数据函数*************************************************************************************************************** *******/void LCD_write_data(uint8 Data){Delay1Us(16);LCD_RS=1;LCD_RW=0;LCD_DATA&=0x0f;LCD_DATA|=Data&0xf0;LCD_en_write();Data=Data<<4;LCD_DATA&=0x0f;LCD_DATA|=Data&0xf0;LCD_en_write();}/****************************************************************************** ***************************** LCD1602光标定位函数************************************************ x--列0~15;y--行0~1********************************************************************************************************* *******/void LCD_set_xy(uint8 x,uint8 y){uint8 address;if(y==0)address=0x80+x;else address=0xc0+x;LCD_write_command(address);}/***************************************************************************************************** LCD1602 初始化函数,四位显示方式******************************************************************************************************* *******/void LCD_init(){LCD_write_command(0x28);// Delay1Us(40);LCD_write_command(0x28);LCD_write_command(0x0c);LCD_write_command(0x01);LCD_write_command(0x06);Delay1Ms(2);}/****************************************************************************** ***************************** LCD写字符串函数******************************************************* x--列0~15;y--行0~1******************************************************* s指向字符串数组**************************************************************************************************************** *******/void LCD_write_str(uint8 x,uint8 y,uint8 *s){LCD_set_xy(x,y);while(*s){LCD_write_data(*s);s++;}}/****************************************************************************** ***************************** LCD写一个字符函数******************************************************* x--列0~15;y--行0~1******************************************************* d--字符的ASCII码**************************************************************************************************************** *******/void LCD_write_char(uint8 x,uint8 y,uint8 d){LCD_set_xy(x,y);LCD_write_data(d);}/*////////////////////////////////////////////////////////////////// 等待繁忙标志/////////////////////////////////////////////////////////////////void LCD_wait(void){P0 = 0xFF;do{LCD_RS = 0;LCD_RW = 1;LCD_EN = 0;LCD_EN = 1;}while (BUSY == 1);LCD_EN = 0;}*//****************************************************************************** ***************************** LCD1602左移********************************************************************************************************************* *******void LCD_youyi(uint8 y,uint8 *s){LCD_write_str(17,y,s);for(a=0;a<16;a++){LCD_write_command(0x1c); //左移LCD_write_command(0x1c); 为右移Delay1Ms(6);}}*///LCD_write_command(0x0d);//光标闪烁//LCD_write_command(0x0e);//光标显示不闪烁//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Lcd1602.h头文件////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef _LCD16024_H_#define _LCD16024_H_typedef unsigned char uint8;typedef unsigned int uint16;typedef unsigned long uint32;void Delay1Us(uint16 n);void Delay1Ms(uint16 n);void LCD_write_data(uint8 dat);void LCD_write_command(uint8 com); //BuysC为0时忽略忙检测void LCD_set_xy(uint8 x,uint8 y);void LCD_en_write(void);void LCD_write_char(uint8 x, uint8 y, uint8 Data1);void LCD_write_str(uint8 x, uint8 y,uint8 *s);void LCD_init();//void LCD_wait(void);//void LCD_youyi(uint8 y,uint8 *s);#endif。
8位数码管显示电子时钟c51单片机程序 /*8位数码管显示时间格式 055000 标示05点50分00秒S1 用于小时加1操作S2 用于小时减1操作S3 用于分钟加1操作S4 用于分钟减1操作*/#includereg52.hsbit KEY1=P3^0; //定义端口参数sbit KEY2=P3^1;sbit KEY3=P3^2;sbit KEY4=P3^3;sbit LED=P1^2; //定义指示灯参数code unsigned chartab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共阴极数码管09unsigned char StrTab[8]; //定义缓冲区unsigned char minute=19,hour=23,second; //定义并初始化为12:30:00void delay(unsigned int cnt){while(cnt);}/********************************************************** ********//* 显示处理函数 *//********************************************************** ********/void Displaypro(void){StrTab[0]=tab[hour/10]; //显示小时StrTab[1]=tab[hour%10];StrTab[2]=0x40; //显示StrTab[3]=tab[minute/10]; //显示分钟StrTab[4]=tab[minute%10];StrTab[5]=0x40; //显示StrTab[6]=tab[second/10]; //显示秒StrTab[7]=tab[second%10];}main(){TMOD |=0x01; //定时器0 10ms inM crystal 用于计时TH0=0xd8; //初值TL0=0xf0;ET0=1;TR0=1;TMOD |=0x10; //定时器1用于动态扫描 TH1=0xF8; //初值TL1=0xf0;ET1=1;TR1=1;EA =1;Displaypro(); //调用显示处理函数while(1){if(!KEY1) //按键1去抖以及动作{delay(10000);if(!KEY1){hour++;if(hour==24)hour=0; //正常时间小时加1Displaypro();}if(!KEY2) //按键2去抖以及动作 {delay(10000);if(!KEY2){hour;if(hour==255)hour=23; //正常时间小时减1 Displaypro();}}if(!KEY3) //按键去抖以及动作{delay(10000);if(!KEY3){minute++;if(minute==60)minute=0; //分加1Displaypro();}if(!KEY4) //按键去抖以及动作{delay(10000);if(!KEY4){minute;if(minute==255)minute=59; //分减1Displaypro();}}}}/********************************************************** ********//* 定时器1中断 *//********************************************************** ********/void time1_isr(void) interrupt 3 using 0 //定时器1用来动态扫描static unsigned char num;TH1=0xF8; //重入初值TL1=0xf0;switch (num){case 0:P2=0;P0=StrTab[num];break; //分别调用缓冲区的值进行扫描case 1:P2=1;P0=StrTab[num];break;case 2:P2=2;P0=StrTab[num];break;case 3:P2=3;P0=StrTab[num];break;case 4:P2=4;P0=StrTab[num];break;case 5:P2=5;P0=StrTab[num];break;case 6:P2=6;P0=StrTab[num];break;case 7:P2=7;P0=StrTab[num];break;default:break;}num++; //扫描8次,使用8个数码管if(num==8)num=0;}/******************************************************************//* 定时器0中断 *//********************************************************** ********/void tim(void) interrupt 1 using 1{static unsigned char count; //定义内部局部变量TH0=0xd8; //重新赋值TL0=0xf0;count++;switch (count){case 0:case 20:case 40:case 60:case 80:Displaypro();break; //隔一定时间调用显示处理case 50:P1=~P1;break; //半秒 LED 闪烁default:break;}if (count==100){count=0;second++; //秒加1 if(second==60){second=0;minute++; //分加1 if(minute==60){minute=0;hour++; //时加1 if(hour==24)hour=0;}}}}。
用51单片机做的电子时钟程序如下:#includeunsigned char codetable1[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f ,0x40,0x76};//字码表0-9,最后一个是一横"-"unsigned int i,a,b,c,d,flag,flag1;unsigned int sec,min,h,nm,nh,nz;unsigned int w,day,mon,year;int miao1,miao2,miao3;sbit keyled=P1^0;sbit key2=P1^1;sbit keyinc=P1^2; sbit keymood=P1^3; sbit BEEP=P1^4; void second();void minute();void hour();void time();void riqi();void xianshi();void delay10ms(); void delay20ms();void tiaoshi();void miaobiao();void miaotime();void week();void naozhong();void shengyin();//前几天刚用了下定时器,想起来之前用汇编写的时钟程序基本没有什么功能,所以这几天就用C再写了下//这个时钟的功能是模仿我自己的手表写的,功能完全一样,有秒表,闹钟,可以显示年月日及星期/{if(min==nm&&h==nh)//时间到了,闹钟响{shengyin(); //闹钟的声音程序}}if(c==0||c==2){if(keymood==0){miao1=0;miao2=0;miao3=0;}}while(b==1)//保证按键只按一次,没有重复按键{tiaoshi();goto B1; //如果b还等于1,刚重复扫描秒表界面}}/{ i=0; //将i清零,保证每次进入都是一样的B2:if(nz==0){ if(min==nm&&h==nh) {shengyin();}}naozhong();while(b==2){ tiaoshi();goto B2;}}{ i=1;B3:if(nz==0){ if(min==nm&&h==nh){shengyin();}}xianshi(); //显示程序,用i的大小来分配,相当于调时、分、秒就显示时间,调年月日就显示日期while(b==3){tiaoshi();goto B3;}}/{ i=0;if(nz==0){ if(min==nm&&h==nh) {shengyin();}}second();minute();hour();}if(keyinc==0){ delay10ms();if(keyinc==0){B: riqi();while(keyinc==0) {goto B;}}}if(keymood==0) {delay10ms();if(keymood==0) {N: naozhong(); }while(keymood==0){goto N;}}tiaoshi();/{if(flag>10) //在flag>10的时候关闭所有的数码管,其他时间开启相应位,这样就可以达到闪烁的目的了{P3=0xff;}else{P3=0x7f;}}else //如果i不等于1,刚正常显示,不会闪烁{P3=0x7f;}P2=table1[secge];for(a=0;a<100;a++); if(i==1){if(flag>10){P3=0xff;}else{P3=0xbf;}}else //如果i不等于1,刚正常显示,不会闪烁{P3=0xbf;}P2=table1[secshi];for(a=0;a<100;a++);P3=0xdf;P2=table1[10];for(a=0;a<100;a++);//*******************************分显示程序***************************void minute(){int minge,minshi;minge=min%10;minshi=min/10;if(i==2){if(flag>10) {P3=0xff;}else{P3=0xef;}}else{P3=0xef;}P2=table1[minge];for(a=0;a<100;a++);if(i==2){if(flag>10){P3=0xff;}else{P3=0xf7;}}else{P3=0xf7;}P2=table1[minshi];for(a=0;a<100;a++);P3=0xfb;P2=table1[10];for(a=0;a<100;a++);}//*********************************时显示程序*************************void hour(){int hourge,hourshi;hourge=h%10;hourshi=h/10;if(i==3) {if(flag>10) {P3=0xff;}else{P3=0xfd;}}else{P3=0xfd;}P2=table1[hourge];for(a=0;a<100;a++); if(i==3){if(flag>10){P3=0xff; }else{P3=0xfe; }}else{P3=0xfe; }P2=table1[hourshi];for(a=0;a<100;a++);}//*****************************年、月、日显示程序************************void riqi(){int dayge,dayshi;int monge,monshi;int yearge,yearshi;dayge=day%10;dayshi=day/10;if(i==4) {if(flag>10) {P3=0xff;}else{P3=0x7f;}}else{P3=0x7f;}P2=table1[dayge];for(a=0;a<100;a++); if(i==4){if(flag>10){P3=0xff;}else{P3=0xbf;}}else{P3=0xbf;}P2=table1[dayshi];for(a=0;a<100;a++); P3=0xdf;P2=table1[10];for(a=0;a<100;a++); monge=mon%10; monshi=mon/10;if(i==5){if(flag>10){P3=0xff;}else{P3=0xef;}}else{P3=0xef;}P2=table1[monge];for(a=0;a<100;a++); if(i==5){if(flag>10){P3=0xff;}else{P3=0xf7;}}else{P3=0xf7;}P2=table1[monshi]; for(a=0;a<100;a++); P3=0xfb;P2=table1[10];for(a=0;a<100;a++); yearge=year%10;yearshi=year/10; if(i==6){if(flag>10) {P3=0xff;}else{P3=0xfd;}}else{P3=0xfd;}P2=table1[yearge];for(a=0;a<100;a++); if(i==6){if(flag>10){P3=0xff; }else{P3=0xfe; }}else{P3=0xfe; }P2=table1[yearshi];for(a=0;a<100;a++);}//*****************************星期显示程序****************************void week(){if(i==7){if(flag>10){P3=0xff; }else{P3=0xef; }}else{P3=0xef; }P2=table1[w];for(a=0;a<100;a++);}//*****************************秒表显示程序************************void miaobiao(){int miao1ge,miao1shi;int miao2ge,miao2shi;int miao3ge,miao3shi;miao1ge=miao1%10;miao1shi=miao1/10;P3=0x7f;P2=table1[miao1ge]; for(a=0;a<100;a++); P3=0xbf;P2=table1[miao1shi]; for(a=0;a<100;a++); P3=0xdf;P2=table1[10];for(a=0;a<100;a++); miao2ge=miao2%10; miao2shi=miao2/10;P3=0xef;P2=table1[miao2ge]; for(a=0;a<100;a++); P3=0xf7;P2=table1[miao2shi]; for(a=0;a<100;a++); P3=0xfb;P2=table1[10];for(a=0;a<100;a++); miao3ge=miao3%10; miao3shi=miao3/10;P3=0xfd;P2=table1[miao3ge];for(a=0;a<100;a++);P3=0xfe;P2=table1[miao3shi];for(a=0;a<100;a++);}//****************************闹钟显示程序************************void naozhong(){int nmge,nmshi;int nhge,nhshi;nmge=nm%10;nmshi=nm/10;if(i==1||i==3||i==5||i==7) {if(flag>10){P3=0xff;}elseP3=0xef;}}else{P3=0xef;}P2=table1[nmge];for(a=0;a<100;a++); if(i==1||i==3||i==5||i==7)if(flag>10) {P3=0xff;}else{P3=0xf7;}}elseP3=0xf7;}P2=table1[nmshi];for(a=0;a<100;a++); P3=0xfb; //显示一横P2=table1[10];for(a=0;a<100;a++); nhge=nh%10;nhshi=nh/10;if(i==2||i==4||i==6)if(flag>10) {P3=0xff;}else{P3=0xfd;}}elseP3=0xfd;}P2=table1[nhge];for(a=0;a<100;a++); if(i==2||i==4||i==6) {if(flag>10){P3=0xff;}else{P3=0xfe;}}else{P3=0xfe;}P2=table1[nhshi];for(a=0;a<100;a++);P3=0xdf; //显示HP2=table1[11];for(a=0;a<100;a++);}//*******************************调时显示***********************void xianshi(){if(i>3&&i<7){riqi();}else if(i==7) {week(); }else{second(); minute(); hour();}}//***********************************闹钟声音程序****************void shengyin(){BEEP=~BEEP;for(a=0;a<10;a++);}//***************************时钟加1程序*******************************void time(){if(flag==90){flag=0;sec++;if(sec==60){sec=0;min++;if(min==60){min=0;h++;。
主题:51单片机4位数码管秒表代码内容:1. 介绍51单片机51单片机是一种通用的单片机系列,广泛应用于各种电子设备中。
它具有稳定性好、成本低、易于编程等优点,因此备受电子爱好者和专业工程师的青睐。
2. 4位数码管秒表4位数码管秒表是一种常见的电子计时器,通过LED数码管显示出当前的时间,可以用于各种计时应用,比如比赛计时、实验计时等。
3. 代码编写以下是一段简单的51单片机4位数码管秒表代码:```c#include <reg52.h>#include <intrins.h>// 数码管位选端口sbit wei1 = P2^2;sbit wei2 = P2^3;sbit wei3 = P2^4;sbit wei4 = P2^5;// 数码管显示段选端口sbit se2 = P0^2;sbit se1 = P0^3;sbit se4 = P0^4;sbit se3 = P0^5;unsigned char code smgduan[17] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00}; // 显示0~9,A,b,C,d,E,F,无的值void delay(unsigned int i) { // 延时while(i--);}void display(unsigned char *tab) { // 数码管显示 unsigned char i;for(i=0; i<7; i++) {P0=0; // 清除段选,以选中所显示的数码管 switch(i) { //确定位选case(0):wei1=0;wei2=wei3=wei4=1;break;case(1):wei2=0;wei1=wei3=wei4=1;break;case(2):wei3=0;wei1=wei2=wei4=1;break;case(3):wei4=0;wei1=wei2=wei3=1;break;default:break;}P0=tab[i]; //段码输出delay(5); // 数码管微秒级延迟}}void m本人n() {unsigned char a=0,b=0,c=0,d=0; //时钟的4位数据 unsigned int i=0;wei1=wei2=wei3=wei4=1; //段选、位选初始化while(1) {a++; // 微秒级的计数if(a==100) { //达到100a=0; b++; //b加1if(b==60) { //当b=60时b=0; c++; //c加1if(c==60) { //当c=60时c=0; d++; //d加1if(d==24) { //当d=24时d=0; //归零}}}}display(smgduan+d10); //显示个秒wei1=1;wei2=wei3=wei4=0; //位选delay(500); //延时display(smgduan+c/10+10); //显示十秒wei2=1;wei1=wei3=wei4=0; //位选delay(500); //延时display(smgduan+b10); //显示个分wei3=1;wei1=wei2=wei4=0; //位选delay(500); //延时display(smgduan+b/10+10); //显示十分wei4=1;wei1=wei2=wei3=0; //位选delay(500); //延时if(i++==200) { //当i=200时i=0;}}}```4. 代码分析该代码通过对51单片机的引脚进行控制,实现了4位数码管秒表的计时功能。
目录目录 (1)函数的使用和熟悉********************************/ (4)实例3:用单片机控制第一个灯亮 (4)实例4:用单片机控制一个灯闪烁:认识单片机的工作频率 (4)实例5:将P1口状态分别送入P0、P2、P3口:认识I/O口的引脚功能 (5)实例6:使用P3口流水点亮8位LED (5)实例7:通过对P3口地址的操作流水点亮8位LED (6)实例8:用不同数据类型控制灯闪烁时间 (7)实例9:用P0口、P1口分别显示加法和减法运算结果 (8)实例10:用P0、P1口显示乘法运算结果 (9)实例11:用P1、P0口显示除法运算结果 (9)实例12:用自增运算控制P0口8位LED流水花样 (10)实例13:用P0口显示逻辑"与"运算结果 (10)实例14:用P0口显示条件运算结果 (11)实例15:用P0口显示按位"异或"运算结果 (11)实例16:用P0显示左移运算结果 (11)实例17:"万能逻辑电路"实验 (11)实例18:用右移运算流水点亮P1口8位LED (12)实例19:用if语句控制P0口8位LED的流水方向 (13)实例20:用swtich语句的控制P0口8位LED的点亮状态 (13)实例21:用for语句控制蜂鸣器鸣笛次数 (14)实例22:用while语句控制LED (16)实例23:用do-while语句控制P0口8位LED流水点亮 (16)实例24:用字符型数组控制P0口8位LED流水点亮 (17)实例25:用P0口显示字符串常量 (18)实例26:用P0口显示指针运算结果 (19)实例27:用指针数组控制P0口8位LED流水点亮 (19)实例28:用数组的指针控制P0口8位LED流水点亮 (20)实例29:用P0、P1口显示整型函数返回值 (21)实例30:用有参函数控制P0口8位LED流水速度 (22)实例31:用数组作函数参数控制流水花样 (23)实例32:用指针作函数参数控制P0口8位LED流水点亮 (23)实例33:用函数型指针控制P1口灯花样 (25)实例34:用指针数组作为函数的参数显示多个字符串 (26)实例35:字符函数ctype.h应用举例 (27)实例36:内部函数intrins.h应用举例 (27)实例37:标准函数stdlib.h应用举例 (28)实例38:字符串函数string.h应用举例 (29)实例39:宏定义应用举例2 (29)1/192实例40:宏定义应用举例2 (30)实例41:宏定义应用举例3 (30)中断、定时器************************************************ (31)实例42:用定时器T0查询方式P2口8位控制LED闪烁 (31)实例43:用定时器T1查询方式控制单片机发出1KHz音频 (31)实例44:将计数器T0计数的结果送P1口8位LED显示 (32)实例45:用定时器T0的中断控制1位LED闪烁 (33)实例46:用定时器T0的中断实现长时间定时 (34)实例47:用定时器T1中断控制两个LED以不同周期闪烁 (34)实例48:用计数器T1的中断控制蜂鸣器发出1KHz音频 (36)实例49:用定时器T0的中断实现"渴望"主题曲的播放 (36)实例50-1:输出50个矩形脉冲 (39)实例50-2:计数器T0统计外部脉冲数 (40)实例51-2:定时器T0的模式2测量正脉冲宽度 (40)实例52:用定时器T0控制输出高低宽度不同的矩形波 (41)实例53:用外中断0的中断方式进行数据采集 (42)实例54-1:输出负脉宽为200微秒的方波 (43)实例54-2:测量负脉冲宽度 (43)实例55:方式0控制流水灯循环点亮 (44)实例56-1:数据发送程序 (45)实例56-2:数据接收程序 (47)实例57-1:数据发送程序 (47)实例57-2:数据接收程序 (49)实例58:单片机向PC发送数据 (50)实例59:单片机接收PC发出的数据 (51)*********************************数码管显示 (52)实例60:用LED数码显示数字5 (52)实例61:用LED数码显示器循环显示数字0~9 (52)实例62:用数码管慢速动态扫描显示数字"1234" (53)实例63:用LED数码显示器伪静态显示数字1234 (54)实例64:用数码管显示动态检测结果 (54)实例65:数码秒表设计 (56)实例66:数码时钟设计 (58)实例67:用LED数码管显示计数器T0的计数值 (62)实例68:静态显示数字“59” (63)*****************************键盘控制2/192*****************************************************/ (63)实例69:无软件消抖的独立式键盘输入实验 (64)实例70:软件消抖的独立式键盘输入实验 (64)实例71:CPU控制的独立式键盘扫描实验 (65)实例72:定时器中断控制的独立式键盘扫描实验 (68)实例73:独立式键盘控制的4级变速流水灯 (71)实例74:独立式键盘的按键功能扩展:"以一当四" (73)实例75:独立式键盘调时的数码时钟实验 (75)实例76:独立式键盘控制步进电机实验 (79)实例77:矩阵式键盘按键值的数码管显示实验 (82)//实例78:矩阵式键盘按键音 (85)实例79:简易电子琴 (86)实例80:矩阵式键盘实现的电子密码锁 (92)**************************************************************************液晶显示LCD*********液晶显示LCD*****液晶显示LCD************************************************************************/ (95)实例81:用LCD显示字符'A' (96)实例82:用LCD循环右移显示"Welcome to China" (99)实例83:用LCD显示适时检测结果 (102)实例84:液晶时钟设计 (106)******************************************一些芯片的使用*****24c02........ DS18B20X5045ADC0832DAC0832DS1302红外遥控**********************************************/ (112)实例85:将数据"0x0f"写入AT24C02再读出送P1口显示 (112)实例86:将按键次数写入AT24C02,再读出并用1602LCD显示 (117)实例87:对I2C总线上挂接多个AT24C02的读写操作 (124)实例88:基于AT24C02的多机通信读取程序 (129)实例88:基于AT24C02的多机通信写入程序 (133)实例90:DS18B20温度检测及其液晶显示 (144)实例91:将数据"0xaa"写入X5045再读出送P1口显示 (153)实例92:将流水灯控制码写入X5045并读出送P1口显示 (157)实例93:对SPI总线上挂接多个X5045的读写操作 (161)实例94:基于ADC0832的数字电压表 (165)实例95:用DAC0832产生锯齿波电压 (171)实例96:用P1口显示红外遥控器的按键值 (171)实例97:用红外遥控器控制继电器 (174)实例98:基于DS1302的日历时钟 (177)实例99:单片机数据发送程序 (185)实例100:电机转速表设计 (186)模拟霍尔脉冲 (192)/********************************************************* ***函数的使用和熟悉***************************************************************///实例3:用单片机控制第一个灯亮#include<reg51.h>//包含51单片机寄存器定义的头文件void main(void){P1=0xfe;//P1=11111110B,即P1.0输出低电平}//4//实例4:用单片机控制一个灯闪烁:认识单片机的工作频率#include<reg51.h>//包含单片机寄存器的头文件/****************************************函数功能:延时一段时间*****************************************/void delay(void)//两个void意思分别为无需返回值,没有参数传递{unsigned int i;//定义无符号整数,最大取值范围65535for(i=0;i<20000;i++)//做20000次空循环;//什么也不做,等待一个机器周期}/*******************************************************函数功能:主函数(C语言规定必须有也只能有1个主函数)********************************************************/void main(void){while(1)//无限循环{P1=0xfe;//P1=11111110B,P1.0输出低电平delay();//延时一段时间P1=0xff;//P1=11111111B,P1.0输出高电平delay();//延时一段时间// 5 P1 P0 P2 P3 I/O //实例 5:将 #include<reg51.h> P1 口状态分别送入 P0、P2、P3 口:认识 I/O口 的引脚功能//包含单片机寄存器的头文件/*******************************************************函数功能:主函数 (C 语言规定必须有也只能有 1个主函数)********************************************************/ void main(void){while(1) //无限循环{P1=0xff; // P1=1111 1111B,熄灭 LEDP0=P1; // 将 P1 口状态送入 P0 口P2=P1; // 将 P1 口状态送入 P2 口P3=P1; // 将 P1 口状态送入 P3口}}//实例 6:使用 P3 口流水点亮 8 位LED #include<reg51.h> //包含单片机寄存器的头文件/****************************************函数功能:延时一段时间*****************************************/void delay(void){unsigned char i,j;for(i=0;i<250;i++)for(j=0;j<250;j++);}/*******************************************************函数功能:主函数********************************************************/ voidmain(void){while(1){P3=0xfe; delay(); P3=0xfd; delay(); P3=0xfb; delay(); P3=0xf7; delay(); P3=0xef; //第一个灯亮//调用延时函数//第二个灯亮//调用延时函数//第三个灯亮//调用延时函数//第四个灯亮//调用延时函数//第五个灯亮delay(); //调用延时函数P3=0xdf; delay(); P3=0xbf;//第六个灯亮//调用延时函数//第七个灯亮delay(); //调用延时函数P3=0x7f; //第八个灯亮} }delay(); //调用延时函数//实例7:通过对P3口地址的操作流水点亮8位LED#include<reg51.h>//包含单片机寄存器的头文件sfr x=0xb0;//P3口在存储器中的地址是b0H,通过sfr可定义8051内核单片机//的所有内部8位特殊功能寄存器,对地址x的操作也就是对P1口的操作/****************************************函数功能:延时一段时间*****************************************/void delay(void){unsigned char i,j;for(i=0;i<250;i++)for(j=0;j<250;j++);//利用循环等待若干机器周期,从而延时一段时间}/*****************************************函数功能:主函数******************************************/void main(void){while(1){x=0xfe;//第一个灯亮delay();//调用延时函数x=0xfd;//第二个灯亮delay();//调用延时函数x=0xfb;//第三个灯亮delay();//调用延时函数x=0xf7;//第四个灯亮delay();//调用延时函数x=0xef;//第五个灯亮delay();//调用延时函数x=0xdf;//第六个灯亮delay();//调用延时函数x=0xbf;//第七个灯亮delay();//调用延时函数x=0x7f;//第八个灯亮delay();//调用延时函数}}//实例8:用不同数据类型控制灯闪烁时间#include<reg51.h>//包含单片机寄存器的头文件/******************************************************函数功能:用整形数据延时一段时间******************************************************/void int_delay(void)//延时一段较长的时间{unsigned int m;//定义无符号整形变量,双字节数据,值域为0~65535 for(m=0;m<36000;m++);//空操作}/******************************************************函数功能:用字符型数据延时一段时间******************************************************/void char_delay(void)//延时一段较短的时间{unsigned char i,j;//定义无符号字符型变量,单字节数据,值域0~255 for(i=0;i<200;i++)for(j=0;j<180;j++);//空操作}/******************************************************函数功能:主函数******************************************************/void main(void){unsigned char i;while(1){for(i=0;i<3;i++){P1=0xfe;//P1.0口的灯点亮int_delay();//延时一段较长的时间P1=0xff;//熄灭int_delay();//延时一段较长的时间}for(i=0;i<3;i++){P1=0xef;//P1.4口的灯点亮char_delay();//延时一段较长的时间P1=0xff;//熄灭char_delay();//延时一段较长的时间}}}//实例9:用P0口、P1口分别显示加法和减法运算结果#include<reg51.h>void main(void){unsigned char m,n;m=43; //即十进制数2x16+11=43n=60;P1=m+n; //即十进制数3x16+12=60//P1=103=01100111B,结果P1.3、P1.4、P1.7 口的灯被点亮}P0=n-m; //P0=17=00010001B,结果P0.0、P0.4的灯被熄灭//实例10:用P0、P1口显示乘法运算结果#include<reg51.h>//包含单片机寄存器的头文件void main(void){unsigned char m,n;unsigned int s;m=64;n=71;s=m*n;//s=64*71=4544,需要16位二进制数表示,高8位送P1口,低8位送P0口//由于4544=17*256+192=H3*16*16*16+H2*16*16+H1*16+H0//两边同除以256,可得17+192/256=H3*16+H2+H1*16+H0)/256//因此,高8位16进制数H3*16+H2必然等于17,即4544除以256的商//低8位16进制数H1*16+H0必然等于192,即4544除以256的余数P1=s/256;//高8位送P1口,P1=17=11H=00010001B,P1.0和P1.4口灭,其余亮P0=s%256;//低8位送P0口,P3=192=c0H=11000000B,P3.1,P3.6,P3.7口灭,其余亮}//实例11:用P1、P0口显示除法运算结果#include<reg51.h>//包含单片机寄存器的头文件void main(void){P1=36/5;//求整数P0=((36%5)*10)/5;//求小数while(1); //无限循环防止程序“跑飞”}//实例12:用自增运算控制P0口8位LED流水花样#include<reg51.h>//包含单片机寄存器的头文件/******************************************************函数功能:延时一段时间******************************************************/void delay(void){unsigned int i;for(i=0;i<20000;i++);}/******************************************************函数功能:主函数******************************************************/void main(void){unsigned char i;for(i=0;i<255;i++)//注意i的值不能超过255{P0=i;//将i的值送P0口delay();//调用延时函数}}//实例13:用P0口显示逻辑"与"运算结果#include<reg51.h>//包含单片机寄存器的头文件void main(void){P0=(4>0)&&(9>0xab);//将逻辑运算结果送P0口while(1);//设置无限循环,防止程序“跑飞”}//14P0//实例14:用P0口显示条件运算结果#include<reg51.h>//包含单片机寄存器的头文件void main(void){P0=(8>4)?8:4;//将条件运算结果送P0口,P0=8=00001000B while(1);//设置无限循环,防止程序“跑飞”}//实例15:用P0口显示按位"异或"运算结果#include<reg51.h>//包含单片机寄存器的头文件void main(void){P0=0xa2^0x3c;//将条件运算结果送P0口,P0=8=00001000B while(1);//设置无限循环,防止程序“跑飞”}//16P0//实例16:用P0显示左移运算结果#include<reg51.h>//包含单片机寄存器的头文件void main(void){P0=0x3b<<2;//将左移运算结果送P0口,P0=11101100B=0xec while(1);//无限循环,防止程序“跑飞”}#include<reg51.h> //实例17:"万能逻辑电路"实验//包含单片机寄存器的头文件sbit X=P1^5; sbit Y=P1^6; sbit Z=P1^7; void main(void) {while(1){ //将X位定义为//将Y位定义为//将Z位定义为P1.5P1.6P1.7} }F=((~X)&Y)|Z;//将逻辑运算结果赋给F;//实例18:用右移运算流水点亮P1口8位LED#include<reg51.h>//包含单片机寄存器的头文件/*****************************函数功能:延时一段时间*****************************/void delay(void){unsigned int n;for(n=0;n<30000;n++);}/*****************************函数功能:主函数*****************************/void main(void){unsigned char i;while(1){P1=0xff;delay();for(i=0;i<8;i++)//设置循环次数为8{P1=P1>>1;//每次循环P1的各二进位右移1位,高位补0delay();//调用延时函数}}}//19iff P08LED//实例19:用iff语句控制P0口8位LED的流水方向#include<reg51.h>//包含单片机寄存器的头文件sbit S1=P1^4;//将S1位定义为P1.4sbit S2=P1^5;//将S2位定义为P1.5/*****************************函数功能:主函数*****************************/void main(void){while(1){if(S1==0)//如果按键S1按下P0=0x0f;//P0口高四位LED点亮if(S2==0)//如果按键S2按下P0=0xf0;//P0口低四位LED点亮}}//实例20:用swtich语句的控制P0口8位LED的点亮状态#include<reg51.h>//包含单片机寄存器的头文件sbit S1=P1^4;//将S1位定义为P1.4/*****************************函数功能:延时一段时间*****************************/void delay(void){unsigned int n;for(n=0;n<10000;n++);}/*****************************函数功能:主函数*****************************/void main(void){unsigned char i;i=0;while(1){//将i初始化为0if(S1==0) {delay();//如果S1键按下//延时一段时间} if(S1==0)//如果再次检测到S1键按下i++;//i自增1if(i==9)//如果i=9,重新将其置为1 i=1;} switch(i)}{}//使用多分支选择语句case1:P0=0xfe;//第一个LED亮break;case2:P0=0xfd;//第二个LED亮break;case3:P0=0xfb;//第三个LED亮break;case4:P0=0xf7;//第四个LED亮break;case5:P0=0xef;//第五个LED亮break;case6:P0=0xdf;//第六个LED亮break;case7:P0=0xbf;//第七个LED亮break;case8:P0=0x7f;//第八个LED亮break;default://缺省值,关闭所有LEDP0=0xff;//21for//实例21:用for语句控制蜂鸣器鸣笛次数#include<reg51.h>//包含单片机寄存器的头文件sbit sound=P3^7;//将sound位定义为P3.7/**************************************** 函数功能:延时形成1600Hz音频****************************************/ void delay1600(void){unsigned char n;for(n=0;n<100;n++);}/**************************************** 函数功能:延时形成800Hz音频****************************************/ void delay800(void){unsigned char n;for(n=0;n<200;n++);}/**************************************** 函数功能:主函数****************************************/ void main(void){unsigned int i;while(1){for(i=0;i<830;i++){sound=0;//P3.7输出低电平delay1600();sound=1;//P3.7输出高电平delay1600();}for(i=0;i<200;i++){sound=0;//P3.7输出低电平delay800();sound=1;//P3.7输出高电平delay800();}}}//实例22:用whille语句控制LED#include<reg51.h> //包含单片机寄存器的头文件/****************************************函数功能:延时约60ms(3*100*200=60000μs)****************************************/void delay60ms(void){unsigned char m,n;for(m=0;m<100;m++)for(n=0;n<200;n++);}/****************************************函数功能:主函数****************************************/void main(void){unsigned char i;while(1)//无限循环{i=0;//将i初始化为0while(i<0xff)//当i小于0xff(255)时执行循环体{P0=i;//将i送P0口显示delay60ms();//延时i++;//i自增1}}}//实例23:用do-whiile语句控制P0口8位LED流水点亮#include<reg51.h>//包含单片机寄存器的头文件/****************************************函数功能:延时约60ms(3*100*200=60000μs)****************************************/void delay60ms(void){unsigned char m,n;for(m=0;m<100;m++)for(n=0;n<200;n++);}/****************************************函数功能:主函数****************************************/void main(void){do{P0=0xfe;//第一个LED亮delay60ms();P0=0xfd;//第二个LED亮delay60ms();P0=0xfb;//第三个LED亮delay60ms();P0=0xf7;//第四个LED亮delay60ms();P0=0xef;//第五个LED亮delay60ms();P0=0xdf;//第六个LED亮delay60ms();delay60ms();P0=0xbf;//第七个LED亮delay60ms();P0=0x7f;//第八个LED亮delay60ms();}while(1);//无限循环,使8位LED循环流水点亮}//实例24:用字符型数组控制P0口8位LED流水点亮#include<reg51.h>//包含单片机寄存器的头文件/****************************************函数功能:延时约60ms(3*100*200=60000μs)****************************************/void delay60ms(void){unsigned char m,n;for(m=0;m<100;m++)} for(n=0;n<200;n++);/****************************************函数功能:主函数****************************************/void main(void){unsigned char i;unsigned char code Tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//定义无符号字符型数组while(1){for(i=0;i<8;i++){P0=Tab[i];//依次引用数组元素,并将其送P0口显示delay60ms();//调用延时函数}}}//25P0//实例25:用P0口显示字符串常量#include<reg51.h> //包含单片机寄存器的头文件/*************************************************函数功能:延时约150ms(3*200*250=150000μs=150ms*************************************************/void delay150ms(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char str[]={"Now,Temperature is:"};//将字符串赋给字符型全部元素赋值unsigned char i;while(1){i=0; //将i初始化为0,从第一个元素开始显示} }while(str[i]!='\0')//只要没有显示到结束标志'\0'{P0=str[i];//将第i个字符送到P0口显示delay150ms();//调用150ms延时函数i++;//指向下一个待显字符}//实例26:用P0#include<reg51.h>void main(void){口显示指针运算结果unsigned char*p1,*p2; //定义无符号字符型指针变量p1,p2 unsigned char i,j; //定义无符号字符型数据i=25; j=15;p1=&i ;p2=&j ; //给i赋初值25//使指针变量指向i//使指针变量指向j,对指针初始化,对指针初始化P0=*p1+*p2; //*p1+*p2相当于i+j,所以P0=25+15=40=0x28}//则P0=00101000B,结果P0.3、P0.5引脚LED熄灭,其余点亮while(1);//无限循环,防止程序“跑飞”//27P08LED//实例27:用指针数组控制P0口8位LED流水点亮#include<reg51.h>/************************************************* 函数功能:延时约150ms(3*200*250=150000μs=150ms *************************************************/ void delay150ms(void){} for(n=0;n<250;n++) ;/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char code Tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; unsigned char*p[]={&Tab[0],&Tab[1],&Tab[2],&Tab[3],&Tab[4],&Tab[5],&Tab[6],&Tab[7]};unsigned char i;//定义无符号字符型数据while(1){for(i=0;i<8;i++){P0=*p[i];delay150ms();}}}//28P08LED//实例28:用数组的指针控制P0#include<reg51.h>口8位LED流水点亮/*************************************************函数功能:延时约150ms(3*200*250=150000μs=150ms*************************************************/void delay150ms(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:主函数*************************************************/void main(void){} unsigned char i;unsigned char Tab[]={0xFF,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,0xFE,0xFC,0xFB,0xF0,0xE0,0xC0,0x80,0x00,0xE7,0xDB,0xBD,0x7E,0x3C,0x18,0x00,0x81,0xC3,0xE7,0x7E,0xBD,0xDB,0xE7,0xBD,0xDB};//流水灯控制码unsigned char*p;//定义无符号字符型指针p=Tab;//将数组首地址存入指针pwhile(1){for(i=0;i<32;i++)//共32个流水灯控制码{P0=*(p+i);//*(p+i)的值等于a[i]delay150ms();//调用150ms延时函数}}//29P0P1//实例29:用P0#include<reg51.h>、P1口显示整型函数返回值/*************************************************函数功能:计算两个无符号整数的和*************************************************/unsigned int sum(int a,int b){unsigned int s;s=a+b;return(s);}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned z;z=sum(2008,2009);P1=z/256;//取得z的高8位P0=z%256;//取得z的低8位while(1);}//实例30:用有参函数控制P0口8位LED流水速度#include<reg51.h>/*************************************************函数功能:延时一段时间*************************************************/void delay(unsigned char x){unsigned char m,n;for(m=0;m<x;m++)for(n=0;n<200;n++);}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char i;unsigned char code Tab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};//流水灯控制码while(1){//快速流水点亮LEDfor(i=0;i<8;i++)//共8个流水灯控制码{P0=Tab[i];delay(100);//延时约60ms,(3*100*200=60000μs)}//慢速流水点亮LEDfor(i=0;i<8;i++)//共8个流水灯控制码{P0=Tab[i];delay(250);//延时约150ms,(3*250*200=150000μs)}}}22/192//31//实例31:用数组作函数参数控制流水花样#include<reg51.h>/*************************************************函数功能:延时约150ms*************************************************/void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:流水点亮P0口8位LED*************************************************/void led_flow(unsigned char a[8]){unsigned char i;for(i=0;i<8;i++){P0=a[i];delay();}}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char code Tab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};//流水灯控制码led_flow(Tab);}//32P08LED//实例32:用指针作函数参数控制P0口8位LED流水点亮/*************************************************函数功能:延时约150ms*************************************************/void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:流水点亮P0口8位LED*************************************************/void led_flow(unsigned char*p)//形参为无符号字符型指针{unsigned char i;while(1){i=0;//将i置为0,指向数组第一个元素while(*(p+i)!='\0')//只要没有指向数组的结束标志{P0=*(p+i);//取的指针所指变量(数组元素)的值,送P0口delay();//调用延时函数i++;//指向下一个数组元素}}}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char code Tab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE, 0xFF,0xFE,0xFC,0xFB,0xF0,0xE0,0xC0,0x80,0x00,0xE7,0xDB,0xBD,0x7E,0xFF,0xFF,0x3C,0x18,0x0,0x81,0xC3,0xE7,0xFF, 0xFF,0x7E};//流水灯控制码unsigned char*pointer;224/192} pointer=Tab;led_flow(pointer);//33P1//实例33:用函数型指针控制P1口灯花样#include<reg51.h>//包含51单片机寄存器定义的头文件unsigned char code Tab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F}; //流水灯控制码,该数组被定义为全局变量/************************************************************** 函数功能:延时约150ms**************************************************************/ void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/************************************************************** 函数功能:流水灯左移**************************************************************/ void led_flow(void){unsigned char i;for(i=0;i<8;i++)//8位控制码{P0=Tab[i];delay();}}/************************************************************** 函数功能:主函数**************************************************************/ void main(void){void(*p)(void);//定义函数型指针,所指函数无参数,无返回值p=led_flow;//将函数的入口地址赋给函数型指针pwhile(1)(*p)(); //通过函数的指针p调用函数led_flow()}//34//实例34:用指针数组作为函数的参数显示多个字符串#include<reg51.h>//包含51单片机寄存器定义的头文件unsigned char code str1[]="Temperature is tested by DS18B20";//C语言中,字符串是作为字符数组来处理的unsigned char code str2[]="Now temperature is:";//所以,字符串的名字就是字符串的首地址unsigned char code str3[]="The Systerm is designed by Zhang San";unsigned char code str4[]="The date is2008-9-30";unsigned char*p[]={str1,str2,str3,str4};//定义p[4]为指向4个字符串的字符型指针数组/**************************************************************函数功能:延时约150ms**************************************************************/ void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/**************************************************************函数功能:流水点亮P0口8位LED**************************************************************/ void led_display(unsigned char*x[])//形参必须为指针数组{unsigned char i,j;for(i=0;i<4;i++)//有4个字符串要显示{j=0;//指向待显字符串的第0号元素while(*(x[i]+j)!='\0')//只要第i个字符串的第j号元素不是结束标志{P0=*(x[i]+j);//取得该元素值送到P0口显示delay();//调用延时函数j++;//指向下一个元素}}}/************************************************************** 函数功能:主函数**************************************************************/ void main(void){unsigned char i;while(1){for(i=0;i<4;i++)led_display(p);//将指针数组名作实际参数传递}}//实例35:字符函数ctype.h应用举例#include<reg51.h>//包含51单片机寄存器定义的头文件#include<ctype.h>void main(void){while(1){P3=isalpha('_')?0xf0:0x0f;//条件运算,若'_'是英文字母,P3=0xf0 }}//实例36:内部函数intrins..h应用举例#include<reg51.h>//包含51单片机寄存器定义的头文件#include<intrins.h>//包含函数isalpha()声明的头文件/*************************************************函数功能:延时约150ms*************************************************/void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}227/192/*************************************************函数功能:主函数*************************************************/void main(void){P3=0xfe;//P3=11111110Bwhile(1){P3=_crol_(P3,1);//将P3的二进制位循环左移1位后再赋给P3 delay();//调用延时函数}}//37stdlib.h//实例37:标准函数stdliib.h应用举例#include<reg51.h>//包含51单片机寄存器定义的头文件#include<stdlib.h>//包含函数isalpha()声明的头文件/*************************************************函数功能:延时约150ms*************************************************/void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char i;while(1){for(i=0;i<10;i++)//产生10个随机数{P3=rand()/160;//将产生的随机数缩小160倍后送P3显示delay();}}}//实例 38:字符串函数 striing.h应用举例 #include<reg51.h> //包含 51 单片机寄存器定义的头文件 #include<string.h> //包含函数 isalpha ()声明的头文件 void main(void){unsigned char str1[ ]="Now, The temperature is :";unsigned char str2[ ]="Now, The temperature is 36 Centgrade:"; unsigned char i;i=strcmp(str1,str2); //比较两个字符串,并将结果存入i if(i==0) //str1=str2P3=0x00;elseif(i<0) //str1<str2P3=0xf0;else //str1>str2P3=0x0f;while(1); //防止程序“跑飞”}// 39 2 #include<reg51.h> //实例 39:宏定义应用举例2 //包含 51 单片机寄存器定义的头文件 # define F(a,b) (a)+(a)*(b)/256+(b) void main(void){unsigned char i,j,k;i=40;j=30;k=20;//带参数的宏定义,a 和 b 为形参 参} P3=F(i,j+k); while(1);//i 和 j+k分别为实参,宏展开时,实参将替代宏定义中的形//实例40:宏定义应用举例2 #include<AT89X51.h>#include<ctype.h>void main(void){P3_0=0;//将P3.0引脚置低电平,LED点亮P3_1=0;//将P3.0引脚置低电平,LED点亮P3_2=0;//将P3.0引脚置低电平,LED点亮P3_3=0;//将P3.0引脚置低电平,LED点亮P3_4=1;//将P3.4引脚置高电平,LED熄灭P3_5=1;//将P3.5引脚置高电平,LED熄灭P3_6=1;//将P3.7引脚置高电平,LED熄灭P3_7=1;//将P3.7引脚置高电平,LED熄灭while(1);}//实例41:宏定义应用举例3#include<reg51.h >#define MAX100 void main(void) {#if MAX>80P3=0xf0;#elseP3=0x0f;#endif}//包含51单片机寄存器定义的头文件//将MAX宏定义为字符串100//如果字符串100大于80//P3口低四位LED点亮//否则,P3口高四位LED点亮//结束本次编译/***************************************************** ************中断、定时器********中断、定时器*********************中断、定时器*********中断、定时器****************************************************************** **///实例42:用定时器T0查询方式P2口8位控制LED闪烁#include<reg51.h>//包含51单片机寄存器定义的头文件/**************************************************************函数功能:主函数**************************************************************/void main(void){//EA=1;//开总中断//ET0=1;//定时器T0中断允许TMOD=0x01;//使用定时器T0的模式1TH0=(65536-46083)/256;//定时器T0的高8位赋初值TL0=(65536-46083)%256;//定时器T0的高8位赋初值TR0=1;//启动定时器T0TF0=0;P2=0xff;while(1)//无限循环等待查询{while(TF0==0);TF0=0;P2=~P2;TH0=(65536-46083)/256;//定时器T0的高8位赋初值TL0=(65536-46083)%256;//定时器T0的高8位赋初值}}//实例43:用定时器T1查询方式控制单片机发出1KHz音频/************************************************************** 函数功能:主函数**************************************************************/ void main(void){//EA=1;//开总中断//ET0=1;//定时器T0中断允许TMOD=0x10;//使用定时器T1的模式1TH1=(65536-921)/256;//定时器T1的高8位赋初值TL1=(65536-921)%256;//定时器T1的高8位赋初值TR1=1;//启动定时器T1TF1=0;while(1)//无限循环等待查询{while(TF1==0);TF1=0;sound=~sound;//将P3.7引脚输出电平取反TH1=(65536-921)/256;//定时器T0的高8位赋初值TL1=(65536-921)%256;//定时器T0的高8位赋初值}}//44T0P18LED //实例44:将计数器T0计数的结果送P1口8位LED显示#include<reg51.h>//包含51单片机寄存器定义的头文件sbit S=P3^4;//将S位定义为P3.4引脚/************************************************************** 函数功能:主函数**************************************************************/ void main(void){//EA=1;//开总中断//ET0=1;//定时器T0中断允许TMOD=0x02;//使用定时器T0的模式2TH0=256-156;//定时器T0的高8位赋初值TL0=256-156;//定时器T0的高8位赋初值TR0=1;//启动定时器T0while(1)//无限循环等待查询{while(TF0==0)//如果未计满就等待。
51单片机电子日历(电子时钟)程序经过两天的调试,完成了51单片机电子日历课程设计,现在把C程序源代码帖出来纪念一下:~硬件实验箱是伟福LAB2000实验箱。
程序代码:/****************************************************************************//* 电子日历,有时间显示、闹铃、日期、秒表及键盘设置功能*//* 功能键A: 设置位数字+1 闹钟模式下为闹钟开关秒表模式下为记时开关*//* 功能键B: 设置位数字-1 闹钟模式下为闹钟开关*//* 功能键C:设置模式及设置位选择秒表模式下为清零键*//* 功能键D:在四种工作模式下切换设置闹钟开关*//* 曹宇03电子0201029 *//* 2006.6.3 更新*//****************************************************************************/#include#include/***************这里设置程序初始化时显示的时间****************/#define SET_HOUR 12 /*设置初始化小时*/#define SET_MINUTE 00 /*设置初始化分钟*/#define SET_SECOND 00 /*设置初始化秒数*//*************************系统地址****************************/#define BASE_PORT 0x8000 /*选通基地址*/#define KEY_LINE BASE_PORT+1 /*键盘行线地址*/#define KEY_COLUMN BASE_PORT+2 /*键盘列线地址*/#define LED_SEG BASE_PORT+4 /*数码管段选地址*/#define LED_BIT BASE_PORT+2 /*数码管位选地址*/#define LED_ON(x) XBYTE[LED_BIT]=(0x01<<X)&NBSP; *6位led的位选通,带参数宏,参数为0~5*=""#define LED_OFF XBYTE[LED_SEG]=0x00 /*LED显示空*//**************在设置模式下对秒分时的宏定义*****************/#define SECOND 0 /*对应数码管右边两位*/#define MINUTE 1 /*对应数码管中间两位*/#define HOUR 2 /*对应数码管左边两位*//********************定义四种工作模式***********************/#define CLOCK clockstr /*时钟模式*/#define ALART alartstr /*闹钟模式*/#define DATE datestr /*日期模式*/#define TIMER timerstr /*秒表模式*//****************以下是所有子函数的声明*********************/void sys_init(void); /*系统的初始化程序*/void display(void); /*动态刷新一次数码管子程序*/void clockplus(void); /*时间加1S的子程序*/void update_clockstr(void); /*更新时间显示编码*/void update_alartstr(void); /*更新闹钟时间的显示编码*/void update_datestr(void); /*更新日期显示编码*/void update_timerstr(void); /*更新秒表时间的显示编码*/void deley(int); /*延时子程序*/void update_dispbuf(unsigned char *); /*更新显示缓冲区*/unsigned char getkeycode(void); /*获取键值子程序*/void keyprocess(unsigned char); /*键值处理子程序*/unsigned char getmonthdays(unsigned int,unsigned char);/*计算某月的天数子程序*//*功能键功能子函数*/void Akey(void); /*当前设置位+1 开关闹钟开关秒表*/void Bkey(void); /*当前设置位-1 开关闹钟*/void Ckey(void); /*设置位选择秒表清零*/void Dkey(void); /*切换四种工作模式*//**********************全局变量声明部分*********************/unsigned char led[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};/*从0~9的LED编码*/unsigned char ledchar[3]={0x5c,0x54,0x71};/*o n f*///unsigned char key[24]={ /* 键值代码数组对应键位:*/// 0x70,0x71,0x72,0x73,0x74,0x75, /* 7 8 9 A TRACE RESET*/// 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5, /* 4 5 6 B STEP MON */// 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5, /* 1 2 3 C HERE LAST */// 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5}; /* 0 F E D EXEC NEXT */struct{ /*时间结构体变量*/unsigned char s;unsigned char m;unsigned char h;}clock={SET_SECOND,SET_MINUTE,SET_HOUR};struct{ /*闹铃时间结构体变量*/unsigned char m;unsigned char h;}alart={SET_MINUTE,SET_HOUR};struct{ /*日期结构体变量*/unsigned int year;unsigned char month;unsigned char day;}date={6,1,1};struct{ /*秒表时间结构体变量*/unsigned char ms;unsigned char s;unsigned char m;}timer={0,0,0};unsigned char dispbuf[6]; /*显示缓冲区数组*/unsigned char clockstr[6]; /*时间显示的数码管编码数组*/unsigned char alartstr[6]; /*闹钟显示的数码管编码数组*/unsigned char datestr[6]; /*日期显示的数码管编码数组*/unsigned char timerstr[6]; /*秒表显示的数码管编码数组*/unsigned int itime=0,idot; /*定时器0中断计数*/unsigned char itime1=0; /*定时器1中断计数*/sbit P3_1=P3^1; /*外接蜂鸣器的管脚*/bdata bit IsSet=0; /*设置模式标志位0:正常走时1:设置模式*/bdata bit Alart_EN=0; /*闹铃功能允许位0:禁止闹铃1:允许闹铃*/bdata bit IsBeep=0; /*响铃标志位0:未响铃1:正在响铃*/unsigned char SetSelect=0; /*在设置模式IsSet=1时,正在被设置的位,对应上面的宏*/unsigned char *CurrentMode; /*标志当前正设置的功能,如CurrentMode=CLOCK或CurrentMode=A LART等*/void timerplus(void);/**************************函数部分*************************/void main(void){sys_init();while(1){XBYTE[KEY_COLUMN,0x00]; /*给键盘列线赋全零扫描码,判断是否有键按下*/while((XBYTE[KEY_LINE]&0x0f)==0x0f) /*检测是否有键按下,无则一直进行LED的刷新显示*/ {if(Alart_EN&&(clock.h==alart.h)&&(clock.m==alart.m)) {IsBeep=1;}else{ IsBeep=0;P3_1=0;}display();}keyprocess(getkeycode()); /*有键按下时得到键值,并送入键值处理程序*/display(); /*可要可不要*/}}void sys_init(void){TMOD=0x22; /*定时器0和1都设置为工作方式2,基准定时250×2=500us=0.5ms*/TH0=6; /*定时器0中断服务用来产生1秒时钟定时及闹钟蜂鸣器蜂鸣脉冲*/TL0=6; /*定时器1中断服务留给秒表使用,产生1/100秒定时*/TH1=6;TL1=6;ET0=1;ET1=1;EA=1;TR0=1;update_clockstr(); /*初始化时钟显示编码数组*/update_alartstr(); /*初始化闹钟显示编码数组*/update_datestr(); /*初始化日期显示编码数组*/update_timerstr(); /*初始化秒表显示编码数组*/update_dispbuf(clockstr);/*初始化显示缓冲数组*/CurrentMode=CLOCK; /*默认的显示摸式为时钟*/P3_1=0; /*蜂鸣器接线引脚复位*/}void timer0(void) interrupt 1 using 1 /*定时器0中断服务器,用来产生1秒定时*/{itime++;if(itime==1000){if(IsSet) /*在设置模式下,对正在设置的位闪烁显示*/{dispbuf[SetSelect*2]=0; /*对正在设置的位所对应的显示缓冲区元素赋0,使LED灭*/ dispbuf[SetSelect*2+1]=0;}if(IsBeep) P3_1=!P3_1; /*闹钟模式时,产生峰鸣器响脉冲*/if(CurrentMode==CLOCK){dispbuf[2]=dispbuf[2]&0x7f;dispbuf[4]=dispbuf[4]&0x7f;}}if(itime==2000) /*两千次计数为1S 2000×0.5ms=1s*/{itime=0; /*定时1s时间到,软计数清零*/clockplus(); /*时间结构体变量秒数加1 */update_clockstr(); /* 更新时间显示编码数组*/if(CurrentMode!=TIMER) update_dispbuf(CurrentMode); /* 用时间编码数组更新显示缓冲区* /}}void timer1(void) interrupt 3 using 2 /*定时器1中断服务器,用来产生1/100秒定时*/{idot++;if(++itime1==20) /*20*0.5ms=10ms*/{itime1=0;timerplus();update_timerstr();if(CurrentMode==TIMER){update_dispbuf(timerstr);dispbuf[2]=dispbuf[2]&0x7f; /*关闭小数点的显示*/dispbuf[4]=dispbuf[4]&0x7f;if(idot<1000) /*闪烁显示小数点*/{dispbuf[2]=dispbuf[2]|0x80;dispbuf[4]=dispbuf[4]|0x80;}else{dispbuf[2]=dispbuf[2]&0x7f;dispbuf[4]=dispbuf[4]&0x7f;}}}if(idot==2000) idot=0;}/*功能模块子函数*/void clockplus(void) /*时间加1s判断分,时子函数*/{if(++clock.s==60) /*秒位判断*/{clock.s=0;if(++clock.m==60) /*分位判断*/{clock.m=0;if(++clock.h==24) /*时位判断*/{clock.h=0;if(++date.day==(getmonthdays(date.year,date.month)+1)){date.day=1;if(++date.month==13) date.month=1;}}}}}void timerplus() /*秒表1/100秒位加1,判断秒、分子程序*/ {if(++timer.ms==100){timer.ms=0;if(++timer.s==60){timer.s=0;if(++timer.m==60){timer.m=0;}}}}void update_clockstr(void) /*更新时钟显示代码数组clockstr*/{clockstr[0]=led[clock.s%10]; /*给元素0赋相应数码管显示编码,编码序号是秒数的个位*/clockstr[1]=led[(int)(clock.s/10)]; /*给元素1赋相应数码管显示编码,编码序号是秒数的十位*/ clockstr[2]=led[clock.m%10]; /*以下类推*/clockstr[3]=led[(int)(clock.m/10)];clockstr[4]=led[clock.h%10];clockstr[5]=led[(int)(clock.h/10)];}void update_alartstr(void) /*更新闹钟显示代码数组alartstr*/{ /*右边两位显示on:闹钟开启of:闹钟关闭*/if(Alart_EN) alartstr[0]=ledchar[1];/*显示字母n*/else alartstr[0]=ledchar[2]; /*显示字母f*/alartstr[1]=ledchar[0]; /*显示字母o*/alartstr[2]=led[alart.m%10];alartstr[3]=led[(int)(alart.m/10)];alartstr[4]=led[alart.h%10];alartstr[5]=led[(int)(alart.h/10)];}void update_datestr(void) /*更新日期显示代码数组datestr*/{datestr[0]=led[date.day%10];datestr[1]=led[(int)(date.day/10)];datestr[2]=led[date.month%10];datestr[3]=led[(int)(date.month/10)];datestr[4]=led[date.year%10];datestr[5]=led[(int)(date.year/10)];}void update_timerstr(void) /*更新秒表显示代码数组timerstr*/{timerstr[0]=led[timer.ms%10];timerstr[1]=led[(int)(timer.ms/10)];timerstr[2]=led[timer.s%10];timerstr[3]=led[(int)(timer.s/10)];timerstr[4]=led[timer.m%10];timerstr[5]=led[(int)(timer.m/10)];}void display(void) /*刷新显示六位LED一次*/{unsigned char i;for(i=0;i<6;i++){LED_ON(i); /*选通相应位*/XBYTE[LED_SEG]=dispbuf[i]; /*写显示段码*/deley(50); /*延时显示*/LED_OFF; /*写LED全灭段码*/}}void update_dispbuf(unsigned char *str) /*更新显示缓冲区子函数,参数为要用来更新缓冲区的源字符数组的首地址*/{dispbuf[0]=str[0]; /*将要更新的源字符数组内容COPY至dispbuf数组,用作显示缓冲区*/dispbuf[1]=str[1];dispbuf[2]=str[2]|0x80; /*默认把时位和分位后面的小数点显示出来,根据需要再取舍*/dispbuf[3]=str[3];dispbuf[4]=str[4]|0x80;dispbuf[5]=str[5];}void deley(int i) /*延时子函数*/{while(i--);}unsigned char getkeycode(void) /*键盘扫描子程序,返回获得的键码*/{unsigned char keycode; /*键码变量,一开始存行码*/unsigned char scancode=0x20; /*列扫描码*/unsigned char icolumn=0; /*键的列号*/display(); /*用刷新数码管显示的时间去抖*/XBYTE[KEY_COLUMN]=0x00;keycode=XBYTE[KEY_LINE]&0x0f; /*从行端口读入四位行码*/while((scancode&0x3f)!=0) /*取scancode的低六位,只要没变为全0,则执行循环*/{XBYTE[KEY_COLUMN]=(~scancode)&0x3f; /*给列赋扫描码,第一次为011111*/if((XBYTE[KEY_LINE]&0x0f)==keycode) break; /*检测按键所在的列跳出循环*/scancode=scancode>>1; /*列扫描码右移一位*/icolumn++; /*列号加1*/}keycode=keycode<<4; /*把行码移到高四位*/keycode=keycode|icolumn; /*由行码和列码组成键码*///等待按键放开XBYTE[KEY_COLUMN]=0x00;while((XBYTE[KEY_LINE]&0x0f)!=0x0f) display();return keycode;}void keyprocess(unsigned char keycode) /*键值处理函数*/{switch (keycode){case 0x73: Akey();break;case 0xB3: Bkey();break;case 0xD3: Ckey();break;case 0xE3: Dkey();break;default: break;}update_dispbuf(CurrentMode);}unsigned char getmonthdays(unsigned int year,unsigned char month)/*得到某月的天数*/ {unsigned char days;switch (month){case 4:case 6:case 9:case 11:days=30;break;case 2: if(year%4==0) days=29;else days=28;break;default:days=31;break;}return days;}/*功能键子函数部分*/void Akey(void) /*对当前设置位进行加一操作,如果设置秒位,则给秒位清零*/{if(CurrentMode==TIMER) /*秒表模式下启闭走时*/{ TR1=!TR1;return;}if(!IsSet) return; /*如果不是设置模式退出*/switch (SetSelect){case SECOND:if(CurrentMode==CLOCK){clock.s=0; /*如果当前被设置位是秒位,则清零秒位*/update_clockstr();}if(CurrentMode==ALART){Alart_EN=!Alart_EN;update_alartstr();}if(CurrentMode==DATE){if(++date.day==(getmonthdays(date.year,date.month)+1)) date.day=1;update_datestr();}if(CurrentMode==TIMER){TR1=!TR1;}break;case MINUTE:if(CurrentMode==CLOCK){if(++clock.m==60) clock.m=0; /*如果当前被设置分位,则分位加1*/ update_clockstr();}if(CurrentMode==ALART){if(++alart.m==60) alart.m=0;update_alartstr();}if(CurrentMode==DATE){if(++date.month==13) date.month=1;update_datestr();}break;case HOUR: if(CurrentMode==CLOCK){if(++clock.h==24) clock.h=0; /*如果当前被设置时位,则时位加1*/ update_clockstr();}if(CurrentMode==ALART){if(++alart.h==24) alart.h=0;update_alartstr();}if(CurrentMode==DATE){if(++date.year==100) date.year=0;update_datestr();}break;default: break;}update_dispbuf(CurrentMode);}void Bkey(void) /*对当前设置位进行减一操作,如果设置秒分,则给秒位清零,类比Akey()函数*/ {if(!IsSet) return;switch (SetSelect){case SECOND:if(CurrentMode==CLOCK){clock.s=0;update_clockstr();}if(CurrentMode==ALART){Alart_EN=!Alart_EN;update_alartstr();}if(CurrentMode==DATE){if(--date.day==0x00) date.day=getmonthdays(date.year,date.month);update_datestr();}break;case MINUTE:if(CurrentMode==CLOCK){if(--clock.m==0xff) clock.m=59;update_clockstr();}if(CurrentMode==ALART){if(--alart.m==0xff) alart.m=59;update_alartstr();}if(CurrentMode==DATE){if(--date.month==0x00) date.month=12;update_datestr();}break;case HOUR: if(CurrentMode==CLOCK){if(--clock.h==0xff) clock.h=23;update_clockstr();}if(CurrentMode==ALART){if(--alart.h==0xff) alart.h=23;update_alartstr();}if(CurrentMode==DATE){if(--date.year==0xffff) date.year=99;update_datestr();}break;default: break;}update_dispbuf(CurrentMode);}void Ckey(void) /*正常走时模式和设置模式的切换*/{if(CurrentMode==TIMER){TR1=0; /*初始化定时器1设置,停止秒表记时*/ TH1=6;TL1=6;timer.ms=0; /*初始化秒表数组*/timer.s=0;timer.m=0;update_timerstr();}else{if(IsSet==0) /*在非秒表模式下,第一次按下C键进入设置模式,设置时位*/{IsSet=1; /*置位标志位,进入设置模式*/SetSelect=HOUR;return;} /*第二次按C键设置分位,第三次按键设置秒位,第四次按键完成退出设置*/if(SetSelect==0) /*按到第四次,即设置完秒位后,将标志位IsSet置0,完成设置*/{IsSet=0; /*复位标志位,进入正常走时模式*/return;}if(SetSelect>0) SetSelect--; /*设置位的标志变量SetSelect=0:时位1:分位2:秒位*/ }}void Dkey(void) /*工作状态切换:时钟、闹钟、日期、秒表*/{if(CurrentMode==CLOCK) /*切换至闹钟,同时开关闹钟*/{ CurrentMode=ALART;Alart_EN=!Alart_EN;update_alartstr();return;}if(CurrentMode==ALART) /*切换至日期*/{ CurrentMode=DATE;return;}if(CurrentMode==DATE) /*切换至秒表,同时关闭设置模式*/{CurrentMode=TIMER;IsSet=0;return;}if(CurrentMode==TIMER) /*切换至时钟*/{CurrentMode=CLOCK;return;}}当我被上帝造出来时,上帝问我想在人间当一个怎样的人,我不假思索的说,我要做一个伟大的世人皆知的人。
XTALiXTAU2RSF D JAJ DO PO 2^.t2 «3/*4>3 PQ 4TA (>4 fPO .CIEW FeiwiW FO.7/AIP7PZ.Q/阳 昭「加 P2 2如 0 PS 3^A1iALE取陀亦伯P1.OH2 P2 7^A1t5PS.DmXD- P1.1/T2EX F3.1/TXD P1.S P3 2?INTia P1.3 P3.3?INT1尸“P3MQ F-1.5 R3,5ni P1.6 P3 a/WRPI.?帕卡扁■j ] JlPS■g L K 4111lcd1602 电 子 钟//调整 //加1 //减1功能最全的电子钟【单片机】c51数字时钟(带年月日显示)摘要:本设计以单片机为核心,lcd1602显示。
采用独立键盘输入能任意修改当 前时间日期和设定闹钟时间。
具有显示年月日(区分闰年和二月),闹钟报警和 整点报时功能 主程序:/****************************************************************************** *************************************************************************************************** ******************** ***********************************************************************************************************************************************************************************************************************************************************# in elude <reg52.h># in elude "lcd16024.h" sbit keyl = P2A 0;****************** U1Di 2013-09-30 UekT : 23:5L £ H 1 1AT&ftCi ;!CRYSTALp F F_1L-...- d- 5 B 7 ..... ........................ I I4,sbit key2 =卩2人1;sbit key3 =卩2人2;//蜂鸣器//闹钟设计//进入判断闰年标志位〃闰年标志位//日加一标记//闹钟标志//整点报时标志uint8 code str1[] = "D:"; uint8 codestr2[] = "T:";uin t8 code str3[] = "Wek";uin t8 daystr[]="2013-07-29 "; uin t8 timestr[]="21:30:59 N";uin t8 daystr1[]="2013-07-29 ' uint8 timestr1[]="21:30:59 N" uint8 nu mweek = 0; II年月日格式//时分秒格式II闹钟年月日格式〃闹钟时分秒格式II星期II秒II分〃时II日II月II年〃闹钟星期〃闹钟秒〃闹钟分〃闹钟时II闹钟日II闹钟月II闹钟年II闹钟星期标记sbit speaker = P2A3;sbit key4 =卩2人4;bit cal_year = 1; bit leap_year;bit calculate = 0;bit run = 0;bit beep = 0; 〃uint8 num = 0;char week = 1;char sec = 53;char min = 50;char hour = 23; uint8 day = 30;uint8 month = 9; uin t16 year = 2013;char week1 = 1; char sec1 = 58;char min1 = 50;char hour1 = 23; uin t8 day1 = 30;uint8 mon th1 = 9; ui nt16 year1 = 2013;uin t8 WeekData1; uint8 nu mber = 0;uin t8 WeekData; uint8 speaker_ num;uin t8 scan_key(void);II 函数声名********************************************************************************************************* 更新LCD 时间分离读************************************************************************************************************************void TimeCha nge(){//时分秒timestr[7] = sec%10+'0: timestr[6] = sec/10+'0: timestr[4] = min %10+'0:timestr[3] = mi n/10+'0: timestr[1] = hour%10+'0: timestr[0] = hour/10+'0:〃年月日daystr[9] = day%10+'0:daystr[8] = day/10+'0: daystr[6] = mon th%1O+'O: daystr[5] = mon th/1O+'O:daystr[3] = year%1O+'O: daystr[2] = year/1O%1O+'O: daystr[1] =year/1OO%1O+'O: daystr[0] = year/1OOO+'O://星期WeekData = week+'O:}****************************************************************************闹钟更新LCD 时间分离读取*****************************************************************************************************************************************************void TimeCha nge1(){//时分秒timestr1[7] = sec1%10+'0';timestr1[6] = sec1/10+'0:timestr1[4] = min 1%10+'0';timestr1[3] = mi n1/10+'0:timestr1[1] = hour1%10+'0';timestr1[0] = hour1/10+'0:〃年月日daystr1[9] = day1%10+'0'; daystr1[8] = day1/10+'0'; daystr1 [6] = month1%10+'0';初始化系统定时器 0闹 钟 时 间 设 置daystrl [5] = mon th1/1O+'O : daystr1[3] = year1%1O+'O : daystr1[2] = year1/1O%1O+'O : daystr1[1] = year1/1OO%1O+'O : daystr1[0] = year1/1OOO+'O ://星期WeekDatal = week1+'O :}**************************************************************************** *******************************************************************************************************************************************************/void systimer0_i nit(void) {TMOD |=0x01;〃设置为1时用或(|) TMOD &=0xfd;//设置为0时用与(& ) TH0 = 0xDC; // 定时 10msTL0 = 0x00; EA = 1; ET0=1; TR0=1; EX0 = 1;}**************************************************************************** ***************************************************************************************************************************************************/void n aozh on g() {uint8 nu mber = 1; uin t8 a = 0; uin t8 b = 0; if(0 == key4){Delay1Ms(5); if(0 == key4) {a = 1;LCD_write_comma nd(0xc0+9);LCD_write_comma nd(OxOf);}while(!key4);}while(a){if(0 == key4){Delay1Ms(5); if(0 == key4) {a = 0;run = ~run; while(!key4);}}if(run){timestr[9] = 'Y';}else{timestr[9] = 'N';}if(0 == key1){Delay1Ms(5); if(0 == key1) {b = 1;} while(!key1);}while(b){if(0 == key1){ Delay1Ms(5); if(0 == key1) {nu mber++;if(4 == nu mber)b = 0;}while(!key1);if(nu mber == 1){LCD_write_comma nd(0xc0+9); LCD_write_command(OxOf);}if(nu mber == 2){LCD_write_comma nd(0xc0+6); LCD_write_command(OxOf);}if(nu mber == 3){LCD_write_comma nd(0xc0+3); LCD_write_command(OxOf);}}}switch( nu mber){case 1:if(0 == key2) //闹钟秒加1的设置{Delay1Ms(5);if(0 == key2){sec1++;if(60 == sec1){sec1 = 0;}while(!key2);timestr1[7] = sec1%10+'0';timestr1[6] = sec1/10+'0';LCD_write_char(8,1,timestr1 [ 6]);LCD_write_char(9,1,timestr1[7]); LCD_write_command(0xc0+9);}}if(0 == key3) //闹钟秒减1的设置Delay1Ms(5);if(O == key3){seci--;if(sec1 < 0){seci = 59;}while(!key3);timestr1[7] = sec1%10+'0:timestr1[6] = sec1/1O+'O:LCD_write_char(8,1,timestr1 [ 6]);LCD_write_char(9,1,timestr1[7]);LCD_write_comma nd(0xc0+9);}}break;case 2:if(0 == key2) //闹钟分加1的设置{Delay1Ms(5);if(0 == key2){mi n1++;if(60 == mi n1){mini = 0;}while(!key2);timestr1[4] = min 1%10+'0'; timestr1[3] = min1/10+'0';;LCD_write_char(5,1,timestr1[3]);LCD_write_char(6,1,timestr1[4]);LCD_write_comma nd(0xc0+6);}}if(0 == key3) //闹钟分减1的设置{Delay1Ms(5);if(0 == key3)mi n1--;if(mi n1 < 0){mini = 59;}while(!key3);timestr1[4] = min 1%1O+'O: timestr1[3] = min 1/1O+'O';;LCD_write_char(5,1,timestr1[3]);LCD_write_char(6,1,timestr1[4]);LCD_write_comma nd(0xc0+6);}}break;case 3:if(0 == key2) //闹钟时加1的设置{Delay1Ms(5);if(0 == key2){hour1++;if(24 == hour1){hour1 = 0;}while(!key2);timestr1[1] = hour1%10+'0';timestr1[0] = hour1/10+'0';LCD_write_char(2,1,timestr1[0]);LCD_write_char(3,1,timestr1[1]); LCD_write_comma nd(0xc0+3);}}if(0 == key3) //闹钟时减1的设置{Delay1Ms(5);if(0 == key3){hour1--; if(hour1 < 0)******************************************************判断按键进入时间调整hourl = 23;}while(!key3);timestr1[1] = hour1%10+'0:timestr1[0] = hour1/10+'0:LCD_write_char(2,1,timestr1[0]);LCD_write_char(3,1,timestr1[1]);LCD_write_comma nd(0xc0+3);}}break;case 4:b = 0;LCD_write_comma nd(OxOc); break;}}}LCD_write_comma nd(OxOc);while(!key4);}/******************************************************************************************************************************************************************** *******/uint8 sca n_key(void){uint8 nu mber = 1;uint8 a = 0;if(0 == key1){Delay1Ms(5);if(0 == key1){while(!key1);a = 1;LCD_write_comma nd(0xc0+9);LCD_write_comma nd(OxOf);}while(a) {if(0 {=keyl)Delay1Ms(5);if(0 == keyl){nu mber++;while(!key1);TRO = 0;if(nu mber == 2){LCD_write_comma nd(0xc0+6);LCD_write_comma nd(0x0f);}if(nu mber == 3){LCD_write_comma nd(0xc0+3);LCD_write_comma nd(0x0f);}if(nu mber == 4){LCD_write_comma nd(0x80+11);LCD_write_comma nd(0x0f);}if(nu mber == 5){LCD_write_comma nd(0x80+8);LCD_write_comma nd(0x0f);}if(nu mber == 6){LCD_write_comma nd(0x80+5);LCD_write_comma nd(0x0f);}if(nu mber == 7){LCD_write_comma nd(0xc0+14);LCD_write_comma nd(0x0f);}if(8 == nu mber){LCD_write_comma nd(OxOc);a = 0;nu mber = 0;}}}switch( nu mber){case 1:if(0 == key2) 〃秒加1的设置{Delay1Ms(5);if(0 == key2){sec++;if(60 == sec){sec = 0;}timestr[7] = sec%1O+'O:timestr[6] = sec/1O+'O:LCD_write_char(8,1,timestr[6]);LCD_write_char(9,1,timestr[7]);LCD_write_comma nd(0xc0+9); while(!key2);}}if(0 == key3) 〃秒减1的设置{Delay1Ms(5);if(0 == key3){sec--;if(sec < 0){sec = 59;}timestr[7] = sec%10+'0'; timestr[6] = sec/10+'0'; LCD_write_char(8,1,timestr[6]);if(0 == key3){Delay1Ms(5); if(0== key3) { 〃分减1的设置LCD_write_char(9,1,timestr[7]);LCD_write_comma nd(0xc0+9); while(!key3);}}break;case 2:if(0 == key2) 〃分加1的设置{Delay1Ms(5);if(0 == key2){mi n++;if(60 == min){min = 0;}timestr[4] = min %1O+'O:timestr[3] = min/1O+'O';;LCD_write_char(5,1,timestr[3]);LCD_write_char(6,1,timestr[4]);LCD_write_comma nd(0xc0+6); while(!key2);}}min--;if(min < 0){min = 59;}timestr[4] = min %10+'0';timestr[3] = min/10+'0';LCD_write_char(5,1,timestr[3]);LCD_write_char(6,1,timestr[4]); LCD_write_command(0xc0+6);while(!key3);} break;case 3:if(0 == key2) 〃时加1的设置{Delay1Ms(5);if(0 == key2){hour++;while(!key2);if(24 == hour){hour = 0;}timestr[1] = hour%10+'0:timestr[0] = hour/10+'0:LCD_write_char(2,1,timestr[0]);LCD_write_char(3,1,timestr[1]);LCD_write_comma nd(0xc0+3);}}if(0 == key3) 〃时减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);hour--;if(hour < 0){hour = 23;}timestr[1] = hour%10+'0';timestr[0] = hour/10+'0';LCD_write_char(2,1,timestr[0]);LCD_write_char(3,1,timestr[1]);LCD_write_comma nd(0xc0+3);}}break;case 4:if(O == key2) 〃日加1的设置{Delay1Ms(5);if(0 == key2){while(!key2);calculate = 1;if(calculate == 1){if(mon th==1|m on th==3|m on th==5|m on th==7|m on th==8|m on th==10| mon th==12) {day++;if(day > 31){day=1;}}if(mon th==4 |mon th==6|m on th==9|m on th==11) {day++;if(day > 30){day=1;}}if(mon th == 2){cal_year = 1;while(cal_year == 1){leap_year = ((year % 4 == 0 && year % 100 != 0)||(year % 400 == 0));cal_year = 0;}if(leap_year==1){day++;{day=1;} else{day++;if(day > 29){day=1;}}} calculate = 0;}daystr[9] = day%10+'0:daystr[8] = day/1O+'O:LCD_write_char(10,0,daystr[8]);LCD_write_char(11,0,daystr[9]);LCD_write_comma nd(0x80+11);}}if(0 == key3) 〃日减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);calculate = 1;if(calculate == 1){if(mon th==1|m on th==3|m on th==5|m on th==7|m on th==8|m on th==10| mon th==12) {day--;if(day == 0){day=31;}}if(mon th==4 |mon th==6|m on th==9|m on th==11){ day--;if(day == 0){}if(mon th == 2){cal_year = 1;while(cal_year == 1){leap_year = ((year % 4 == 0 && year % 100 != O)||(year % 400 == 0));cal_year = 0;}if(leap_year==1){day--;if(day == 0){day=30;}}else{day--;if(day == 0){day=29;}}} calculate = 0;}daystr[9] = day%10+'0:daystr[8] = day/10+'0';LCD_write_char(10,0,daystr[8]);LCD_write_char(11,0,daystr[9]);LCD_write_comma nd(0x80+11);} } break;case 5:if(0 == {key2) 〃月加1的设置if(0 == key2){Delay1Ms(5); if(0== key2) { 〃年加1的设置Delay1Ms(5);if(O == key2){while(!key2);mon th++;if(13 == mon th){mon th = 1;}daystr ⑹=mo nth%1O+'O: daystr ⑸=month/1O+'O: LCD_write_char(7,0,daystr ⑸);LCD_write_char(8,0,daystr ⑹);LCD_write_comma nd(0x80+8);}}if(0 == key3) 〃月减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);mon th--;if(mon th == 0){month = 12;}daystr ⑹=mo nth%1O+'O:daystr ⑸=mon th/1O+'O:LCD_write_char(7,0,daystr ⑸);LCD_write_char(8,0,daystr ⑹);LCD_write_comma nd(0x80+8);}}break;case 6:while(!key2);〃年减1的设置}daystr[3] = year%10+'0: daystr[2] = year/10%10+'0:daystr[1] = year/100%10+'0: daystr[0] =year/1OOO+'O : LCD_write_char(2,0,daystr[0]);LCD_write_char(3,0,daystr[1]);LCD_write_char(4,0,daystr[2]);LCD_write_char(5,0,daystr[3]); LCD_write_command(0x80+5);} if (0 == key3){Delay1Ms(5);if(0 == key3){while(!key3);year--;if(year == 0){year = 2020;}daystr[3] = year%10+'0';daystr[2] = year/10%10+'0';daystr[1] = year/100%10+'0'; daystr[0] =year/1000+'0'; LCD_write_char(2,0,daystr[0]);LCD_write_char(3,0,daystr[1]);LCD_write_char(4,0,daystr[2]);LCD_write_char(5,0,daystr[3]);LCD_write_comma nd(0x80+5);}} break;case 7:if(0 == key2){Delay1Ms(5); if(0== key2) { 〃星期加1的设置while(!key2);if(7 == week){ week = 0;}LCD_write_char(14,1,week+'O');LCD_write_comma nd(OxcO+14);}}if (0 == key3) 〃星期减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);week--;if(week < 0){ week = 6;}LCD_write_char(14,1,week+'O');LCD_write_comma nd(OxcO+14);}}break;case 8:TRO = 1;break;}}}**************************************************************************** ************************************************************************************************************************************************ *******/void mai n(void){systimer0_i nit();LCD_i ni t();LCD_write_str(O,O,str1);********************** //定时10msLCD_write_str(0,1,str2);LCD_write_str(13,0,str3);speaker = 0;while (1){TimeCha nge();sca n_key();n aozho ng();LCD_write_str(2,0,daystr);LCD_write_str(2,1,timestr);LCD_write_char(14,1,WeekData);if(1 == run){if(sec==sec1 & mon th==mon th1 & hour==hour) {speaker_ num =30;beep = 1;}}else{speaker_ num =0;beep = 0;}}}***********************************************************************************定 时 中 断 0**************************************************************************************************************************/void time_0() in terrupt 1 {THO = 0xDC;TL0 = 0x00;nu mber++;if(nu mber ==100){sec++; if(beep){//判断这个月有多少天 speaker=!speaker;speaker, nu m--;if(speaker_ num == 0){beep=0;speaker = 0;}}if(sec == 60){sec = 0;mi n++;if(min == 60){min = 0;hour++;//小时加 1 speaker_ num = hour%12;// 蜂鸣器响的次数beep = 1;if(hour == 24){hour = 0;calculate = 1; if(calculate == 1) {if(mon th==1|m on th==3|m on th==5|m on th==7|m on th==8|m on th==10| mon th==12) {day++;if(mon th==7|m on th==12){week++;if(7 == week){week = 0;}}else{if(day <= 31){week++;if(7 == week){week = 0;}if(day > 31){if(mon th==7|m on th==12){day = 1;}else{day=0;}mon th++;if(mon th > 12){mon th=1;year++; cal_year=1;}}}if(mo nth==4|m on th==6|m on th==9|m on th==11) { day++;week++;if(7 == week){week = 0;}if(day > 30){day=1;mon th++;if(mon th > 12){mon th=1;year++;cal_year=1;}}}if(mon th == 2){!= O)||(year % 400 == 0));while(cal_year == 1){leap_year = ((year % 4 = = 0 && year % 100cal_year = 0;}if(leap_year==1){day++;if(day <= 30){week++;if(7 == week){ week = 0;}}if(day > 30){day=1; mon th++;if(mon th > 12){mon th=1;year++;cal_year=1;}}}else{day++;week++;if(7 == week){ week = 0;}if(day > 29){day=1; mon th++;if(mon th > 12){mon th=1;year++;cal_year=1;}}}}}calculate=O;}}}}}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////// Lcd1602.c 子程序:////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// **********************lcd1602 低层函****************************************************************************************************************************/#in clude <reg52.h>#in clude vintrin s.h>#in clude "lcd16024.h"# define //LCD1602的数据口定义sbit LCD_RS = POP;sbit LCD_RW = PO A1;sbit LCD_EN =卩0人2;/******************************************************************************************************************************************************************************************************************************** *******/ void Delay1Us(ui nt16 n){for(; n> 0; n--){//LCD1602控制线的定义,4位控制方式延时1MS延时IMS********************** 延时1MS***************** ***************************** LCD 写一个字节命令函数*****_n op_();****************************************************************************************************************************************************************************************************************************** *******/void Delay1Ms(ui nt16 n){while( n--){Delay1Us(1000);}}******************************************************************************************************************************************************************************************************** *******/void LCD_e n_write(void) {LCD_EN=0;LCD_EN=1;Delay1Us(1);LCD_EN=0;}**************************************************************************** ************************************************************************************** void LCD_write_comma nd(ui nt8 comma nd) {Delay1Us(16);LCD_RS=0;}LCD_RW=0;LCD_DATA&=OxOf;***************LCD写一个字节数据函数******************************** ******************************************************************************* *******/void LCD_write_data(ui nt8 Data) { Delay1Us(16);LCD_RS=1;LCD_RW=0;LCD_DATA&=OxOf;LCD_DATA|=Data &OxfO;LCD_e n_write();Data=Data<<4;LCD_DATA&=OxOf;LCD_DATA|=Data &OxfO; LCD_e n_write();}**************************************************************************** ******************************************************* ************************************************ LCD1602光标定位函数x--列0~15; y--行0~1LCD_DATA|=comma nd&OxfO;LCD_e n_write();comma nd=comma nd<<4;LCD_DATA&=OxOf;LCD_DATA|=comma nd&OxfO;LCD_e n_write();}/****************************************************************************** ****************************************************************************************************************************************************************** *******/void LCD_set_xy(ui nt8 x,ui nt8 y){uint8 address; if(y==0)address=0x80+x;else address=OxcO+x;LCD_write_comma nd(address);}******* **************** ************************ LCD1602 初始化函数, 四位显示方式 ******************************************************************************* *******/ void LCD_i nit() { LC D_write_c omma nd(0x28); // Delay1Us (40); **************************************************************************** ******* ********************** *********************************LCD写字 符 串********************** **************************************************************************************** X —列 0~15; y--行 0~1s 指向字符串数组**************************************************************************************/void LCD_write_str(ui nt8 x,ui nt8 y,ui nt8 *s) {LCD_set_xy(x,y);while(*s){LCD_write_data(*s);s++;}}********************************************************************************************************* LCD个字符 x--列 0~15; y--行 0~1d--字符的ASCII 码 ******************************************************* ******************************************************* *******************************************************LCD1602 左移**************************************************************************************/void LCD_write_char(ui nt8 x,ui nt8 y,ui nt8 d) {LCD_set_xy(x,y);LCD_write_data(d);} /*//////////////////////////////////////////////////////////////////等待繁忙标志/////////////////////////////////////////////////////////////////void LCD_wait(void){P0 = OxFF; do{LCD_RS = 0;LCD_RW = 1;LCD_EN = 0;LCD_EN = 1; }while (BUSY == 1); LCD_EN = 0;}*/************************************************************************************************************************* **************************************************************************************void LCD_youyi(u int8 y,ui nt8 *s){LCD_write_str(17,y,s);for(a=0;a<16;a++){LCD_write_command(0x1c); // 左移 LCD_write_command(0x1c);为右移Delay1Ms(6);}}*///LCD_write_command(OxOd);// 光标闪烁//LCD_write_command(OxOe);// 光标显示不闪烁 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Lcd1602.h头文件////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef _LCD16024_H_#defi ne _LCD16024_H_typedef un sig ned char uin t8;typedef un sig ned int uin t16;typedef un sig ned long uin t32;void Delay1Us(ui nt16 n);void Delay1Ms(ui nt16 n);void LCD_write_data(ui nt8 dat);void LCD_write_command(uint8 com); //BuysC 为0 时忽略忙检测void LCD_set_xy(ui nt8 x,ui nt8 y);void LCD_e n_write(void);void LCD_write_char(ui nt8 x, ui nt8 y, ui nt8 Data1);void LCD_write_str(ui nt8 x, uint8 y,ui nt8 *s);void LCD_i ni t();//void LCD_wait(void);//void LCD_youyi(u int8 y,ui nt8 *s);#en dif。
---------------------------------------------------------------范文最新推荐------------------------------------------------------ 51单片机的数字电流表设计+C语言源码+电路图+仿真图摘要:本文设计了一种可以对被测流电流数字显示和报警的基于单片机的数字电流表。
该设计包括由AT89S51构成的主控模块,选用ACS712系列芯片的数据采集模块,采用ADC0808芯片的模-数转换模块,LED显示模块和报警电路。
程序设计采用C语言编写,并采用proteus软件实现仿真。
通过仿真,设计实现预期功能,具有结构新颖,精确度高,电路简单,性价比高等特点。
关键词:A/D转换器;AT89S51;ACS712电流测量芯片4592The Design of Digital Ammeter Based on MCU1 / 18Abstract: This paper introduces a design of digital ammeter that can measure the current of digital display and alarm. The design chooses AT89S51 as the main control module, uses ACS712 series chip as data acquisition module, with using ADC0808 chip as analog-to-digital conversion module and includes LED display module and alarm circuit. The design adapts C language to complete the programme and simulation debugging is carried out by proteus. Through the simulation, the design can achieve the anticipated function and it has the advantages of novel structure, high precision, simple circuit, high performance-cost ratio.Key words: A/D converter; AT89S51; ACS712 current measurement chip目录摘要1---------------------------------------------------------------范文最新推荐------------------------------------------------------ 引言11. 系统整体设计11.1 系统硬件模块组成21.2 电路工作原理22. 电流测量系统硬件设计22.1 数据采集电路设计32.2 A/D转换芯片结构52.3 AT89S51单片机结构介82.4 LED电路显示设计102.5 报警电路的设计113. 软件程序设计123 / 183.1 程序流程图123.2 程序编写124. 仿真与调试13图1系统基本框图2. 电流测量系统硬件设计硬件电路设计大体上分为数据采集电路、A/D转换电路、主控电路、LED显示电路、报警电路等。
//基于51单片机的八位数字秒表//开发语言:C51//所选芯片:AT89S51//开发者:jnu.bluecoffee//开发日期:2009年6月18日//小弟刚刚入道,完全原创。
如有转载,请注明出处。
#include <reg51.h>#include <intrins.h>#define DIG_NONE 0xff;#define DIG_1 0x7f#define DIG_2 0xbf#define DIG_3 0xdf#define DIG_4 0xef#define DIG_5 0xf7#define DIG_6 0xfb#define DIG_7 0xfd#define DIG_8 0xfe#define LINE 0xf7//根据共阴共阳以及接法要调整typedef unsigned char Byte;typedef bit bool;sbit START = P3^0;sbit RESET = P3^1;Byte data dis_digit;Byte data min;Byte data sec;Byte data msec;bool data isStarted;Byte data dis_digit;Byte data dis_index;Byte data dis_buff[8];Byte data dis_num[8];//根据共阴共阳以及数码管接法这里要的表要调整Byte code number[11]={ 0x28, 0x7E, 0xA2, 0x62, 0x74, 0x61, 0x21, 0x7A, 0x20, 0x60,0xff};//0,1,2,3,4,5,6,7,8,9,关显示,数码管码表Byte dis_buff[8]; // 显示缓冲区Byte dis_num[8]; // 秒计数值, BCD码Byte dis_index;bit Scan_Key();void Proc_Key();void Delayms(Byte ms);void Update_buff();void Msec_Increment();void Reset(void);bool Get_Key(bit key);//有效为1void MCU_Init(void);void Timer0_Overflow();void Timer1_Overflow();//sbit K1 = P3^2;void Msec_Increment()//中断里面的设置{msec += 1;if (msec == 100){msec = 0;sec += 1;}if (sec == 60){sec = 0;min += 1;}if (min == 60)min = 0;}void MCU_Init(){P1 = 0xff;P2 = 0xff;TMOD = 0x12;TH1 = 0xd8;TL1 = 0xf0;TH0 = 0x9c;TL0 = 0x00;////定时器1选用方式1工作,扫描周期0.01s=10ms,定时器0选用工作方式3工作,自动装入,扫描周期0.1ms=100μsReset();min = 0;sec = 0;msec = 0;dis_digit = 0x7f; // 初始显示P20口数码管dis_index = 0;IE = 0x8a; // 使能timer0, timer1中断TR0 = 1;TR1 = 0;isStarted = 0;}void Reset(){min = 0;sec = 0;msec = 0;Update_buff();}void Update_buff(){dis_num[0] = min / 10;dis_num[1] = min % 10;dis_num[3] = sec / 10;dis_num[4] = sec % 10;dis_num[6] = msec / 10;dis_num[7] = msec % 10;//这里根据数码管的顺序进行调整dis_buff[0] = number[dis_num[7]];dis_buff[1] = number[dis_num[6]];dis_buff[2] = LINE;dis_buff[3] = number[dis_num[4]];dis_buff[4] = number[dis_num[3]];dis_buff[5] = LINE;dis_buff[6] = number[dis_num[1]];dis_buff[7] = number[dis_num[0]];}bool Get_Key(bit key)//有效为1,这里按下为低电平{if (key == 0)return1;elsereturn0;}void timer0() interrupt 1{P2 = 0xff; // 先关闭所有数码管P1 = dis_buff[dis_index]; // 显示代码传送到P0口P2 = dis_digit; //dis_digit = _cror_(dis_digit,1); // 位选通值右移(P20<-P27), 下次中断时选通下一位数码管//_cror_()为字符循环右移函数dis_index++; //dis_index &= 0x07; // 8个数码管全部扫描完一遍之后,再回到第一个开始下一次扫描}void timer1() interrupt 3{TH1 = 0xd8;TL1 = 0xf0;Msec_Increment();Update_buff();}void delayms(unsigned char ms)// 延时子程序{unsigned char i;while(ms--){for(i = 0; i < 120; i++);}}void main(void){bool startkey, resetkey;MCU_Init();while(1){startkey = Get_Key(START);resetkey = Get_Key(RESET);if (startkey == 1){Delayms(50);startkey = Get_Key(START);if (startkey == 1){isStarted = !isStarted;TR1 = !TR1;}}if (resetkey == 1 && isStarted == 0) {Delayms(20);resetkey = Get_Key(RESET);if (resetkey == 1 && isStarted == 0) {Reset();}}}}。
基于51单片机的万年历,闹钟,秒表设计有关接线图完整的程序代码#include<reg52.h>#define uchar unsigned char#define uint unsigned intuchar code table[]={"20 年月日"};uchar code table1[]={" : : "};uchar code table5[]={" QI CHUANG LA"};void LCD_WRITE_COM(uchar com);void LCD_WRITE_DAT(uchar dat);void LCD_CSH();void LCD_GD();void LCD_CLR();void DELAYUS(uchar i);void DELAY(uint t);void DELAY_A(uint n);void DISP_TIME();void DISL1();void DISL3();void DS1302_CSH();void DS1302_WRITE(uchar addr,uchar dat); void WRITE_BTY(uchar dat);void DSweek(uchar num);void DS1820RST();void DS1820WR(uchar dat);void KEYSCAN();void KEYMOVE();void TIME_UP();void TIME_DOWN();uchar DS1820RD();uchar READ_T();uchar DS1302_READ(uchar addr);uchar READ_BTY();sbit IO=P3^5;sbit RST=P1^7;sbit SCLK=P1^6;sbit FMQ=P2^4;sbit DQ=P2^3; //DS18B20输出口sbit RS=P2^5; //寄存器选择信号sbit RW=P2^6; //读写控制信号线sbit LCDEN=P2^7; //使能信号线sbit S1=P1^0;sbit S2=P1^1;sbit S3=P1^2;sbit S4=P1^3;sbit S=P1^4;char BW,SW,GW;uchar t,tflag;uchar m,f,s,x,r,y,n;uchar A,A_m,A_f,A_s,A_x;uchar num1,num2;uchar flag,flag_A,flag_j;uchar shi,ge;uchar M_a,M_b,M_c,M_d,M_e,M_f,temp,ss; long int z=0,m1,m2;//*********延时*********void DELAY(uint t) //延时1MS{int x,y;for(x=t;x>0;x--)for(y=110;y>0;y--);}void DELAY_US(uint i) //延时1US {while(i--);}void DELAY_A(uint i){ uint j;char k;for(j=0;j<i;j++){ if(S4==0){DELAY(20);if(S4==0){break;}}for(k=110;k>0;k--){FMQ=1;DELAY(10);FMQ=0;DELAY(10);if(S4==0){DELAY(20); if(S4==0) {break;} }}}}//*********LCD模块*******void LCD_CSH(){ LCD_WRITE_COM(0x38); //设置液晶工作模式 16*2行显示,5*7点阵,8位数据DELAY(1);LCD_WRITE_COM(0x0c); //开显示DELAY(1);LCD_WRITE_COM(0x06); //光标移动DELAY(1);LCD_WRITE_COM(0x01); //清屏DELAY(1);}void LCD_WRITE_COM(uchar com){RW=0; //写RS=0; //寄存器模式选择,写命令P0=com; //写命令LCDEN=0;DELAY(1);LCDEN=1; //使能,0到1DELAY(1);LCDEN=0; //数据送入有效}void LCD_WRITE_DAT(uchar dat){RW=0;RS=1; //寄存器选择,写数据P0=dat; //写数据LCDEN=0;DELAY(1);LCDEN=1; //使能0到1DELAY(1);LCDEN=0; //数据送入有效}void LCD_WORD(unsigned char *p){while(*p>0){ LCD_WRITE_DAT(*p) ;p++;}}//固定显示void LCD_GD(){char i;LCD_WRITE_COM(0x80); //"20 年月日"for(i=0;i<15;i++){LCD_WRITE_DAT(table[i]);DELAY(1);}LCD_WRITE_COM(0x90); //" : : "for(i=0;i<11;i++){LCD_WRITE_DAT(table1[i]);}LCD_WRITE_COM(0x99);LCD_WRITE_DAT(0x03);LCD_WRITE_DAT(0x03);LCD_WRITE_COM(0x9A);LCD_WORD("萍水缘");LCD_WRITE_DAT(0x03);LCD_WRITE_DAT(0x03);}//清屏void LCD_CLR(){LCD_WRITE_COM(0x01);DELAY(2);}//上电欢迎界面void DISL1(){ LCD_WRITE_COM(0x80);LCD_WORD("基于51单片机的万年历,欢迎使用!"); }void DISL3() //闹钟时间到的显示界面{char i;LCD_WRITE_COM(0x80);for(i=0;i<15;i++){LCD_WRITE_DAT(table5[i]);DELAY(1);}LCD_WRITE_COM(0x90);for(i=0;i<15;i++){LCD_WRITE_DAT(table5[i]);DELAY(1);}}//********DS1302模块**********void DS1302_CSH()//(写程序要对照DS1302的各个写地址){RST=0;SCLK=0;DS1302_WRITE(0x8e,0x00);//允许写DS1302_WRITE(0x80,0x00);//初始秒0DS1302_WRITE(0x82,0x00);//初始分0DS1302_WRITE(0x84,0x15);//初始时0DS1302_WRITE(0x8a,0x01);//初始星期6DS1302_WRITE(0x86,0x04);//初始日1DS1302_WRITE(0x88,0x06);//初始月1DS1302_WRITE(0x8c,0x12);//初始年11DS1302_WRITE(0x8e,0x80);//写保护关}uchar DS1302_READ(uchar addr){uchar dat;RST=0; //初始CE为0SCLK=0; //初始时钟线为0RST=1; //传输开始WRITE_BTY(addr); //传送读取时间的地址dat=READ_BTY(); //读取时间SCLK=1; //时钟线拉高RST=0; //传输结束return dat; //返回时间}void DS1302_WRITE(uchar addr,uchar dat) {RST=0; //初始CE为0SCLK=0; //初始时钟线为0RST=1; //传输开始DELAY(1);WRITE_BTY(addr); //传送读取时间的地址WRITE_BTY(dat); //写入修改的时间SCLK=1; //时钟线拉高RST=0; //传输结束}uchar READ_BTY(){uchar i,dat=0;SCLK=0;DELAY(1);for(i=0;i<8;i++){dat=dat>>1;DELAY(1);if(IO==1) //如果读出数据是1(当前数据线为高时,证明该位数据为1)dat|=0x80; //要传输数据的当前位置为1,不是,则为0SCLK=1; //拉高时钟线DELAY(1);SCLK=0; //制造下降沿DELAY(1);}return dat;}void WRITE_BTY(uchar dat){uchar i;SCLK=0; //当前时钟线为0DELAY(1);for(i=0;i<8;i++) //开始传输8为数据{IO=dat&0x01; //取最低位DELAY(1);SCLK=0; //拉低时钟线DELAY(1);SCLK=1; //拉高时钟线dat=dat>>1; //数据右移一位,准备传输下一个数据}}//显示时间void DISP_TIME(){LCD_WRITE_COM(0x81);//显示年,DS1302的读地址8d为年位置,LCD显示在0x81位置shi=DS1302_READ(0x8d)/16;ge=DS1302_READ(0x8d)%16;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x83); //显示月,DS1302的读地址83为年位置shi=DS1302_READ(0x89)/16;ge=DS1302_READ(0x89)%16;LCD_WRITE_DAT(shi+0x30);LCD_WRITE_DAT(ge+0x30);LCD_WRITE_COM(0x85);//显示日shi=DS1302_READ(0x87)/16;ge=DS1302_READ(0x87)%16;LCD_WRITE_DAT(shi+0x30);LCD_WRITE_DAT(ge+0x30);LCD_WRITE_COM(0x90);//显示小时shi=DS1302_READ(0x85)/16;ge=DS1302_READ(0x85)%16;LCD_WRITE_DAT(shi+0x30);LCD_WRITE_DAT(ge+0x30);LCD_WRITE_COM(0x92);//显示分钟shi=DS1302_READ(0x83)/16;ge=DS1302_READ(0x83)%16;LCD_WRITE_DAT(shi+0x30);LCD_WRITE_DAT(ge+0x30);LCD_WRITE_COM(0x94);//显示秒shi=DS1302_READ(0x81)/16;ge=DS1302_READ(0x81)%16;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);DSweek(DS1302_READ(0x8b)); //显示星期if(A==1) //显示闹钟{LCD_WRITE_COM(0x87);LCD_WRITE_DAT(0x20);LCD_WRITE_DAT(0x0e);}if(A!=1){LCD_WRITE_COM(0x87);LCD_WRITE_DAT(' ');}}//显示时间的星期模块void DSweek(uchar num){LCD_WRITE_COM(0x95); //95位置清空,96.97显示周一,二,三,四,五,六,日LCD_WRITE_DAT(0x20);LCD_WRITE_DAT(0x20);LCD_WRITE_COM(0x96);switch(num){case 1:LCD_WRITE_DAT(0xD6);LCD_WRITE_DAT(0xDC);LCD_WRITE_DAT(0xD2);LCD_WRITE_DAT(0xBB);break;case 2:LCD_WRITE_DAT(0xD6);LCD_WRITE_DAT(0xDC);LCD_WRITE_DAT(0xB6);LCD_WRITE_DAT(0xFE);break;case 3:LCD_WRITE_DAT(0xD6); LCD_WRITE_DAT(0xDC);LCD_WRITE_DAT(0xC8);LCD_WRITE_DAT(0xFD);break;case 4:LCD_WRITE_DAT(0xD6); LCD_WRITE_DAT(0xDC);LCD_WRITE_DAT(0xCB);LCD_WRITE_DAT(0xC4);break;case 5:LCD_WRITE_DAT(0xD6); LCD_WRITE_DAT(0xDC);LCD_WRITE_DAT(0xCE);LCD_WRITE_DAT(0xE5);break;case 6:LCD_WRITE_DAT(0xD6); LCD_WRITE_DAT(0xDC);LCD_WRITE_DAT(0xC1);LCD_WRITE_DAT(0xF9);break;case 7:LCD_WRITE_DAT(0xD6); LCD_WRITE_DAT(0xDC);LCD_WRITE_DAT(0xC8);LCD_WRITE_DAT(0xD5);break;}}//**********温度模块*******void DS1820RST() //DS18b20的初始化函数{ uchar x=0;DQ=1; //DQ复位DELAY_US(4); //延时DQ=0; //DQ拉低DELAY_US(100); //精确延时大于480usDQ=1; //拉高DELAY_US(40);x=DQ;}uchar DS1820RD() //读一个字节{uchar i=0,dat=0;for (i=8;i>0;i--){DQ=0; //给脉冲信号 dat=dat>>1;DQ=1; //给脉冲信号if(DQ==1)dat|=0x80;DELAY_US(10);}return dat; //写一个字节}void DS1820WR(uchar dat){char i=0;for (i=8;i>0;i--){DQ=0;DQ=dat&0x01;DELAY_US(10);DQ=1;dat=dat>>1;}}uchar READ_T(){uchar a,b;DS1820RST();DS1820WR(0xcc);//跳过读序列号(固定)DS1820WR(0x44);//启动温度转换DS1820RST();DS1820WR(0xcc);//跳过读序列号DS1820WR(0xbe);//读取温度a=DS1820RD();b=DS1820RD();b<<=4;b+=(a&0xf0)>>4;t=b;return t;}//显示温度void DISP_T(){ uchar R1;R1=READ_T();LCD_WRITE_COM(0xc8);LCD_WRITE_DAT(0xCE);LCD_WRITE_DAT(0xC2);LCD_WRITE_DAT(0xB6);LCD_WRITE_DAT(0xC8);LCD_WRITE_DAT(':');if(R1<0x81){LCD_WRITE_DAT(0x30+R1/100);} else{R1=~(R1)+1;LCD_WRITE_DAT('-');}LCD_WRITE_DAT(0x30+R1%100/10);LCD_WRITE_DAT(0x30+R1%10);LCD_WRITE_DAT(0xA1);LCD_WRITE_DAT(0xE6);}//*******键盘******//读暂停时的时间void TIME(){if(flag==0){m=DS1302_READ(0x81); //分别读出秒,分,时,星期,日,月,年(DS1302的读地址应用)f=DS1302_READ(0x83);s=DS1302_READ(0x85);x=DS1302_READ(0x8b);r=DS1302_READ(0x87);y=DS1302_READ(0x89);n=DS1302_READ(0x8d);}}//时间更新void TIME_UPDATE(){DS1302_WRITE(0x8e,0x00); //写允许DS1302_WRITE(0x80,m); //分别写出秒,分,时,星期,日,月,年(DS1302的写地址应用)DS1302_WRITE(0x82,f);DS1302_WRITE(0x84,s);DS1302_WRITE(0x8a,x);DS1302_WRITE(0x86,r);DS1302_WRITE(0x88,y);DS1302_WRITE(0x8c,n);DS1302_WRITE(0x8e,0x80); //禁止写}//闹钟void ALARM_CLOCK(){LCD_CLR();DELAY(10);DISL3(); //显示起床DELAY_A(100);FMQ=0; //蜂鸣器响flag_A=0;LCD_CLR();LCD_GD(); //固定显示}//闹钟开关显示void ALARM_KG(){if(x!=1){A=0;LCD_WRITE_COM(0x85);LCD_WRITE_DAT(0xb9);LCD_WRITE_DAT(0xd8);x=0;}if(x==1){A=1;LCD_WRITE_COM(0x85);LCD_WRITE_DAT(0xbf);LCD_WRITE_DAT(0xaa);}}//*******秒表******void CSH(){EA=1;ET0=1;TMOD=0x01;TH0=(65535-4900)/256;TL0=(65535-4900)%256;TR0=0;ss=0;M_a=M_b=M_c=M_d=0;}//秒表的键盘扫描void KEYSCAN_M(){ S=0;if(S2==0){DELAY(100);if(S2==0){while(S2==0);ss=~ss;TR0=1;if(ss==0) //S2可以暂停或者继续TR0=0;}}if(S3==0){DELAY(100);if(S3==0){while(S3==0){M_a=M_b=M_c=M_d=0;}}}}void TIME_M() interrupt 1{TH0=(65535-4900)/256;TL0=(65535-4900)%256;temp++;if(temp==2){temp=0;M_c++;if(M_c==10){M_c=0;M_b++;if(M_b==10){M_b=0;M_a++;if(M_a==10){M_a=0;M_d++;if(M_d==6){M_d=0;M_e++;if(M_e==0){M_e=0;M_f++;}}}}}}}//显示秒表,fe:da:bcvoid DISP_M(){ LCD_WRITE_COM(0x83); //显示秒表LCD_WRITE_DAT(0xc3);LCD_WRITE_DAT(0xeb);LCD_WRITE_DAT(0xb1);LCD_WRITE_DAT(0xed);LCD_WRITE_COM(0x91); //显示00:00::00LCD_WRITE_DAT(0x30+M_f);LCD_WRITE_DAT(0x30+M_e);LCD_WRITE_DAT(':');LCD_WRITE_COM(0x93);LCD_WRITE_DAT(0x30+M_d);LCD_WRITE_DAT(0x30+M_a);LCD_WRITE_DAT(':');LCD_WRITE_COM(0x95);LCD_WRITE_DAT(0x30+M_b);LCD_WRITE_DAT(0x30+M_c);}//按键扫描,s1为功能显示,s2为光标移动/秒表暂停(开始),s3为加时间和秒表复位,s4为减时间和停止闹钟void KEYSCAN(){ S=0;if(S1==0){DELAY(100);if(S1==0)while(!S1);{num1++; // 界面切换switch(num1){case 1: num2=0;m=A_m;f=A_f;s=A_s;x=A_x;LCD_CLR();LCD_WRITE_COM(0x80); //显示闹钟设置LCD_WRITE_DAT(0xC4);LCD_WRITE_DAT(0xD6);LCD_WRITE_DAT(0xD6);LCD_WRITE_DAT(0xD3);LCD_WRITE_DAT(0xC9);LCD_WRITE_DAT(0xE8);LCD_WRITE_DAT(0xD6);LCD_WRITE_DAT(0xC3);LCD_WRITE_COM(0x94);LCD_WRITE_DAT(0x30+m/16); LCD_WRITE_DAT(0x30+m%16);LCD_WRITE_COM(0x92);LCD_WRITE_DAT(0x30+f/16); LCD_WRITE_DAT(0x30+f%16); LCD_WRITE_DAT(':');LCD_WRITE_COM(0x90);LCD_WRITE_DAT(0x30+s/16); LCD_WRITE_DAT(0x30+s%16); LCD_WRITE_DAT(':');LCD_WRITE_COM(0x8b);ALARM_KG();break;case 2: LCD_WRITE_COM(0x0c); //开显示LCD_CLR();break;case 3: num2=0;num1=0;A_m=m;A_f=f;A_s=s;A_x=x;LCD_WRITE_COM(0x0c);flag=0; //读暂停的时间标志位LCD_CLR();LCD_GD(); //固定显示break;}}}}//光标移动void KEYMOVE(){ S=0;if(S2==0){ DELAY(100);if(S2==0)while(!S2);{num2++;}}if(num1==0) //调整时间,日期{switch(num2){case 1: //S2按下一次TIME(); //读出暂停的时间flag=1;LCD_WRITE_COM(0x97); //光标在星期位置闪烁LCD_WRITE_COM(0x0f);TIME_UPDATE(); //时间更新,写入设置的时间break;case 2:LCD_WRITE_COM(0x94); //光标在秒位置闪烁TIME_UPDATE(); //时间更新,写入设置的时间break;case 3:LCD_WRITE_COM(0x92); //光标在分钟位置闪烁TIME_UPDATE(); //时间更新,写入设置的时间break;case 4:LCD_WRITE_COM(0x90); //光标在时位置闪烁TIME_UPDATE(); //时间更新,写入设置的时间break;case 5:LCD_WRITE_COM(0x85); //光标在日期位置闪烁TIME_UPDATE(); //时间更新,写入设置的时间break;case 6:LCD_WRITE_COM(0x83); //光标在月份位置闪烁TIME_UPDATE(); //时间更新,写入设置的时间break;case 7:LCD_WRITE_COM(0x81); //光标在年份位置闪烁TIME_UPDATE(); //时间更新,写入设置的时间break;case 8:LCD_WRITE_COM(0x0c); //开显示flag=0; // 读暂停的时间标志位TIME_UPDATE(); //时间更新,写入设置的时间num2=0; //复位 break;}}if(num1==1) //调整闹钟{switch(num2){case 1:LCD_WRITE_COM(0x85); //是够开闹钟LCD_WRITE_COM(0x0f);break;case 2:LCD_WRITE_COM(0x94); //光标在秒位置闪烁break;case 3:LCD_WRITE_COM(0x92); //光标在分钟位置闪烁break;case 4:LCD_WRITE_COM(0x90); //光标在小时位置闪烁break;case 5:LCD_WRITE_COM(0x0c); //开显示num2=0; //复位 break;}}if(S3==0) //加时间{ DELAY(100);if(S3==0)while(!S3);{TIME_UP();}}if(S4==0) //减时间{ DELAY(100);if(S4==0)while(!S4);{TIME_DOWN();}}}//加时间void TIME_UP(){switch(num2){case 1:x++; //星期加1if(x==0x08) x=1;if(num1==0){ DS1302_WRITE(0x8e,0x00);//写允许DS1302_WRITE(0x8a,x);DS1302_WRITE(0x8e,0x80); //写禁止DSweek(DS1302_READ(0x8b));//显示时间的星期模块}if(num1==1){ ALARM_KG();} //闹钟开关显示 break;case 2: m++; //秒加1if(m%16==10) m=(m&0xf0)+0x10;if(m==0x60) m=0;shi=m>>4;ge=m&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x94);break;case 3:f++; //分钟加1if(f%16==10) f=(f&0xf0)+0x10;if(f==0x60) f=0;shi=f>>4;ge=f&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x92);break;case 4:s++; //小时加1if(s%16==10) s=(s&0xf0)+0x10; if(s==0x24) s=0;shi=s>>4;ge=s&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x90);break;case 5:r++; //日期加1if(r%16==10) r=(r&0xf0)+0x10; if(r==0x32) r=1;shi=r>>4;ge=r&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x85);break;case 6:y++; //月份加1if(y%16==10) y=(y&0xf0)+0x10; if(y==0x13) y=1;shi=y>>4;ge=y&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x83);break;case 7:n++; //年份加1if(n%16==10) n=(n&0xf0)+0x10; if(n==0x99) n=1;shi=n>>4;ge=n&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x81);break;}}//减时间void TIME_DOWN(){switch(num2){case 1:x--; //星期减1if(x==0x00) x=7;if(num1==0){DS1302_WRITE(0x8e,0x00); DS1302_WRITE(0x8a,x);DS1302_WRITE(0x8e,0x80);DSweek(DS1302_READ(0x8b));}if(num1==1){ ALARM_KG();}break;case 2:m--; //秒减1if(m%16==15) m=(m&0xf0)+0x09; if(m==0xf9) m=0x59;shi=m>>4;ge=m&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x94);break;case 3:f--; //分钟减1if(f%16==15) f=(f&0xf0)+0x09; if(f==0xf9) f=0x59;shi=f>>4;ge=f&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x92);break;case 4:s--; //小时减1if(s%16==15) s=(s&0xf0)+0x09; if(s==0xf9) s=0x23;shi=s>>4;ge=s&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x90);break;case 5:r--; //日期减1if(r%16==15) r=(r&0xf0)+0x09; if(r==0xf9) r=0x31;shi=r>>4;ge=r&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x95);break;case 6:y--; //月份减1if(y%16==15) y=(y&0xf0)+0x09; if(y==0xf9) y=0x12;shi=y>>4;ge=y&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x93);break;case 7:n--; //年减1if(n%16==15) n=(n&0xf0)+0x09; if(n==0xf9) n=0x99;shi=n>>4;ge=n&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x91);break;}}void main(){ CSH();LCD_CSH();DELAY(10);DS1302_CSH();DISL1(); //上电欢迎界面DELAY(10000);LCD_CLR(); //清屏LCD_GD(); //固定显示while(1){ KEYSCAN();if(num1==2){while(1){DISP_M();KEYSCAN_M();if(S1==0){DELAY(100);if(S1==0)break;}}}KEYMOVE();if(num1==0&&flag==0){DISP_TIME();DISP_T();if(DS1302_READ(0x83)==A_f&&DS1302_READ(0x85)==A_s&&DS1302_R EAD(0x81)==A_m&&A==1){ALARM_CLOCK();}}}}。
完整51单片机多功能电子钟程序代码#include "regx52.h"#define uint8 unsigned charcode uint8 LED[] = {0xc0, 0xf9, 0xa4, 0xb0,0x99, 0x92, 0x82, 0xf8,0x80, 0x90, 0x88, 0x83,0xc6, 0xa1, 0x86, 0x8e}; unsigned char riqi[8]; static uint8 keyReleas;uint8 disptmp;uint8 pos;uint8 buffer[8];code uint8 BIT[8] = {0xfe, 0xfd, 0xfb, 0xf7,0xef, 0xdf, 0xbf, 0x7f}; uint8 flag2ms;uint8 t2msCnt;uint8 halfSecCnt;uint8 IsTimerRun;uint8 mode;void GlobalvarInit();void T0Init();void TimeRun();unsigned char KeyScan();void Command();void Command();void T0IntSvr() interrupt 1 using 1{TL0 = (65536-2000)%256;TH0 = (65536-2000)/256;switch(mode){case 0:disptmp=LED[buffer[pos]]; switch(pos){case 2:case 4:case 6:disptmp&=~(1<<7); break;}break;case 1:disptmp=LED[riqi[pos]]; switch(pos){case 2:case 4:disptmp&=~(1<<7); break;}break;}P2 = 0xff;P0 = disptmp;P2 = BIT[pos];pos++;if(pos>7)pos = 0;flag2ms = 1;}void main(){GlobalvarInit();T0Init();EA = 1;while(1){TimeRun();Command();}}void TimeRun(){if(IsTimerRun == 0) return; if(flag2ms != 1) return; flag2ms = 0;t2msCnt++;if(t2msCnt < 250) return; t2msCnt = 0; halfSecCnt++;if(halfSecCnt < 2) return; halfSecCnt = 0;buffer[0]++;if(buffer[0] < 10) return; buffer[0] = 0;buffer[1]++;if(buffer[1] < 6) return; buffer[1] = 0;buffer[2]++;if(buffer[2] < 10) return;buffer[2] = 0;buffer[3]++;if(buffer[3] < 6) return;buffer[3] = 0;buffer[4]++;switch(buffer[5]){case 0:case 1:if(buffer[4] < 10) return; buffer[4] = 0;break; case 2: if(buffer[4] < 4) return; buffer[4] = 0;break; }buffer[5]++;if(buffer[5] < 3) return;buffer[5] = 0;riqi[0]++;switch(riqi[1]){case 0:if( riqi[0] < 10) return; riqi[0] = 1;break; case 1: case 2:if( riqi[0] < 10) return; riqi[0] = 0;break; case 3:if( riqi[0] < 2) return; riqi[0] = 0;break;}riqi[1]++;if(riqi[1]<4) return;riqi[1]=0;riqi[2]++;switch(riqi[3]){case 0:if( riqi[2] < 10) return; riqi[2] = 1;break;case 1:if( riqi[2] < 3) return; riqi[2] = 0;break; }riqi[3]++;if(riqi[3]<1) return;riqi[3]=0;riqi[4]++;if(riqi[4]<10) return;riqi[4]=0;riqi[5]++;if(riqi[5]<10) return;riqi[5]=0;riqi[6]++;if(riqi[6]<10) return;riqi[6]=0;riqi[7]++;if(riqi[7]<10) return;riqi[7]=0;}void T0Init(){TMOD = TMOD & 0xf0 | 0x01;// 2msTL0 = (65536-2000)%256;TH0 = (65536-2000)/256;ET0 = 1;TR0 = 1;}// 全局变量初始化void GlobalvarInit(){uint8 i;for (i = 0; i < 8; i++){buffer[i] = 0;}pos = 1;flag2ms = 0;t2msCnt = 0; IsTimerRun = 1;mode = 0;riqi[0]= 0;riqi[1]= 2;riqi[2]=6;riqi[3]=0;riqi[4]=3;riqi[5]=1;riqi[6]=0;riqi[7]=2;}unsigned char KeyScan() { unsigned char key;P3 = 0x0f;if ((P3 & 0x0f) == 0x0f) {return 0;}P3 = 0x7f;key = P3;key = key & 0x0f;if(key != 0x0f){return (key | 0x70);}P3 = 0xbf;key = P3;key = key & 0x0f;if(key != 0x0f){return (key | 0xb0);}P3 = 0xdf;key = P3;key = key & 0x0f;if(key != 0x0f){return (key | 0xd0);}P3 = 0xef;key = P3;key = key & 0x0f;if(key != 0x0f){return (key | 0xe0);}return 0;}static uint8 keyRelease = 1; void Key_bd(){buffer[7] = 0x0b; buffer[6] = 0x0d; }void Key_be() {switch(mode) {case 0:mode = 1; break;case 1:mode = 0; break;}}void Key_0x77() {if(buffer[4]>3) {buffer[5]++;if(buffer[5]>1) buffer[5]=0;}else{buffer[5]++;if(buffer[5]>2) buffer[5]=0;}}void Key_0x7b(){switch(buffer[5]){case 0:case 1:buffer[4]++;if(buffer[4]>9)buffer[4]=0; break;case 2:buffer[4]++;if(buffer[4]>3)buffer[4]=0;break; }}void Key_0xee(){switch(riqi[1]){case 0: riqi[0]++;if(riqi[0]>9) riqi[0]=1;break;case 1:case 2:riqi[0]++;if(riqi[0]>9) riqi[0]=0;break;case 3:riqi[0]++;if(riqi[0]>1)riqi[0]=0;break;}}void Key_0xeb() {switch(riqi[3]){case 0:riqi[2]++;if(riqi[2]>9) riqi[2]=1; break;case 1:riqi[2]++;if(riqi[2]>2) riqi[2]=0; break;}}void Key_0xed() {if(riqi[0]<=1){riqi[1]++;if(riqi[1]>3)riqi[1]=0;}if(riqi[0]>1){riqi[1]++;if(riqi[1]>2)riqi[1]=0;}}void Key_0xe7(){if(riqi[2]>2)riqi[3]=0;else{riqi[3]++;if(riqi[3]>1)riqi[3]=0;}}void Command(){uint8 key;key = KeyScan();if (key == 0){keyRelease = 1;return;}if(keyRelease == 0)return;keyRelease = 0;switch(key){case 0xbe: Key_be(); break; // Key_8 case 0xbd: Key_bd(); break; // Key_9 case 0xbb: IsTimerRun = 1; break;// Key_A case 0xb7: IsTimerRun = 0; break;// Key_Bcase 0x77: Key_0x77();break;// Key_Fcase 0x7b: Key_0x7b();break;// Key_Ecase 0x7d: buffer[3]++;if(buffer[3]>5)buffer[3]=0;;break;// Key_D case 0x7e: buffer[2]++;if(buffer[2]>9)buffer[2]=0;;break;// Key_C case 0xde: riqi[4]++;if(riqi[4]>9)riqi[4]=0; break;// Key_4 case 0xdd: riqi[5]++;if(riqi[5]++>9)riqi[5]=0; break;// Key_5 case 0xdb: riqi[6]++;if(riqi[6]>9)riqi[6]=0; break;// Key_6case 0xd7: riqi[7]++;if(riqi[7]>9)riqi[7]=0; break;// Key_7case 0xee: Key_0xee(); break;// Key_0case 0xed: Key_0xed();break;// Key_1case 0xeb: Key_0xeb(); break;// Key_2case 0xe7: Key_0xe7();break;// Key_3}}。
原理图:源程序:/*************************************************************标题:定时器中断精确到00.01的秒表效果:能清零重新开始,暂停,继续计时,能精确到0.01秒作者:皖绩小挺说明:使用12M晶振,四位数码管,3个按键****************************************************************/ #include<reg52.h>#define uint unsigned int#define uchar unsigned charuint temp,tt,qian,bai,shi,ge;sbit smg_q=P1^0;sbit smg_b=P1^1;sbit smg_s=P1^2;sbit smg_g=P1^3;sbit key1 = P3^7;sbit key2 = P3^6;sbit key3 = P3^5;uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};uchar code table1[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //带小数点void keyscan();void display(uint shi,uint ge);void delay(uint z);void init();/************************************************************** 主函数******************************************************************/void main(){init();//初始化子程序while(1){if(tt==1){tt=0;temp++;if(temp==10000){temp=0;}qian=temp/1000;bai=temp%1000/100;shi=temp%100/10;ge=temp%10;}keyscan();display(shi,ge);}}/********************************************************************* 延时***********************************************************************/ void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}/*********************************************************************按键控制***********************************************************************/ void keyscan(){if(key1==0) //清零并重新开始计时{temp=0;TR0=1;}if(key2==0) //暂停计时{TR0=0;}if(key3==0) //继续计时{TR0=1;}}/********************************************************************* 显示***********************************************************************/ void display(uint shi,uint ge){smg_q=0;P0=table[qian];delay(1);smg_q=1;P0=0xff;smg_b=0;P0=table1[bai];delay(1);smg_b=1;P0=0xff;smg_s=0;P0=table[shi];delay(1);smg_s=1;P0=0xff;smg_g=0;P0=table[ge];delay(1);smg_g=1;P0=0xff;}/********************************************************************* 初始化***********************************************************************/ void init(){smg_q=1;smg_b=1;smg_s=1;smg_g=1;temp=0;TMOD=0x01;TH0=(65536-10000)/256;TL0=(65536-10000)%256;EA=1;ET0=1;TR0=1;}/********************************************************************* 中断***********************************************************************/ void t0() interrupt 1{TH0=(65536-10000)/256;TL0=(65536-10000)%256;tt++;}。
电子科学与技术系 科研训练
中文题目: 基于C51单片机为主控芯片的电子时钟 英文题目: Based on C51 single chip microcomputer as main control chip of electronic watch
姓 名: 王**** 学 号: ********** 专业名称: 电子科学与技术 指导教师: 郑国旭
成绩 基于C51单片机为主控芯片的电子表 作者 哈尔滨理工大学电子科学与技术系 [内容摘要]本文论述了用C51单片机制作电子表的方法和过程,电路图以及程序源代码。包括时间基准的选取和实现;1602液晶显示屏的驱动和编程;独立键盘的使用和编程;单片机内部时间中断的原理及编程。
[关键词] C51单片机; 时间基准; 1602液晶显示屏; 编程
Based on C51 single chip microcomputer as main control chip of electronic watch
[Abstract] This paper discusses the using C51 production method and process of digital watches, circuit diagram and the program source code. Including the selection of time benchmark and implementation; 1602 LCD driver and programming; The use of independent keyboard and programming; The principle and programming of single chip microcomputer internal time interrupt.
[Keywords] C51 production; Time benchmark; 1602 LCD; programming 目 录 1 引言 ............................................................................................................................................... 1 2 相关文献综述 ............................................................................................................................... 1 3 元件简述及应用 ........................................................................................................................... 1 3.1 STC89C51RC单片机简介及其应用 ................................................................................. 2 3.1.1 STC89C51RC单片机简介 ...................................................................................... 2 3.1.2 STC89C51RC单片机应用 ...................................................................................... 2 3.2 1602液晶屏简介及其应用 ................................................................................................ 3 3.2.1 1602液晶屏简介 ..................................................................................................... 3 3.2.2 1602液晶屏应用 ..................................................................................................... 4 4硬件电路构建 ................................................................................................................................ 5 4.1中控部分以及时间基准部分 ............................................................................................. 6 4.2按键交互部分 ..................................................................................................................... 7 4.3液晶显示部分 ..................................................................................................................... 8 5 软件程序编程 ............................................................................................................................... 9 5.1计算类函数代码 ................................................................................................................. 9 5.1.1闰年计算函数 .......................................................................................................... 9 5.1.2日期清零函数 .......................................................................................................... 9 5.1.3星期计算函数 ........................................................................................................ 10 5.2独立按键函数 ................................................................................................................... 11 5.2.1 S1数位选择按键 ................................................................................................ 11 5.2.2 S2数值加一按键 ................................................................................................ 12 5.2.3 S3数值减一按键 ................................................................................................ 14 5.3计时器函数 ....................................................................................................................... 15 5.3.1计时器初始化函数 ................................................................................................ 15 5.3.2计时器中断函数 .................................................................................................... 16 5.4全部源代码 ....................................................................................................................... 18 6结论 .............................................................................................................................................. 29