基于52单片机控制的1602液晶电子时钟显示程序(精心整理)
基于51单片机的1602日历时钟程序
if(y == 0)
x |= 0x40 ; //如果显示是在第二行,则x的值加0x40
x |= 0x80 ; //获得x的值
LCD1602_write_cmd(x) ;//写入坐标值到LCD
}
}
/************************************************************
case 3 : sele_count = 3 ; break ;
default : break ;
}
return(self_cou***************************************************
蜂鸣器
************************************************************/
void delay_ms(uint16 count) // 延时时间count*1ms
{ uint16 i;
for(;count>0;count--)
LCD1602_DATA = dat ;
LCD1602_EN = 1 ;
LCD1602_EN = 0 ;
}
/***********************************************************
1602初始化
************************************************************/
uint8 LCD1602_display_self(uint8 count)
51单片机实现电子时钟功能-1602液晶显示
第一章设计要求及系统组成一、基本操作时序:读状态:输入:RS=L,RW=H,E=H 输出:D0~D7=状态字写指令:输入:RS=L,RW=L,D0~D7=指令码,E=高脉冲输出:无读数据:输入:RS=H,RW=H,E= 高脉冲输出:D0~D7数据写数据:输入:RS=H,RW=L。
D0~D7=数据,E=高脉冲输出:无二、、、状态字说明:STA7 D7\ STA6 D6\ STA5 D5 \ STA4 D4 \STA3 D3 \ STA2 D2\\ STA1 D1STA0-6:当前数据地址指针的数值STA7:读写操作使能 1表示禁止,0表示允许对控制器每次进行读写操作之前,都必须进行读写检测,确保STA7为0;但是我们可以进行延时进行实现。
RAM地址映射: LCD 16字*2行00 01 02 03 04 05 06 07 08 08 09 0A 0B 0C 0D 0E 0F (27)40 41 42 4F 50 (67)指令说明:1.初始化设置 1.显示模式设置指令码:00111000(0x38)功能:设置16*2显示,5*7点阵,8位数据接口必须开显示 2.显示开、关及光标设置指令码:00001DCB,功能:D=1 开显示;D=0 关显示;C=1显示光标;B=1 光标闪烁;B=0 光标不显示 000001NS:功能:N=1当读或写一个字符后地址指针加1,且光标加1;N=0相应的减1;S=1当写一个字符,整屏显示左移(N=1)或右移(N=0),以得到光标不移动而屏幕移动的效果。
S=0 当写一个字符,正屏显示不移动。
数据控制:控制器内部设有一个数据地址指针,用户可通过它们来访问内部的全部80字节RAM4.2.1 数据指针设置:指令码:80H+地址码(0-27H,第二行开始:40H-67H) 4..2.2 读数据,写数据其它设置:01H:显示清屏:1.数据指令清零 2 所有显示清零 02H:显示回车:1.数据清零如何进行连接:实际操作中,液晶接到,第一管脚是D,第二管脚是VCC,15和16是背光,D0-D7是数据口,接到单片机的P0口,P0口接了两个锁存器,液晶,D/A,具有高阻状态的都可以随便接,没有影响,,第六管脚是LCDEN相当于 E,使能信号,它接P3^4,R/W接地,表示低电平,因为我们只进行写操作,RS接2实验板上的P3^5;只需这两端口便足以控制液晶,2和3是偏压信号,一端接地,接口信号说明:编号:1 VSS(符号表示)电源地(引脚说明)2VDD 电源正极3VL液晶显示偏压信号4RS数据/命令选择端(H/L)5R/W 读写选择端(H/L)6E使能信号7D0 Data 1/0 8D1 Data 1/0 9 D2 Data 1/0 10 D3 Data 1/0 11D4 Data 1/0 12D5 Data 1/0 13D6 Data 1/0 14D7 Data 1/0 15BLK背光源正极16 BLK背光源负极实际操作:::先写光标程序;写两个子程序,一个写数据,一个写指令:先进性两个宏定义,再位申明LCDEN与RS;为了电量充足。
基于51单片机的1602液晶显示温度和时间的C程序
//液晶显示温度#include "AT89X52.H"#define Ddata P0sbit RS=P2^7; //命令数据控制端sbit RW=P2^6; //读写选择端sbit LCDE=P2^5; //液晶使能端sbit DQ=P2^0; //ds18b20与单片机连接口#define uchar unsigned char#define uint unsigned intunsigned char hour=0,min=0,sec=0; //定义初值unsigned int count=0;unsigned char line1[16]={" temp: "}; //16个字符unsigned char line2[16]={" time: 00:00:00"}; //16个字符unsigned char tab[]={'0','1','2','3','4','5','6','7','8','9'}; //数组uchar data disdata[5];uint tvalue; //温度值uchar tflag; //温度正负标志void time();/*************************lcd1602程序**************************/ void delay1ms(unsigned int ms)//延时1毫秒(不够精确的){unsigned int i,j;for(i=0;i<ms;i++)for(j=0;j<110;j++);}void delay5ms()//延时5毫秒(不够精确的){unsigned int i;for (i=0;i<1000;i++);}void delay50us(){register int i;for (i=0;i<20;i++);}void delay(){unsigned char m,n;for(m=255;m>0;m--)for(n=255;n>0;n--);}void wr_com(unsigned char comm) //********写控制字符程序E=1 RS=0RW=0 **********//{LCDE=0; //使能端RS=0; //********RS寄存器选择输入端,当RS=0;当进行写模块操作,指向指令寄存器。
51单片机c语言编写的1602液晶显示闹钟
#include<reg52.h>#define uchar unsigned char#define uint unsigned intuchar code table[]=" 2012-08-17 MON"; //设定开始显示的时间uchar code table1[]=" 12:30:00";uchar code table2[7][3]= {{"MON"},{"TUE"},{"WED"},{"THU"},{"FRI"},{"SAT"},{"SUN"}};//定义二维字符数组sbit wr=P3^6; // 1602液晶的读/写端sbit dula=P2^6; // 数码管段选sbit wela=P2^7; // 数码管位选sbit lcden=P3^4; // 1602液晶使能端sbit lcdrs=P3^5; // 1602液晶命令/数据端sbit key1=P3^0; // 声明s4按键sbit key2=P3^1; // 声明s8按键sbit key3=P3^2; // 声明s12按键sbit key4=P3^3; // 声明s16按键sbit beep=P2^3; // 声明蜂鸣器sbit rd=P3^7; // 声明4个按键的公共端uchar num1,shi=12,fen=30,miao,yue=8,ri=17,shi1,fen1,miao1,keynum1,week; //定义时分秒变量uint nian=2012; //定义年变量void delayms(uint x){uint i,j;for(i=x;i>0;i--) //定义带参数延时函数for(j=110;j>0;j--);}void write_com(uchar com) //1602液晶写指令函数{ wr=0;lcdrs=0;P0=com;delayms(1);lcden=1;delayms(1);lcden=0;}void write_date(uchar date) //1602液晶写数据函数{ wr=0;lcdrs=1;P0=date;delayms(1);lcden=1;delayms(1);lcden=0;}void write_addate1(uchar add,uint date) //定义显示年的函数{ uint qian;uchar bai,shi,ge;qian=date/1000;bai=date%1000/100;shi=date%1000%100/10;ge=date%10;write_com(add+0x80);write_date(0x30+qian);write_date(0x30+bai);write_date(0x30+shi);write_date(0x30+ge);}void write_addate2(uchar add,uchar date) //定义显示月、日、时、分、秒函数{uchar shi,ge;shi=date/10;ge=date%10;write_com(add+0x80);write_date(0x30+shi);write_date(0x30+ge);}void write_rq(uchar i) //定义显示星期的函数{ uchar x;for(x=0;x<3;x++){ write_date(table2[i][x]);delayms(1);}}void init () //定义初始化函数{dula=0; // 关闭数码管段、位选端wela=0;TMOD=0x01; // 定时器0工作方式为16位TH0=(65536-45872)/256; // 装初值TL0=(65536-45872)%256;EA=1; // 开总中断ET0=1; // 开定时器0中断write_com(0x38); // 设置16*2显示,5*7点阵,8位数据口write_com(0x06); // 写一个字符后地址指针加1write_com(0x0c); // 设置开显示,不显示光标write_com(0x01); // 显示清0,数据清0write_com(0x80); // 使指针指向第1行第1列}void keyscan() // 定义按键函数{uchar keynum;rd=0; //4个按键公共端为低电平if(key1==0) //s4按键被按下{ delayms(3); //去抖延时if(key1==0) //确认s4按键被按下,进入调时间模式{keynum++;while(!key1); //松手检测}if(keynum==1) //s4按下一次{ TR0=0; //关闭定时器0write_com(0x81); //指针指向第1行2列write_com(0x0f); //开启光标显示,光标闪烁}if(keynum==2){write_com(0x86); //光标跳到月份}if(keynum==3){write_com(0x89); //光标跳到日}if(keynum==4){write_com(0x8c); //光标跳到星期}if(keynum==5){write_com(0xc4); //光标跳到时}if(keynum==6){write_com(0xc7); //光标跳到分}if(keynum==7){write_com(0xca); //光标跳到秒}if(keynum==8){ keynum=0; //退出调时间模式TR0=1; //开启定时器0write_com(0x0c); //关闭光标显示}}if(keynum) //当进入调时间模式时{if(key2==0) //s8按键按下{delayms(3); //去抖延时if(key2==0){if(keynum==1){nian++; //s8每按下一次年份加1if(nian==10000) // 加满清0nian=0;write_addate1(1,nian); // 显示年份write_com(0x81); //写完数据指针指向年份原来位置}if(keynum==2){yue++; //s8每按下一次月份加1if(yue==13)yue=0; //加满清0write_addate2(6,yue); //显示月份write_com(0x86); //写完数据指针指向月份原来位置}if(keynum==3){ ri++;if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12) //1,3,5,7,8,10,12月有31天if(ri==32)//加满还原ri=1;if(yue==4||yue==6||yue==9||yue==11) //4,6,9,11月有30天if(ri==31)ri=1;if(yue==2&&((nian%4==0&&nian%100!=0)||nian%400==0)) //闰年2月有30天if(ri==30)ri=1;if(yue==2&&(nian%4!=0)||(nian%100==0&&nian%400!=0)) //非闰年2月有31天if(ri==29)ri=1;write_addate2(9,ri); //显示日write_com(0x89); //写完数据指针指向日原来位置}if(keynum==4){week++;//s8每按下一次星期加1if(week==7)//加满还原week=0;write_rq(week); //显示星期write_com(0x8c); //写完数据指针指向星期原来位置}if(keynum==5){shi++;//s8每按下一次时加1if(shi==24)shi=0;//加满还原write_addate2(0x44,shi); //显示时write_com(0xc4); //写完数据指针指向时原来位置}if(keynum==6){fen++;//s8每按下一次分加1if(fen==60)fen=0;//加满还原write_addate2(0x47,fen); //显示分write_com(0xc7);//写完数据指针指向分原来位置}if(keynum==7){miao++;//s8每按下一次秒加1if(miao==60)miao=0;//加满还原write_addate2(0x4a,miao);//显示秒write_com(0xca);//写完数据指针指向秒原来位置}while(!key2); //松手检测}}if(key3==0){delayms(3);if(key3==0){ //s12按下时减1if(keynum==1){nian--;if(nian==-1)nian=9999;write_addate1(1,nian);write_com(0x81);}if(keynum==2){ yue--;if(yue==-1)yue=12;write_addate2(6,yue);write_com(0x86);}if(keynum==3){ri--;if(ri==0){if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)ri=31;if(yue==4||yue==6||yue==9||yue==11)ri=30;if(yue==2&&((nian%4==0&&nian%100!=0)||nian%400==0))ri=29;if(yue==2&&(nian%4!=0)||(nian%100==0&&nian%400!=0))ri=28;}write_addate2(9,ri);write_com(0x89);}if(keynum==4){week--;if(week==-1)week=6;write_rq(week);write_com(0x8c);}if(keynum==5){shi--;if(shi==-1)shi=23;write_addate2(0x44,shi);write_com(0xc4);}if(keynum==6){fen--;if(fen==-1)fen=59;write_addate2(0x47,fen);write_com(0xc7);}if(keynum==7){miao--;if(miao==-1)miao=59;write_addate2(0x4a,miao);write_com(0xca);}while(!key3); //松手检测}}}if(key4==0) //s16被按下进入调闹钟模式{ delayms(3);if(key4==0){keynum1++;while(!key4);}if(keynum1==1){ write_com(0x01); //清屏,指针清0write_com(0xc6); //在时分之间显示“:”write_date(':');write_com(0xc9); //在分秒之间显示“:”write_date(':');write_com(0x0f); //开启光标write_com(0xc4); //光标指向时}if(keynum1==2){write_com(0xc7);//光标指向分}if(keynum1==3){write_com(0xca); //光标指向秒}if(keynum1==4){ keynum1=0;write_com(0x0c); //关闭光标}}if(keynum1){if(key2==0) //s8按下加1{delayms(3);if(key2==0){if(keynum1==1){shi1++;if(shi1==24)shi1=0;write_addate2(0x44,shi1);write_com(0xc4);}if(keynum1==2){fen1++;if(fen1==60)fen1=0;write_addate2(0x47,fen1);write_com(0xc7);}if(keynum1==3){miao1++;if(miao1==60)miao1=0;write_addate2(0x4a,miao1);write_com(0xca);}while(!key2);}}if(key3==0) //s12每按一次减1{delayms(3);if(key3==0){if(keynum1==1){shi1--;if(shi1==-1)shi1=23;write_addate2(0x44,shi1);write_com(0xc4);}if(keynum1==2){fen1--;if(fen1==-1)fen1=59;write_addate2(0x47,fen1);write_com(0xc7);}if(keynum1==3){miao1--;if(miao1==-1)miao1=59;write_addate2(0x4a,miao1);write_com(0xca);}while(!key3);//松手检测}}}}void main(){ uchar num;init();for(num=0;num<15;num++){ write_date(table[num]);delayms(5);} //显示初始时间write_com(0xc0);for(num=0;num<12;num++){ write_date(table1[num]);delayms(5);}TR0=1; //开启定时器0while(1){ if(shi==shi1&&fen==fen1&&miao==miao1) //闹钟到了蜂鸣器响beep=0;keyscan(); //扫描键盘}}void time() interrupt 1 //中断函数{TH0=(65536-45872)/256;TL0=(65536-45872)%256; //进入中断装初值num1++;if(num1==20) //一秒到了{ num1=0; //清0miao++;if(miao==60) //一分到了{ miao=0; fen++; }if(!keynum1) write_addate2(0x4a,miao); //当调闹钟模式按下时不显示当前时间if(fen==60){ fen=0;shi++;}if(!keynum1) write_addate2(0x47,fen); //当调闹钟模式按下时不显示当前时间if(shi==24){shi=0;ri++;week++;}if(!keynum1) write_addate2(0x44,shi); //当调闹钟模式按下时不显示当前时间if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)if(ri==32){ ri=1; y ue++; }if(yue==4||yue==6||yue==9||yue==11)if(ri==31){ ri=1; yue++; }if(yue==2&&((nian%4==0&&nian%100!=0)||nian%400==0))if(ri==30){ ri=1; yue++; }if(yue==2&&(nian%4!=0)||(nian%100==0&&nian%400!=0))if(ri==29){ ri=1; yue++; }if(!keynum1) write_addate2(9,ri);//当调闹钟模式按下时不显示当前时间if(week==7)week=0;if(!keynum1)//当调闹钟模式按下时不显示当前时间{ write_com(0x8c);write_rq(week);}if(yue==13){ yue=0;nian++;}if(!keynum1)//当调闹钟模式按下时不显示当前时间{write_addate2(6,yue);write_com(0x88);write_date('-');}if(nian==10000)nian=0;if(!keynum1){ write_addate1(1,nian);//当调闹钟模式按下时不显示当前时间write_com(0x85);write_date('-');}}}。
关于52单片机驱动74HC595控制LCD1602的程序
关于52单片机驱动74HC595控制LCD1602的程序谁能帮忙写个52单片机驱动74hc595控制LCD1602的程序#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#define LcdBus P0sbit LED1602_RS=P2^6; //LCD端口定义sbit LED1602_RW=P2^5 ;sbit LED1602_EN=P2^4 ;void LcdIni(void);void WrOp(uchar dat);void WrDat(uchar dat);void ChkBusy(void);void print_LCD(uchar disp[],uchar num);//延时n ms子程序void delayms(unsigned int n){unsigned int i,j;for(i=0;i<n;i++)for(j=0;j<120;j++);}main(){uchar disp1[16]={'S','u','n','J','i','e',' ','m','a','d','e',' ','a','t',' ',' '};uchar disp2[16]={'2','0','0','8',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};while(1){LcdIni();WrOp(0x80); //数据指针地址第一行print_LCD(disp1,16);WrOp(0xc0); //第二行print_LCD(disp2,4);delayms(3000);WrOp(0x01);}}/**************************************************************************************** **名称:led1602显示程序模块功能:驱动1602 包括数据口P1 三个控制口编译:keil作者:孙杰时间:2008-8-9**************************************************************************************** ***/void print_LCD(uchar disp[],uchar num) //显示数组disp 显示长度为num {uchar i;for(i=0;i<num;i++){WrDat(disp[i]);delayms(300);}}void LcdIni(){WrOp(0x38);WrOp(0x06); //光标加1WrOp(0x0f); //开显示光标闪烁// WrOp(0x0c); //开显示光标不闪烁}void WrOp(uchar dat){//uchar i;ChkBusy();LED1602_RS=0; //RS=0LED1602_RW=0; //RW=0LED1602_EN=0; //EN=0LcdBus=dat; //送数据LED1602_EN=1; //EN=1delayms(10); //延时LED1602_EN=0; //EN=0}void WrDat(uchar dat){//uchar i;ChkBusy();LED1602_RS=1; //rs=1LED1602_RW=0; //rw=0LED1602_EN=0; //en=0LcdBus=dat; //送数据LED1602_EN=1; //en=1delayms(10);; //延时LED1602_EN=0; //en=0}void ChkBusy(){LED1602_RS=0; //RS=0LED1602_RW=1; //RW=1LED1602_EN=1; //EN=1while(LcdBus&0x80); //送数据LED1602_EN=0; //en=0}74hc595驱动问题#define uc unsigned char#define ui unsigned int#include<iom128v.h>uc Bmp[]={/*------------------------------------------------------------------------------ ; 源文件/ 文字:; 宽×高(像素): 64×8; 字模格式/大小: 单色点阵液晶字模,横向取模,字节正序/64字节; 数据转换日期: 2009-4-7 11:11:41------------------------------------------------------------------------------*/0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40, 0x40,0x40,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x10, 0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x04,0x04,0x04,0x04,0x04,0x04, 0x04,0x04,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01};uc B1[8]={0};uc B2[8]={0};void delay(ui n) //延时函数{ui j;ui i;for(i=0;i<n;i++)for(j=0;j<20;j++);}void H_B1(uc h) //十六进制转换为二进制,转换后放在数组B1中{B1[7]=h&0x01;B1[6]=h&0x02;B1[5]=h&0x04;B1[4]=h&0x08;B1[3]=h&0x10;B1[2]=h&0x20;B1[1]=h&0x40;B1[0]=h&0x80;}void H_B2(uc h) //十六进制转换为二进制,转换后放在数组B2中{B2[0]=h&0x01;B2[1]=h&0x02;B2[2]=h&0x04;B2[3]=h&0x08;B2[4]=h&0x10;B2[5]=h&0x20;B2[6]=h&0x40;B2[7]=h&0x80;}void print(void) //扫描函数{uc byte=0;uc j=0;uc row=7; //扫第一行uc column;uc bit=0;uc h=0;PORTD=row; //行数赋给PDH_B1(Bmp[0]);while(1){for(row=7;row!=0xff;row--){PORTD=row; //行数赋给PDPORTF=0X00; //给一个扫描点PORTC=0xff;PORTC=0x00;PORTF=0XFF;for(byte=0;byte<8;byte++){H_B1(Bmp[byte+j]);for(bit=0;bit<8;bit++){//delay(2000);PORTC=0xff; //时钟上升沿//delay(1000);if(B1[bit]==0) PORTE=0Xff;//如果该点不应亮则74_138输出高阻else {PORTE=0X00; delay(40);}//否则输出低电平PORTF=0XFF; //扫描点后面通通熄灭//delay(2000);PORTC=0x00; //时钟下降沿}PORTG=0Xff;//delay(2000);PORTG=0X00;//bit=0;}j+=8;byte=0;}j=0;}}void main(void){DDRC=0XFF; //PC口为时钟输出DDRD=0XFF; //PD为行选,连74_138的ABC输入端DDRF=0XFF; //PF为列选,扫描点,接74_595的DS端DDRE|=0X80; //PE7为输出,74_138使能控制,低电平有效DDRG =0Xff;PORTG=0X00;PORTE=0XFF; delay(5000); PORTE=0X00; //开机信号//PORTE=0X00;print();}这是我刚写的一个64*8的点阵扫描程序用74HC595做行选,但是没用锁存,可以显示,但亮度很低。
用51单片机和1602液晶做的数字钟
课程设计报告数字钟姓名:学号:班级:指导教师:高雪飞目录一、设计题目和要求 (1)二、设计原理与实现功能 (1)三、元器件介绍………………………………………………四、电路设计…………………………………………………五、软件设计…………………………………………………六、设计总结…………………………………………………一、设计题目和要求题目:用STC89C52单片机和1602液晶做的数字时钟要求:1.准确计时,以数字形式显示时、分、秒的时间;2.小时的计时要求为“24翻1”,分和秒的计时为60进制。
二、设计原理与实现功能设计原理:控制芯片采用STC89C52RC单片机,晶振频率为11.0592MHZ,采用C语言编程,显示模块采用通用型1602液晶,发声模块采用无源蜂鸣器。
参考资料:51单片机C语言编程,1602datasheet,网络。
本装置使用的1602液晶为5v电压驱动,带背光,可显示两行,每行16个字符,不能显示汉字,内置含128个字符的ASCII字符集字库,只有并行接口,无串行接口,关于1602液晶的接口信号说明,主要技术参数,基本操作时序,RAM地址映射图,数据指针设置,初始化设置,写操作时序和其他设置请查阅1602的相关资料。
计时部分采用T0计时器中断方式1,TO定时器既有定时功能又有计数功能,通过设置与它们相关的特殊功能寄存器可以选择启用定时功能或计数功能。
当定时器的计数器计满后,会产生中断,通知CPU该如何处理。
关于51单片机的寄存器和中断功能及操作说明请查阅相关资料。
蜂鸣器的发声为单片机的一个引脚加一个三极管控制。
(1.要画出结构框图;2.数字钟的实现方法不止一种,因此必须说明自己所设计的数字钟采用何种方法、何种原理)实现功能:开启装置,则在1602液晶上有左向右划过“hello world I love programing”文字,之后上下两行显示年月日,星期和时间,其中年月日星期只能通过程序更改,时分秒自动从0开始计时,按秒更新,时分秒可用装置的两个按键进行调节,分别为时间设置键,数值增大键,闹钟的时间设置只能通过程序进行更改,一旦液晶显示时间和程序设定时间完全一致,蜂鸣器发声。
1602电子时钟程序
#include<reg52.h> //52单片机头文件#define uchar unsigned char //宏定义#define uint unsigned intsbit rs=P1^0; //声明单片机P1口的第一位读写指令还是数据端sbit rw=P1^1; //声明单片机P1口的第二位读写数据端sbit lcden=P1^2; //声明单片机P1口的第三位液晶使能端sbit s1=P2^5; //声明单片机P2口的第六位按键控制端sbit s2=P2^6; //声明单片机P2口的第七位按键控制端sbit s3=P2^7; //声明单片机P2口的第八位按键控制端sbit s4=P2^0; //声明单片机P2口的第一位按键控制端sbit s5=P2^4; //声明单片机P2口的第五位按键控制端sbit a=P3^5; //声明单片机P3口的第六位按键控制端char count,shi,fen,miao,s1num,xp,s5num,date1; //定义有符号字符形变量char nian,tian,yue,nshi,nfen; //定义有符号字符形变量uchar code table[]=" 2000-01-01 Mon "; //定义日期时间数组uchar code table1[]=" 00:00:00";uchar code table2[]=" Alarm clock"; //定义日期时间数组uchar code table3[]=" 00:00";void delay(uint z){uint x,y;for(x=z;x>0;x--) //延时子函数for(y=110;y>0;y--);}void write_com(uchar com) //指令子函数{rs=0; //选择写指令lcden=0; //使能端初始为底P0=com; //将送到要写的指令数据线上delay(5); //延时待数据稳定lcden=1; //使能端给一个高脉冲把数据写入1602液晶delay(5); //延时lcden=0; //拉低使能端完成高脉冲}void write_date(uchar date) //数据子函数{rs=1; //选择写数据lcden=0;P0=date;delay(5);lcden=1;delay(5);lcden=0;}void init() //初始子函数{uchar num; //定义变量用来调用数组rw=0; //选择只写数据到液晶lcden=0; //初始使能端为低电平write_com(0x38); //设置16*2显示,5*7点阵,8位数据接口write_com(0x0c); //开显示,不显示光标write_com(0x06); //写一个字符指针自动加1write_com(0x01); //显示清零,数据指针清零write_com(0x80); //将数据指针定位到第一行第一个字处for(num=0;num<15;num++){write_date(table[num]); //写日期数组数据delay(20);}write_com(0x80+0x40); //选择将时间写到液晶第二行for(num=0;num<12;num++){write_date(table1[num]); //写时间数组数据delay(20);}write_com(0x80+16); //使用移屏操作for(num=0;num<13;num++){write_date(table2[num]); //写闹钟名称delay(20);}write_com(0x80+0x40+16); //选择移屏第二行for(num=0;num<10;num++){write_date(table3[num]); //写闹钟初始值delay(20);}TMOD=0x01; //选择定时器工作方式为方式1TH0=(65536-50000)/256; //装初值TL0=(65536-50000)%256;EA=1; //开总中断ET0=1; //选择定时器零TR0=1; //开定时器零}void write_sfm(uchar add,uchar date ) //子函数写时间日期到液晶上{uchar shi,ge; //定义变量用以分离十位和个位上的数字shi=date/10; //分离十位上的数字ge=date%10; // 分离个位上的数字write_com(0x80+0x40+add) ; //给出写的位置指令write_date(0x30+shi); //写十位上的数字write_date(0x30+ge); //写个位上的数字}void write_sfn(uchar add,uchar date) //子函数写时间日期到液晶上{uchar shi,ge; //定义变量用以分离十位和个位上的数字shi=date/10; //分离十位上的数字ge=date%10; // 分离个位上的数字write_com(0x80+add) ; //给出写的位置指令write_date(0x30+shi); //写十位上的数字write_date(0x30+ge); //写个位上的数字}void keyscan() //按键子函数{{s4=0; //让共同接口置零if(s1==0) //判断s1是否被按下{delay(5); //延时5ms去斗if(s1==0) //再次判断s1是否真被按下{s1num++; //设置变量判断s1被按下几次while(!s1); //松手检测if(s1num==1) //S1被第一次按下{TR0=0; //关定时器write_com(0x80+0x40+11); //确定指针位置在秒钟write_com(0x0f); //开显示显示光标光标闪烁}}if(s1num==2){write_com(0x80+0x40+8); //确定指针位置在分钟}if(s1num==3){write_com(0x80+0x40+5); //确定指针位置在时针}if(s1num==4){write_com(0x80+4); //确定指针位置在时针}if(s1num==5){write_com(0x80+7); //确定指针位置在时针}if(s1num==6){write_com(0x80+10); //确定指针位置在时针}if(s1num==7){write_com(0x80+14); //确定指针位置在时针}if(s1num==8){uchar num ;write_com(0x18) ;write_com(0x18) ;write_com(0x18) ;write_com(0x18) ;write_com(0x18) ;write_com(0x18) ;write_com(0x18) ; //移屏操作write_com(0x18) ;write_com(0x18) ;write_com(0x18) ; //整屏左移同时光标也跟着移动write_com(0x18) ;write_com(0x18) ;write_com(0x18) ;write_com(0x18) ;write_com(0x18) ;write_com(0x18) ;write_com(0x80+0x40+22); //确定指针位置在时针}if(s1num==9){write_com(0x80+0x40+25); //确定指针位置在时针}if(s1num==10){uchar n;while(n<24){n++; //移屏操作write_com(0x18);}s1num=0;n=0;write_com(0x0c); //结束光标显示表开始走TR0=1;}}}if(s1num!=0) //说明已S1被按下{if(s2==0) //判断S2是否被按下{delay(5); //判断S2是否真被按下if(s2==0); //判断S2是否真被按下{while(!s2); //松手检测if(s1num==1) //判断S1被按下一下{miao++; //秒自加一if(miao==60) //判断miao是否为60miao=0; //秒清零write_sfm(10,miao) ; //把秒数据写到指定位置write_com(0x80+0x40+11); //不让指针向后移}if(s1num==2) //判断S1被按下两下{fen++; //分自加一if(fen==60) //判断fen是否为60fen=0; //fen清零write_sfm(7,fen) ; //把fen数据写到指定位置write_com(0x80+0x40+8); //不让指针向后移}if(s1num==3) //判断S1被按下三下{shi++; //shi自加一if(shi==24) //判断shi是否为24shi=0; //shi清零write_sfm(4,shi) ; //把shi数据写到指定位置write_com(0x80+0x40+5); //不让指针向后移}if(s1num==4) //判断S1被按下四下{nian++; //nian自加一write_sfn(3,nian) ; //把年数据写到指定位置write_com(0x80+4); //不让指针向后移}if(s1num==5) //判断S1被按下五下{yue++; //yue自加一if(yue==13) //使月循环加yue=1;write_sfn(6,yue) ; //把月数据写到指定位置write_com(0x80+7); //不让指针向后移}if(s1num==6) //判断S1被按下六下{tian++; //tian自加一if(yue==1,3,5,7,8,10,12){if(tian==32)tian=1;}if(yue==2){if(tian==29)tian=1;}if(yue==4){if(tian==31) //解决不同的月有不同的天的问题tian=1;}if(yue==6){if(tian==31)tian=1;}if(yue==9){if(tian==31)tian=1;}if(yue==11){if(tian==31)tian=1;}write_sfn(9,tian) ; //把天数据写到指定位置write_com(0x80+10); //不让指针向后移}if(s1num==8) //判断S1被按下八下{nshi++; //闹钟的时自加一if(nshi==24)nshi=0;write_sfm(21,nshi) ;write_com(0x80+0x40+22);}if(s1num==9) //判断S1被按下九下{nfen++; //闹钟的分自加一if(nfen==60) //判断nfen是否为60nfen=0; //nfen清零write_sfm(24,nfen) ; //把nfen数据写到指定位置write_com(0x80+0x40+25); //不让指针向后移}}}if(s1num==7) //判断S1被按下七下{if(s5==0){delay(5);if(s5==0){s5num++;while(!s5);if(s5num==1){write_com(0x80+12);write_date(0x4D);write_com(0x80+13);write_date(0x6F); //写星期一write_com(0x80+14);write_date(0x6E);write_com(0x80+14);}if(s5num==2){write_com(0x80+12);write_date(0x54);write_com(0x80+13); //写星期二write_date(0x75);write_com(0x80+14);write_date(0x65);write_com(0x80+14);}if(s5num==3){write_com(0x80+12);write_date(0x57);write_com(0x80+13);write_date(0x65); //写星期三write_com(0x80+14);write_date(0x64);write_com(0x80+14);}if(s5num==4){write_com(0x80+12);write_date(0x54);write_com(0x80+13);write_date(0x68); //写星期四write_com(0x80+14);write_date(0x75);write_com(0x80+14);}if(s5num==5){write_com(0x80+12);write_date(0x46);write_com(0x80+13);write_date(0x72); //写星期五write_com(0x80+14);write_date(0x69);write_com(0x80+14);}if(s5num==6){write_com(0x80+12);write_date(0x53);write_com(0x80+13);write_date(0x61); //写星期六write_com(0x80+14);write_date(0x74);write_com(0x80+14);}if(s5num==7){write_com(0x80+12);write_date(0x53);write_com(0x80+13);write_date(0x75); //写星期日write_com(0x80+14);write_date(0x6E);write_com(0x80+14);}if(s5num==7){s5num=0;}}}}if(s3==0) //判断S3是否被按下{delay(5); //判断S3是否真被按下if(s3==0) //判断S3是否真被按下{while(!s3); //松手检测if(s1num==1) //判断S1被按下一下{miao--; //秒自减一if(miao==-1) //当秒等于-1时miao=59; //把秒赋值为59write_sfm(10,miao); //把秒数据写到指定位置write_com(0x80+0x40+11); //不让指针向后移}if(s1num==2) //判断S1被按下两下{fen--; //分自减一if(fen==-1) //当分等于-1时fen=59; //把分赋值为59write_sfm(7,fen); //把分数据写到指定位置write_com(0x80+0x40+8); //不让指针向后移}if(s1num==3) //判断S1被按下三下{shi--; //时自减一if(shi==-1) //当时等于-1时shi=23; //把时赋值为59write_sfm(4,shi); //把时数据写到指定位置write_com(0x80+0x40+5); //不让指针向后移}if(s1num==4) //判断S1被按下四下{nian--; //年自减一if(nian==-1){nian=0; //不让年少于2000}write_sfn(3,nian); //把时数据写到指定位置write_com(0x80+4); //不让指针向后移}if(s1num==5) //判断S1被按下五下{yue--; //月自减一if(yue==-1) //当月等于-1时yue=12; //把月赋值为12if(yue==0)yue=12; //解决月第一次减不正确的问题write_sfn(6,yue); //把时数据写到指定位置write_com(0x80+7); //不让指针向后移}if(s1num==6) //判断S1被按下六下{tian--; //天自减一if(yue==2){if(tian==-1)tian=28;if(tian==0)tian=28;}if(yue==4){if(tian==-1)tian=30;if(tian==0) // 解决不同的月有不同的天的问题tian=30;}if(yue==6){if(tian==-1)tian=30;if(tian==0)tian=30;}if(yue==9){if(tian==-1)tian=30;if(tian==0)tian=30;}if(yue==11){if(tian==-1)tian=30;if(tian==0)tian=30;}if(yue==1,3,5,7,8,10,12){if(tian==-1)tian=31;if(tian==0)tian=31;}write_sfn(9,tian); //把时数据写到指定位置write_com(0x80+10); //不让指针向后移}if(s1num==8) //判断S1被按下八下{nshi--; //闹钟的时自减一if(nshi==-1)nshi=23;write_sfm(21,nshi) ; //把nshi数据写到指定位置write_com(0x80+0x40+22); //不让指针向后移}if(s1num==9) //判断S1被按下九下{nfen--; //闹钟的分自加一if(nfen==-1) //判断nfen是否为-1nfen=59; //nfen为59write_sfm(24,nfen) ; //把nfen数据写到指定位置write_com(0x80+0x40+25); //不让指针向后移}}}}}void main() //主函数{init(); //初始化函数while(1){keyscan(); //控制按键}}void timer0() interrupt 1 //中断子函数{TH0=(65536-50000)/256; //重装初值TL0=(65536-50000)%256;count++; //用以计时的变量if(count==20) //判断中断时间是否为一秒{count=0; //为一秒count清零重新计时miao++; //秒加一if(miao==60) //判断miao是否为60{miao=0; //为60miao清零fen++; //fen加一if(fen==60) //判断fen是否为60{fen=0; //为60fen清零shi++; //时加一if(shi==24) //判断shi是否为24{shi=0; //为24shi清零tian++; //天自加一s5num++;if(s5num==1){write_com(0x80+12);write_date(0x4D);write_com(0x80+13);write_date(0x6F); //写星期一write_com(0x80+14);write_date(0x6E);write_com(0x80+14);}if(s5num==2){write_com(0x80+12);write_date(0x54);write_com(0x80+13);write_date(0x75); //写星期二write_com(0x80+14);write_date(0x65);write_com(0x80+14);}if(s5num==3){write_com(0x80+12);write_com(0x80+13);write_date(0x65); //写星期三write_com(0x80+14);write_date(0x64);write_com(0x80+14);}if(s5num==4){write_com(0x80+12);write_date(0x54);write_com(0x80+13);write_date(0x68); //写星期四write_com(0x80+14);write_date(0x75);write_com(0x80+14);}if(s5num==5){write_com(0x80+12);write_date(0x46);write_com(0x80+13);write_date(0x72); //写星期五write_com(0x80+14);write_date(0x69);write_com(0x80+14);}if(s5num==6){write_com(0x80+12);write_date(0x53);write_com(0x80+13);write_date(0x61); //写星期六write_com(0x80+14);write_date(0x74);write_com(0x80+14);}if(s5num==7){write_com(0x80+12);write_com(0x80+13);write_date(0x75); //写星期日write_com(0x80+14);write_date(0x6E);write_com(0x80+14);}if(s5num==7){s5num=1;}if(yue==1,3,5,7,8,10,12){if(tian==32)tian=1;}if(yue==4){if(tian==31) //解决天循环问题tian=1;}if(yue==6){if(tian==31)tian=1;}if(yue==9){if(tian==31)tian=1;}if(yue==11){if(tian==31)tian=1;}if(yue==2){if(tian==29)tian=1;}write_sfn(9,tian); //写天到指定位置if(tian==1){yue++;if(yue==13) //月循环{yue=1;}if(yue==1)nian++;write_sfn(3,nian); //写年到指定位置}write_sfn(6,yue); //写月到指定位置}write_sfm(4,shi); //写小时到指定位置}write_sfm(7,fen); //写分钟到指定位置if(shi==nshi&&fen==nfen){uchar n,s;while(n<60){n++;if(s5==0){ //控制闹钟delay(5);if(s5==0){while(!s5);s++;}}if(s!=1){s=0;a=0; delay(50);a=1; delay(50);a=0; delay(50);a=1; delay(50);a=0; delay(50);a=1; delay(50);a=0; delay(50);a=1; delay(50); //蜂鸣器的响与断a=0; delay(50);a=1; delay(50);a=0; delay(50);a=1; delay(50);a=0; delay(50);a=1; delay(50);a=0; delay(50);a=1; delay(50);a=0; delay(50);a=1; delay(50);a=0; delay(50);a=1; delay(50);}}if(n==60){fen++;if(fen==60){fen=0; shi++;} write_sfm(4,shi); //闹钟响一分钟分自加一}write_sfm(7,fen); //写分钟到指定位置n=0;s=0;}}}write_sfm(10,miao); //写秒钟到指定位置}。
51单片机控制基于1602液晶显示 电子时钟【带闹铃和整点报时】
write_date(week6[num]);
delay1();
}
};
break;
}
}
void display() //显示时间子程序
{
write_week(week);
write_ymd(3,year);
write_ymd(6,months);
write_ymd(9,day);
write_sfm(0,shi);
write_sfm(3,fen);
write_sfm(6,miao);
}
void display_1() //显示闹钟子程序
{
write_week(week_1);
write_ymd(3,year1);
write_ymd(6,months1);
write_ymd(9,day1);
write_sfm(0,shi1);
write_com(0x80+add);
write_date(0x30+sh);
write_date(0x30+ge);
}
void write_week(uchar add) //周几显示
{
switch(add)
{
case 0:{
write_com(0x80+12);//设置数据起始地址
for(num=0;num<3;num++)
{
write_date(week3[num]);
delay1();
}
};
break;
case 4:{
write_com(0x80+12);//设置数据起始地址
for(num=0;num<3;num++)
用51单片机和1602液晶做的数字钟
用51单片机和1602液晶做的数字钟数字钟是人们日常生活中常见的时间显示设备,它能够精确显示当前的时间,并且兼具简约和实用性。
本文将介绍使用51单片机和1602液晶屏幕制作自己的数字钟的方法。
所需材料在开始制作之前,我们需要准备以下材料: - 51单片机开发板 - 1602液晶屏幕 - 数字时钟芯片RTC(Real-Time Clock) - 面包板和导线 - 电阻和电容 - 编程器和烧录器硬件连接首先,我们需要将51单片机、1602液晶屏幕和RTC芯片连接起来。
根据硬件接口的定义和引脚功能的规定,我们可以进行以下连接: - 将51单片机的VCC 引脚连接到1602液晶屏幕的VCC引脚,用于提供电源。
- 将51单片机的GND引脚连接到1602液晶屏幕的GND引脚,用于地线连接。
- 将51单片机的P0口连接到1602液晶屏幕的数据线D0-D7,用于数据传输。
- 将51单片机的P2口连接到1602液晶屏幕的RS引脚,用于选择数据和命令传输。
- 将51单片机的P3口连接到1602液晶屏幕的EN引脚,用于启用LCD。
此外,还需要将RTC芯片连接到51单片机上,以实现时间的准确显示。
具体的连接方式可以参考RTC芯片的规格说明书。
软件编程完成硬件连接后,我们需要进行软件编程,以便控制51单片机、1602液晶屏幕和RTC芯片的功能。
初始化首先,我们需要对51单片机和1602液晶屏幕进行初始化设置。
这包括设置引脚的功能模式、初始化1602液晶屏幕的显示模式和清空显示区域。
读取时间接下来,我们需要通过RTC芯片来读取当前的时间。
这通常包括读取RTC芯片存储的年、月、日、时、分和秒的数据。
显示时间读取时间后,我们可以将其显示在1602液晶屏幕上。
这可以通过更新特定的LCD显示区域来实现。
我们可以在指定的位置、特定的行和列上显示时间。
更新时间为了实现实时的时间显示,我们需要定期更新显示的时间。
可以使用定时器中断来定期更新时间,并根据需要刷新液晶屏幕上的显示。
1602液晶显示电子钟时间C程序
#include<reg51.h>#define uchar unsigned char#define uint unsigned intsbit RS=P2^0;sbit RW=P2^1;sbit E=P2^2;sbit key1=P2^3;sbit key2=P2^4;sbit key3=P2^5;void delay(void);void init(void);void wc51r(uchar i);void wc51ddr(uchar i);void fbusy(void);void LCD_xianshi(void);void delay_zs(uint z);void tiaoshi(void);uchar hour,hour1,min,min1,sec,sec1,aa,bb,num1,num2,num3,flag;uchar year1,year2,year3,year4,month,month1,month2,day,day1,day2; unsigned int year;uchar tab[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};void main(){init();while(1){LCD_xianshi();}}void init(){// key1=1;key2=1;key3=1;num1=12;year=2010;month=11;day=15;// wc51r(0x01);wc51r(0x38);wc51r(0x0c);wc51r(0x06);TMOD=0x01; //工作方式1TH0=(65536-5000)/256; //定时器高位装初值计数溢出一次为50ms TL0=(65536-5000)%256; //定时器低位装初值EA=1; //CPU开中断ET0=1; //允许T0中断// ET1=1;TR0=1; //启动T0工作// TR1=1;}void fbusy(){RW=1;RS=0;E=1;while(!P1&0x80);E=0;delay();}void wc51r(uchar j){fbusy();E=0;RS=0;RW=0;E=1;P1=j;E=0;delay();}void wc51ddr(uchar j){fbusy();E=0;RS=1;RW=0;E=1;P1=j;E=0;delay();}void delay(){uchar i,j;for(j=0;j<10;j++)for(i=0;i<10;i++);}/*void delay_zs(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}*/void LCD_xianshi(){year1=year/1000;year2=year/100%10;year3=year%100/10;year4=year%10;month1=month/10;month2=month%10;day1=day/10;day2=day%10;hour=num1/10;hour1=num1%10;min=num2/10;min1=num2%10;sec=num3/10;sec1=num3%10;wc51r(0x84); //起始地址为第1行第1列,0x85为第1行第6列;0xc0为第2行第1列wc51ddr(tab[hour]); //显示1wc51ddr(tab[hour1]); //显示2wc51ddr(0x3a); //显示:wc51ddr(tab[min]); //显示0wc51ddr(tab[min1]); //显示0wc51ddr(0x3a); //显示:wc51ddr(tab[sec]);wc51ddr(tab[sec1]);wc51r(0xc3);wc51ddr(tab[year1]);wc51ddr(tab[year2]);wc51ddr(tab[year3]);wc51ddr(tab[year4]);wc51ddr('-');wc51ddr(tab[month1]);wc51ddr(tab[month2]);wc51ddr('-');wc51ddr(tab[day1]);wc51ddr(tab[day2]);}/*void tiaoshi(void){while(key1){TR0=0;if(key2==0){LCD_xianshi;num3++;if(num3==60){num3=0;num2++;}}else if(key3==0)num2++;}// while(key1);// if(key1==0){ET0=1;TR0=1;flag=0;}}*///************************定时器中断程序**************************// void timer0() interrupt 1{TH0=(65536-50000)/256; //重装计数初值TL0=(65536-50000)%256;aa++;if(aa==20) //计数20次后恰为20x50ms==1s{aa=0;num3++; //秒加1if(num3==60) //秒计数到60后清零{num3=0;num2++;if(num2==60){num2=0;num1++;if(num1==24){num1=0;day++;if(month%2==0){if(day==31){day=0;month++;if(month==13){month=0;year++;}}}else if(month%2==1){if(day==32){day=0;month++;if(month==13){month=0;year++;}}}}}}}}//************************定时器中断程序**************************// /*void timer1() interrupt 3{TH1=(65536-50000)/256; //重装计数初值TL1=(65536-50000)%256;bb++;if(bb%20==0){if(key1==0){ET0=0;TR0=0;flag=1;}}}*/#include <msp430g2452.h>unsigned char table[] ={"0123456789"};unsigned char hanzi1[8]={0x04,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02};//年 unsigned char hanzi2[8]={0x0f,0x09,0x0f,0x09,0x0f,0x09,0x13,0x11};//月 unsigned char hanzi3[8]={0x1f,0x11,0x11,0x1f,0x11,0x11,0x1f,0x00};//日unsigned char num;void delay_1ms(void){unsigned int i;for (i=0;i<1140;i++);}void delay_nms(unsigned int n){unsigned int i=0;for (i=0;i<n;i++)delay_1ms();}void write_com(unsigned int com){//lcdrs = 0;P2OUT&= 0xfd; P1OUT = com; delay_nms(5); //lcden = 1;P2OUT|= 0x01; delay_nms(5); P2OUT&= 0xfe; }void write_dat(unsigned int dat) {//lcdrs = 1;P2OUT |= 0x02; P1OUT = dat; delay_nms(5); //lcden=1;P2OUT|= 0x01; delay_nms(5); // lcden=0;P2OUT&= 0xfe; }void init() {write_com(0x38);// write_com(0x0f);// write_com(0x01);// write_com(0x06);// // write_com(0x07);//整屏移动 delay_nms(10); }void CGRAM_LCD(unsigned char *hz,unsigned char temp) {unsigned char s; for(s=0;s<8;s++) {write_com(temp+s);write_dat(*(hz+s)); } }void main(void) {WDTCTL = WDTPW + WDTHOLD; // Stop WDT P1DIR |= 0xff; // P1.2 output P2DIR |= 0xff; init();CGRAM_LCD(hanzi1,0x40); CGRAM_LCD(hanzi2,0x48); CGRAM_LCD(ha nzi3,0x50);write_com(0x80); write_dat(table[2]); delay_nms(100);write_com(0x80+0x01); write_dat(table[0]); delay_nms(100);write_com(0x80+0x02); write_dat(table[1]); delay_nms(100);write_com(0x80+0x03); write_dat(table[2]);delay_nms(100);write_com(0x80+0x04); write_dat(0); delay_nms(100);write_com(0x80+0x06); write_dat(table[6]); delay_nms(100);write_com(0x80+0x07); write_dat(1); delay_nms(100);write_com(0x80+0x09); write_dat(table[2]); delay_nms(100);write_com(0x80+0x0a); write_dat(2); while(1); }。
基于51单片机定时器的1602液晶显示器时钟显示(带年月日)
基于51单片机定时器的1602液晶显示器时钟显示(带年月日)#include#define uchar unsigned char#define uint unsigned intuchar a,count,S1num,xqnum;char yue,ri,shi,fen,miao;int nian;sbit lcdrs=P2^5;sbit lcdrw=P2^4;sbit lcden=P2^3;sbit S1=P3^0; //定义键——进入设置sbit S2=P3^1; //定义键——增大sbit S3=P3^2; //定义键——减小sbit S4=P3^3; //定义键——退出设置uchar code table0[]="2014-08-13 WED";uchar code table1[]="00:00:00";uchar code xingqi[][3]={"MON","TUE","WED","THU","FRI","SAT","SUN"};void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}/**************************************************1602液晶显示器模块sbit lcdrs=P2^5;sbit lcdrw=P2^4;sbit lcden=P2^3;*************************************************/ void write_com(uchar com) //液晶写指令{lcdrw=0;lcdrs=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;}void write_data(uchar dat) //液晶写数据{lcdrw=0;lcdrs=1;P0=dat;delay(5);lcden=1;delay(5);lcden=0;}/********************************************年月日写入1602函数********************************************/void write_sfm(uchar add,uchar dat) //写时分秒函数{ uchar shi,ge;shi=dat/10;ge=dat%10;write_com(0x80+0x40+add);write_data(0x30+shi);write_data(0x30+ge);}void write_yr(uchar add,uchar dat) //写月日函数{uchar shi,ge;shi=dat/10;ge=dat%10;write_com(0x80+add);write_data(0x30+shi);write_data(0x30+ge);}void write_nian(uchar add,uint dat) //写年函数{ uint qian,bai,shi,ge;qian=dat/1000;bai=dat%1000/100;shi=dat%100/10;ge=dat%10;write_com(0x80+add);write_data(0x30+qian);write_data(0x30+bai);write_data(0x30+shi);write_data(0x30+ge);/*************************************************** 初始化***************************************************/ void init_lcd() //液晶初始化{lcden=0;nian=2014;yue=8;ri=13;shi=0; //初始shi、fen、miaofen=0;miao=0;write_com(0x38); //设置16x2显示,5x7点阵,8位数据口write_com(0x0c); //设置开显示,不显示光标write_com(0x06); //写一个字符后地址指针加1write_com(0x01); //显示清0,数据指针清0}void init() //初始化函数{init_lcd(); //液晶初始化write_com(0x80); //设置显示初始坐标for(a=0;a<14;a++) //显示年月日初始值{write_data(table0[a]);delay(5);}write_com(0x80+0x40); //设置显示初始坐标for(a=0;a<8;a++) //显示时分秒初始值{write_data(table1[a]);delay(5);}write_nian(0,nian);write_sfm(6,miao); //分别将shi、fen、miao送去液晶显示write_sfm(3,fen);write_sfm(0,shi);count=0;xqnum=0;S1num=0; //初始化全局变量countTMOD=0x01; //设置定时器0工作模式 1 TH0=(65535-50000)/256; //定时器装初始值TL0=(65535-50000)%256;EA=1; //开总中断ET0=1; //开定时器0中断TR0=1; //启动定时器0}/**************************************************独立键盘sbit S1=P3^0; //定义键——进入设置sbit S2=P3^1; //定义键——增大sbit S3=P3^2; //定义键——减小sbit S4=P3^3; //定义键——退出设置独立键盘已接地*************************************************/void keyscan(){if(S1==0){delay(5); //确认定义键被按下if(S1==0){S1num++; //定义键S1按下次数记录while(!S1); //释放按键确认if(S1num==1) //S1按下一次时{TR0=0; //关闭定时器write_com(0xc0+7); //光标定位到秒位置write_com(0x0f); //光标闪烁}if(S1num==2) //S1按下两次时{write_com(0xc0+4); //光标定位到分位置}if(S1num==3) //S1按下三次时{write_com(0xc0+1); //光标定位到时位置}if(S1num==4) //S1按下四次时{write_com(0x80+13); //光标定位到星期位置}if(S1num==5) //S1按下五次时{write_com(0x80+9); //光标定位到日位置}if(S1num==6) //S1按下六次时{write_com(0x80+6); //光标定位到月位置}if(S1num==7) //S1按下七次时{write_com(0x80+3); //光标定位到年位置}if(S1num==8) //S1按下八次时{S1num=0; //S1记录按键次数清零TR0=1; //开启定时器write_com(0x0c); //取消光标闪烁}}}if(S1num!=0) //只有定义键按下后S2、S3、S4才有效{ if(S2==0){delay(5); //防抖if(S2==0) //确认按键被按下{while(!S2); //释放按键确认if(S1num==1) //S1按下一次时{miao++; //调整秒加1if(miao==60) //满60清零miao=0;write_sfm(6,miao); //每调节一次送液晶显示一次write_com(0x80+0x40+6); //显示位置重新回到调节处} if(S1num==2) //S1按下两次时{fen++; //调整分加1if(fen==60)fen=0;write_sfm(3,fen);write_com(0x80+0x40+3);}if(S1num==3) //S1按下三次时{shi++; //调整时加1if(shi==24)write_com(0x80+0x40); write_sfm(0,shi);}if(S1num==4) //星期加调整{ xqnum++;if(xqnum==7)xqnum=0;write_com(0x80+0x0b);for(a=0;a<3;a++){write_data(xingqi[xqnum][a]); delay(5);}}if(S1num==5) //日加调整{ri++;if(yue==2){if(nian%400==0){if(ri==30){ri=1;}}if(nian%400!=0){if(ri==29){}}}else if(yue<=7){if(yue%2==0&yue!=2) {if(ri==31){ri=1;}}else if(yue%2!=0&yue!=2) {if(ri==32){ri=1;}}}else if(yue>=8){if(yue%2==0){if(ri==32){ri=1;}}else if(yue%2!=0){if(ri==31){ri=1;}}}write_yr(8,ri);}if(S1num==6) //月加调整{ yue++;if(yue==13)yue=1;write_yr(5,yue);}if(S1num==7) //年加调整{ nian++;if(nian==2019)nian=2014;write_nian(0,nian);}}}if(S3==0){delay(5);if(S3==0) //确认按键被按下{while(!S3);if(S1num==1){miao--; //调整秒减1if(miao==-1) //减到00后再减重新设置为59 miao=59;write_sfm(6,miao);write_com(0x80+0x40+6);}if(S1num==2){fen--; //调整分减1if(fen==-1)fen=59;write_sfm(3,fen);write_com(0x80+0x40+3);}if(S1num==3){shi--; //调整时减1if(shi==-1)shi=23;write_sfm(0,shi);write_com(0x80+0x40);}if(S1num==4){xqnum--; //调整星期减一if(xqnum==-1)xqnum=6;write_com(0x80+0x0b);for(a=0;a<3;a++){write_data(xingqi[xqnum][a]); delay(5);}}if(S1num==5) //调整日{ri--;if(yue==2){if(nian%400==0){if(ri==0){ri=29;}}if(nian%400!=0){if(ri==0){ri=28;}}}else if(yue<=7){if(yue%2==0&yue!=2){if(ri==0)ri=30;}}else if(yue%2!=0&yue!=2) {if(ri==0){ri=31;}}}else if(yue>=8){if(yue%2==0){if(ri==0){ri=31;}}else if(yue%2!=0){if(ri==0){ri=30;}}}write_yr(8,ri);if(S1num==6) //调整月{yue--;if(yue==0)yue=12;write_yr(5,yue);}if(S1num==7) //调整年{nian--;if(nian==2013)nian=2018;write_nian(0,nian);}}}if(S4==0) //退出设置、开启中断{delay(5);if(S4==0){S1num=0;TR0=1;write_com(0x0c);}}}}/**************************************************定时器0*************************************************/void timer0() interrupt 1 //定时器0中断服务程序{TH0=(65535-50000)/256; //重装定时器初始值TL0=(65535-50000)%256;count++; //中断次数累加if(count==20) //20次50毫秒即一秒{count=0;miao++;if(miao==60) //秒加到60时分进位{miao=0;fen++;if(fen==60) //分加到60时时进位{fen=0;shi++;if(shi==24) //时加到24时清0{shi=0;xqnum++;ri++;if(yue==2) //如果是二月{if(nian%400==0) //闰年判断{if(ri==30){ri=1;yue++;write_yr(5,yue);}}if(nian%400!=0) //平年判断{if(ri==29){ri=1;yue++;write_yr(5,yue);}}}else if(yue<=7&yue!=2) //一月到七月{if(yue%2==0) //偶数月(除二月){if(ri==31){ri=1;yue++;}}else if(yue%2!=0) //奇数月{if(ri==32){ri=1;yue++;}}write_yr(5,yue);}else if(yue>=8) //八月到12月{if(yue%2==0) //偶数月(除二月){if(ri==32){ri=1;yue++;if(yue==13) //如果判断月份为12月,则加一后重新定义月份为1{yue=1;nian++;write_nian(0,nian);}write_yr(5,yue);}}else if(yue%2!=0) //奇数月{if(ri==31){ri=1;yue++;write_yr(5,yue);}}}write_yr(8,ri);if(xqnum==7) //星期写入xqnum=0;write_com(0x80+0x0b);for(a=0;a<3;a++){write_data(xingqi[xqnum][a]);delay(5);}}write_sfm(0,shi); //重新写入数据}write_sfm(3,fen); //重新写入数据}write_sfm(6,miao); //重新写入数据}}/************************************************* 主函数*************************************************/ void main(){init();while(1){keyscan(); //不停的检测按键是否被按下}}。
51单片机控制基于1602液晶显示 电子时钟【带闹铃和整点报时】
{
switch(be)
{//uint i;
/*用于整点响铃*/case 0:{
buzz=~buzz;
//delay1();
}break;
/*用于闹铃报时*/case 1:{
buzz=~buzz;
//delay(10);
}break;
}
}
void write_com(uchar com)//命令写入函数
{
rs=0;
delay(3);
P0=com;
delay(3);
lcden=1;
delay(3);
lcden=0;
}
void write_date(uchar date)//数据写入函数
{
rs=1;
delay(3);
P0=date;
delay(3);
write_date(0x30+ge);
}
void write_ymd(uchar add,uchar date)//年月日写入子程序
{
uchar sh,ge;
sh=date/10;
ge=date%10;
write_com(0x80+add);
write_date(0x30+sh);
write_date(0x30+ge);
sbit buzz=P1^5; //蜂鸣器控制端
uchar code week0[]="Sun";
uchar code week1[]="Mon";
uchar code week2[]="Tue";
最新基于52单片机控制的1602液晶电子时钟显示程序(精心整理)
基于52单片机控制的1602液晶电子时钟显示程序关于利用52单片机制作1602液晶电子时钟显示的程序,网上也有很多资料,不过个人感觉还是挺乱的。
曾经我也是一名初学者,看过很多别人的资料,查找过很多书籍,一个个程序的摸索,经常被弄得头昏脑涨,深受其苦。
今天,我自己精心的整理了一份“基于52单片机控制的1602液晶电子时钟显示程序”的资料,程序每个点几乎都有注释,适合初学者学习,供有兴趣的朋友参考。
也算作为自己一直以来在网上搜索那么多资料而给大家的一点点回报吧。
这程序简单易懂,也有一些可改善的地方,比如写命令和写数据的函数可以合并等等。
大家可根据自己的爱好进行修改,多动手多尝试,相信你很快就能学会。
值得注意的是,1,此程序是利用52单片机控制,如果你的是51单片机,需要改动一下头文件#include<reg51.h> 的。
2,关于引脚,大家需要根据实际情况定义具体的引脚,不同的学习板,或者你自己焊接的板子,引脚都可能不一样。
3,本程序的日期是固定的,自己可以编写函数进行年月日显示。
由于本作者水平有限,错误疏漏之处在所难免,欢迎读者指正。
#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit lcden=P3^4; //1602使能信号sbit lcdrs=P3^5; //1602命令(0)/数据(1)选择端sbit wr=P3^6; //1602读写选择端,一般为低电平(0)sbit key1=P3^7; //定义功能按键,可根据实际情况改变sbit key2=P2^0; //数字增加按键,也可根据实际情况改变sbit dula=P2^6; //关闭实验板上数码管的段选,这两句可根据实际情况注释掉sbit wela=P2^7; //关闭实验板上数码管的段选uchar temp,num,shi,fen,miao;uchar code tabe[]="2013-07-20"; //固定日期,可扩展为动态void delay(uint z) //延时1ms程序{uint i,j;for(i=z;i>0;i--)for(j=110;j>0;j--);}void write_com(uchar com) //写命令{lcdrs=0; //rs为低电平写命令P0=com;delay(5);lcden=1; //高脉冲使能delay(5);lcden=0;}void write_data(uchar dat) //写数据{lcdrs=1; //rs为高电平写数据P0=dat;delay(5);lcden=1;delay(5);lcden=0;}void init() //初始化{EA=1; //开总中断ET1=1; //开定时器1中断TMOD=0x10; //设置TMOD参数TH1=(65536-50000)/256; //给寄存器装初值TL1=(65536-50000)%256;TR1=1; //开启定时器1num=0;shi=0;fen=0;miao=0;lcden=0;dula=0;wela=0;wr=0; //写,低电平有效write_com(0x38); //设置16*2显示,5*7点阵,8位数据接口write_com(0x0C); //开显示,这里上下四句话需参考厂家提供的1602参数设置write_com(0x06); //写一个字符后地址指针加1,且光标加1,写一个字符时,整屏不动write_com(0x01); //显示清屏,数据指针清0}void d1602(uchar add,uchar date) //给1602发送地址与数据{uchar date2,date1; //拆分个位与十位date2=date/10;date1=date%10;write_com(0x80+0x40+add); //写指令,地址write_data(date2+0x30);delay(5); //写数据,十位write_data(date1+0x30);delay(5); //写数据,个位}void key() //按键函数{if(key1==0){delay(5); //去抖延时if(key1==0){num++; //功能键按下次数while(!key1); //松手判断if(num==1) //第一次按下{TR1=0; //关定时器1,时钟暂停write_com(0x8b+0x40); //地址写到显示秒位置write_com(0x0f); //控制显示光标,光标闪烁}if(num==2) //第二次按下{write_com(0x88+0x40); //地址写到显示分位置}if(num==3) //第三次按下{write_com(0x85+0x40); //地址写到显示时位置}if(num==4) //第四次按下{num=0;write_com(0x0c); //开显示,不显示光标,光标也不闪烁TR1=1; //开启定时器1,时钟继续运行}}}if(num!=0) //当有功能按键按下,才进入下面操作{if(key2==0) //增加按键按下,增加时或分或秒{delay(10); //去抖if(key2==0){while(!key2); //松手判断if(num==1) //当功能键按下的次数是一次{miao++;if(miao==60)miao=0;d1602(0x0a,miao); //改变一次,给1602送一次数据write_com(0x10); //因为上面操作一次,光标加1,} //这里是光标左移,保证闪烁位置不变if(num==2){fen++;if(fen==60)fen=0;d1602(0x07,fen);write_com(0x10);}if(num==3){shi++;if(shi==24)shi=0;d1602(0x04,shi);write_com(0x10);}}}}if(num==0) //当功能键没用被按下{d1602(0x04,shi); //一直送‘时’数据到相应位置d1602(0x07,fen); //一直送‘分’数据到相应位置d1602(0x0a,miao); //一直送‘秒’数据到相应位置}}void main() //主函数{uchar ctr;init();write_com(0x83); //第一行首地址for(ctr=0;ctr<10;ctr++) //固定不变的日期显示,1602的第一行{write_data(tabe[ctr]);delay(5);}write_com(0x86+0x40); //具体地址,写数据‘:’write_data(':');delay(5);write_com(0x89+0x40);write_data(':');delay(5);while(1){key(); //不断的扫描按键}}void timer() interrupt 3 //中断{TH1=(65536-50000)/256; //重装初值TL1=(65536-50000)%256;temp++; //累加计数,每次计数为50ms if(temp==20) //20次为1s{temp=0; //清零,一定别忘记miao++; //秒if(miao==60){miao=0;fen++; //分if(fen==60){fen=0;shi++; //时if(shi==24){shi=0;}}}}}。
基于单片机的LCD1602电子时钟设计
基于单片机的LCD1602电子时钟设计近年来,随着物联网和智能设备的快速发展,电子时钟作为一种常见的智能设备,广泛应用于家庭、办公室等各种场合。
本文将基于单片机设计一款LCD1602电子时钟,实现时间显示、闹钟设置等功能。
一、硬件设计1.单片机选择在本设计中,选择常用的51系列单片机AT89C51,具有丰富的外设资源和强大的处理能力。
该单片机具有8位数据总线、16位地址总线,并且集成了定时/计数器、中断控制器和串行通信接口等外设。
2.显示模块选择3.时钟模块选择通过接入DS1302时钟模块,可以实现实时时钟的功能。
DS1302模块具有时钟计数器、电压检测电路、串行通信接口等,并且具有低功耗特点。
4.控制板设计根据LCD1602的引脚连接方式,设计一个控制板,用于将单片机、显示模块和时钟模块等连接在一起。
同时,需注意设计供电电路、外设输入输出电平等电路。
二、软件设计1.初始化设置通过单片机的GPIO口配置,将LCD1602和DS1302对应的引脚设置为输出模式,同时初始化LCD显示屏并进行清屏操作。
此外,需设置DS1302时钟模块的时钟、日期、闹钟等参数。
2.时间显示通过读取DS1302时钟模块的计数器,获得当前的小时、分钟和秒数,然后将其格式化为HH:MM:SS的形式,并通过LCD显示出来。
3.时间设置通过单片机的外部中断,当用户按下设置按钮后,进入时间设置模式。
在时间设置模式下,用户可以通过按下不同的按键来调整小时、分钟和秒数。
调整完成后,再次按下设置按钮即可保存设置。
4.闹钟设置通过单片机的定时器中断,设定一个闹钟定时器。
当闹钟定时器触发时,触发相应的中断,然后通过LCD显示闹钟提示。
此外,用户也可以通过按下按钮来设置闹钟时间,并通过单片机的外部中断进行处理。
5.闹钟响铃当闹钟时间到达时,触发相应的中断,通过LCD显示闹钟提示,并通过蜂鸣器发出响铃声。
总结通过本设计,可以实现一款功能齐全的LCD1602电子时钟。
基于单片机的1602电子时钟设计
基于单片机的1602电子时钟设计一.实验目的:(1)用单片机设计基于单片机的1602电子时钟显示;(2)熟练掌握Keil软件;(3)熟练掌握Proteus软件仿真;(4)掌握单片机的I/O接口的工作原理;(5)掌握LCD显示器的原理和编程方法;(6)掌握独立式键盘的工作原理和编程方法;(7)掌握单片机下载方法;二.实验要求(1)可实现时钟显示(2)可调整时间三.实验内容(1)画仿真图如图1图1(2)编写程序(3)下载运行(4)运行结果,分析其中的错误四.程序(一)#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intsbit LCD_RS=P2^0;sbit LCD_RW=P2^1 ;sbit LCD_EN=P2^2;void Delay_ms(uint xms) ;bit lcd_busy();void lcd_wcmd(uchar cmd);void lcd_wdat(uchar dat) ;void lcd_clr() ;void lcd_init() ;/********以下是延时函数********/void Delay_ms(uint xms){uint i,j;for(i=xms;i>0;i--) //i=xms即延时约xms毫秒for(j=110;j>0;j--);}/********以下是LCD忙碌检查函数********/bit lcd_busy(){bit result;LCD_RS = 0;LCD_RW = 1;LCD_EN = 1;_nop_(); _nop_(); _nop_(); _nop_();result = (bit)(P0&0x80);LCD_EN = 0;return result;}/********以下是写指令寄存器IR函数********/void lcd_wcmd(uchar cmd){while(lcd_busy());LCD_RS = 0; LCD_RW = 0; LCD_EN = 0;_nop_(); _nop_();P0 = cmd;_nop_(); _nop_(); _nop_(); _nop_();LCD_EN = 1;_nop_(); _nop_(); _nop_(); _nop_();LCD_EN = 0;}/********以下是写寄存器DR函数********/void lcd_wdat(uchar dat){while(lcd_busy());LCD_RS = 1; LCD_RW = 0; LCD_EN = 0;P0 = dat;_nop_(); _nop_(); _nop_(); _nop_();LCD_EN = 1;_nop_(); _nop_(); _nop_(); _nop_();LCD_EN = 0;}/********以下是LCD清屏函数********/void lcd_clr(){lcd_wcmd(0x01); //清除LCD的显示内容Delay_ms(5);}/********以下是LCD初始化函数********/void lcd_init(){Delay_ms(15); //等待LCD电源稳定lcd_wcmd(0x38); //16*2显示,5*7点阵,8位数据Delay_ms(5);lcd_wcmd(0x38);Delay_ms(5);lcd_wcmd(0x38);Delay_ms(5);lcd_wcmd(0x0c); //显示开,关光标Delay_ms(5);lcd_wcmd(0x06); //移动光标Delay_ms(5);lcd_wcmd(0x01); //清除LCD的显示内容Delay_ms(5);}(二)#include <reg51.h>#include "LCD_drive.h"#define uchar unsigned char#define uint unsigned intuchar year=12,mon=10,day=10,hour=12,min=00,sec=00;uchar count_10ms;sbit k7=P3^0; sbit k1=P3^2; sbit k2=P3^3; sbit k3=P3^4;sbit k4=P3^5; sbit k5=P3^6; sbit k6=P3^7; bit k1_flag=0;uchar code line1_data[] = {"----"};uchar code line2_data[] = {"****"};uchardisp_buf[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; void LCD_conv(char in1,in2,in3,in4,in5,in6){disp_buf[0]=in1/10+0x30; disp_buf[1]=in1%10+0x30; disp_buf[2]=in2/10+0x30; disp_buf[3]=in2%10+0x30; disp_buf[4]=in3/10+0x30; disp_buf[5]=in3%10+0x30; disp_buf[6]=in4/10+0x30; disp_buf[7]=in4%10+0x30; disp_buf[8]=in5/10+0x30; disp_buf[9]=in5%10+0x30; disp_buf[10]=in6/10+0x30; disp_buf[11]=in6%10+0x30; }void LCD_disp(){lcd_wcmd(0x04|0x80);lcd_wdat(disp_buf[0]); lcd_wdat(disp_buf[1]);lcd_wdat(0xb0);lcd_wdat(disp_buf[2]); lcd_wdat(disp_buf[3]);lcd_wdat(0xb0);lcd_wdat(disp_buf[4]); lcd_wdat(disp_buf[5]);lcd_wcmd(0x44|0x80);lcd_wdat(disp_buf[6]); lcd_wdat(disp_buf[7]);lcd_wdat(0x3a);lcd_wdat(disp_buf[8]); lcd_wdat(disp_buf[9]);lcd_wdat(0x3a);lcd_wdat(disp_buf[10]); lcd_wdat(disp_buf[11]);}void timer1() interrupt 3{TH1=0xdc; TL0=0x00;count_10ms++;if(count_10ms>=100){count_10ms=0; sec++;if(sec>=60){sec=0; min++;if(min>=60){min=0; hour++;if(hour>=24){hour=0; day++;if(day>=30){day=1; mon++;if(mon>=12){mon=1; year++;} }}} } }}void keyprocess(){TR1=0;if(k2==0){Delay_ms(10);if(k2==0){while(!k2); year++; }}if(k3==0){Delay_ms(10);if(k3==0){while(!k3); mon++;if(mon>12){mon=0;} } }if(k4==0){Delay_ms(10);if(k4==0){while(!k4); day++;if(day>30){day=0;} } }if(k5==0){Delay_ms(10);if(k5==0){while(!k5); hour++;if(hour==24){hour=0;} }}if(k6==0){Delay_ms(10);if(k6==0){while(!k6); min++; if(min==60) {min=0;} }}if(k7==0){Delay_ms(10);if(k7==0){while(!k7);TR1=1; k1_flag=0;} }}void timer1_init(){TMOD=0x10;TH1=0xdc; TL1=0x00;EA=1; ET1 =1; TR1 =1;}void main(){uchar i;P0=0xff; P2=0xff;timer1_init ();lcd_init(); lcd_clr();lcd_wcmd(0x00|0x80);i=0;while(line1_data[i]!='\0'){lcd_wdat(line1_data[i]); i++;}lcd_wcmd(0x0c|0x80); i=0;while(line1_data[i]!='\0'){lcd_wdat(line1_data[i]); i++;}lcd_wcmd(0x40|0x80); i=0;while(line2_data[i]!='\0'){lcd_wdat(line2_data[i]); i++;}lcd_wcmd(0x4c|0x80); i=0;while(line2_data[i]!='\0'){lcd_wdat(line2_data[i]); i++;}while(1){if(k1==0){Delay_ms(10);if(k1==0){while(!k1);k1_flag=1;}}if(k1_flag==1)keyprocess();LCD_conv(year,mon,day,hour,min,sec); LCD_disp();}}。
(完整word版)1602液晶时钟程序(51单片机)
1602液晶时钟程序程序按郭天袢《新概念51单片机C语言教程》第十四章扩展显示年、月、日、星期调节功能。
1)时间显示在1602液晶上,并按秒实时更新2)能调节按键调整时、分、秒、年、月、日和星期3)每次按键按下时有短滴声响声4)断电后下次上电会接着上次断电前的时间数继续运行原理图如图//原代码如下:#include<reg52.h>//#include"24c02.h"#define uchar unsigned char#define uint unsigned int#include"24c02.h"sbit dula=P2^6;sbit wela=P2^7;sbit LCDEN=P3^4;sbit LCDRS=P3^5;sbit s1=P3^0;//定义按键--功能键sbit s2=P3^1;//定义按键--增大键sbit s3=P3^2;//定义按键--减小键sbit rd=P3^7;//按键公共脚sbit beep=P2^3;//定义蜂鸣器脚uchar count,s1_num;//定义中断次数计数变量功能键按键次数变量uchar week,day,month,year;//定义变量:星期日月年char miao,shi,fen;//定义秒分时变量uchar code table[]=" 2012-11-28 Wed";//void write_week(char we);//显示星期几函数void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void di()//蜂鸣器响一声函数{beep=0;delay(100);beep=1;}void write_com(uchar com) //液晶写命令函数{LCDRS=0;P0=com;delay(5);LCDEN=1;delay(5);LCDEN=0;}void write_date(uchar date) //液晶写数据函数{LCDRS=1;P0=date;delay(5);LCDEN=1;delay(5);LCDEN=0;}void write_week(char we) //写星期几显示函数{write_com(0x80+12);switch(we){case 1: write_date('M');delay(5); //星期一Mondaywrite_date('o');delay(5);write_date('n');delay(5);break;case 2: write_date('T');delay(5); //星期二Tuesdaywrite_date('u');delay(5);write_date('e');delay(5);break;case 3: write_date('W');delay(5); //Wednesdaywrite_date('e');delay(5);write_date('d');delay(5);break;case 4: write_date('T');delay(5); //Thursdaywrite_date('h');delay(5);write_date('u');delay(5);break;case 5: write_date('F');delay(5); //星期五Fridaywrite_date('r');delay(5);write_date('i');delay(5);break;case 6: write_date('S');delay(5); //星期六Saturdaywrite_date('a');delay(5);write_date('t');delay(5);break;case 7: write_date('S');delay(5); //星期日Sundaywrite_date('u');delay(5);write_date('n');delay(5);break;default: break;}}void write_sfm(uchar add,uchar date) //写时分秒函数{uchar shiwei,gewei;shiwei=date/10;gewei=date%10;write_com(0x80+0x40+add);//设置显示位置write_date(0x30+shiwei);//加上0x30是因为数字变成字符串需要加上0x30,看ASCII码值与字符的关系write_date(0x30+gewei);}void write_year_month_day(uchar add,uchar day) //写年月日数函数{uchar shi,ge;shi=day/10;ge=day%10;write_com(0x80+add);//设置显示位置write_date(0x30+shi);//加上0x30是因为数字变成字符串需要加上0x30,看ASCII码值与字符的关系write_date(0x30+ge);}void init() //初始化函数{uchar num;rd=0;beep=1;dula=0;wela=0;LCDEN=0;//将使能端置0以完成高脉冲fen=0;miao=0;shi=0;count=0;//计数初始为0init_24c02();write_com(0x38);//设置16*2显示,5*7点阵,8位数据接口write_com(0x0c);//设置开显示,不显示光标write_com(0x06);//写一个字符后地址指针自动加1write_com(0x01);//显示清0,数据指针清0write_com(0x80); //设置显示初始坐标for(num=0;num<15;num++) //显示年月日{write_date(table[num]);delay(5);}write_com(0x80+0x40+6); //写出时间显示部分的两个冒号write_date(0x3a);delay(5);write_com(0x80+0x40+9);write_date(0x3a);delay(5);miao=read_add(1);//开机上电时读取24c02 IIC的数据赋值fen=read_add(2);shi=read_add(3);week=read_add(4);//读取星期几day=read_add(5);//读取多少日month=read_add(6);year=read_add(7);write_sfm(10,miao);//分别送去液晶显示write_sfm(7,fen);write_sfm(4,shi);write_week(week);//开机从24c02读取的星期几数从新写入液晶显示出来write_year_month_day(9,day);write_year_month_day(6,month);write_year_month_day(3,year);//定时器初始化TMOD=0x01; //设置定时器0工作模式1TH0=(65536-45876)/256; //定时器装初值TL0=(65536-45876)%256;EA=1; //开总中断ET0=1; //打定时器0中断TR0=1; //启动定时器0}void keyscan() //按键扫描函数{if(s1==0){delay(5);if(s1==0){s1_num++; //功能键按下次数记录while(!s1); //按键释放确认di();if(s1_num==1) //只按一次按键时TR0=0; //关闭定时器write_com(0x80+0x40+11);write_com(0x0f); //打开光标闪烁}if(s1_num==2) //第二次按下光标闪烁定位到分钟位置{write_com(0x80+0x40+8);}if(s1_num==3) //第三次按下光标闪烁定位到小时位置{write_com(0x80+0x40+5);}/**************************************if(s1_num==4) //第三四次按下退出{s1_num=0;write_com(0x0c); //取消光标闪栎TR0=1; //启动定时器使时钟开始走}***************************************/if(s1_num==4) //光标处星期{write_com(0x80+14);}if(s1_num==5) //光标处日{write_com(0x80+10);}if(s1_num==6) //光标处月{write_com(0x80+7);}if(s1_num==7) //光标处年{write_com(0x80+4);}if(s1_num==8) //当第八次按功能键时退出光标闪烁及开始计时{s1_num=0;write_com(0x0c); //取消光标闪栎TR0=1; //启动定时器使时钟开始走}}if(s1_num!=0){if(s2==0)//增加键确认按下{delay(5);if(s2==0){while(!s2);di();if(s1_num==1){miao++;if(miao==60)miao=0;write_sfm(10,miao);write_com(0x80+0x40+11);write_add(1,miao);}if(s1_num==2){fen++;if(fen==60)fen=0;write_sfm(7,fen);write_com(0x80+0x40+8);write_add(2,fen);}if(s1_num==3){shi++;if(shi==24)shi=0;write_sfm(4,shi);write_com(0x80+0x40+5);write_add(3,shi);}if(s1_num==4)//按四次功能键后光标至星期几处,可调节星期几{week++;if(week==8)week=1;write_week(week);write_com(0x80+14); //写一个字符后光标会移一位,所以要重新定义光标位置write_add(4,week);}if(s1_num==5) //光标至显示日处,可调节多少日{day++;if(day==32)day=1;write_year_month_day(9,day);write_com(0x80+10);write_add(5,day);}if(s1_num==6) //光标至显示月处调节月份{month++;if(month==13)month=1;write_year_month_day(6,month);write_com(0x80+7);write_add(6,month);}if(s1_num==7){year++;if(year==100)year=00;write_year_month_day(3,year);write_com(0x80+4);write_add(7,year);}}}if(s3==0) //确认减小键被按下{delay(5);//按键防抖延时if(s3==0) //确认减小键被按下{while(!s3);di();if(s1_num==1){miao--;if(miao==-1)miao=59;write_sfm(10,miao);write_com(0x80+0x40+11);write_add(1,miao);}if(s1_num==2){fen--;if(fen==-1)fen=59;write_sfm(7,fen);write_com(0x80+0x40+8);write_add(2,fen);}if(s1_num==3){shi--;if(shi==-1)shi=23;write_sfm(4,shi);write_com(0x80+0x40+5);write_add(3,shi);}if(s1_num==4){week--;if(week==0)week=7;write_week(week);write_com(0x80+14); //写一个字符后光标会移一位,所以要重新定义光标位置write_add(4,week);}if(s1_num==5)//光标至显示日处,可调节多少日{day--;if(day==0)day=31;write_year_month_day(9,day);write_com(0x80+10);//光标位置移回在显示多少日的个位write_add(5,day);}if(s1_num==6) //光标至显示月处调节月份{month--;if(month==0)month=12;write_year_month_day(6,month);write_com(0x80+7);write_add(6,month);}if(s1_num==7){year--;if(year==-1)year=99;write_year_month_day(3,year);write_com(0x80+4);write_add(7,year);}}}}}void main(){init();//首先初始化各数据while(1){keyscan(); //按键扫描函数}}void timer0() interrupt 1 //定时器0中断服务程序{TH0=(65536-45876)/256;TL0=(65536-45876)%256;count++; //中断次数累加,计数if(count==20) //50微秒乘以20等于1秒{count=0;miao++;if(miao==60) //秒加到60则进位分钟{miao=0; //同时秒数清0fen++;if(fen==60) //分钟加到60则进位小时{fen=0; //同时分钟清0shi++;if(shi==24) //小时加到24则小时清0{shi=0;}write_sfm(4,shi);//小时若变化则重新写入write_add(3,shi);//写入24c02存储起来,小时数的写入地址为3 }write_sfm(7,fen);//分钟若变化则重新写入write_add(2,fen);}write_sfm(10,miao);//秒若变化则重新写入write_add(1,miao);}}/***********************************24C02.h头文件,将以下源代码需存为与保存的C代码根目录下。
1602液晶电子时钟程序51单片机
1602液晶电子时钟程序[日期:2009-06-11 ] [来源:net 作者:佚名] [字体:大中小] (投递新闻)连线图:; DB0---DPROT.0 DB4---DPROT.4 RS-------------P1.2; DB1---DPROT.1 DB5---DPROT.5 RW-------------P1.3; DB2---DPROT.2 DB6---DPROT.6 E--------------P1.4; DB3---DPROT.3 DB7---DPROT.7 VLCD接10K可调电阻到GND*#include "reg52.h"//头文件#include "intrins.h"#define uchar unsigned char//宏定义#define uint unsigned int//宏定义sbit RS=P1^2;//定义I/O的硬件接口sbit RW=P1^3;sbit E=P1^4;sbit led_1=P1^7;//;;;LED秒闪烁uchar Hours=0;//定义小时uchar Minutes=0;//定义分钟uchar Seconds=0;//定义秒bit Seconds_Scintillation=1;//定义秒闪烁标志#define DPDR P0//并行数据接口定义uchar code DispTab_1[]={'0','1','2','3','4','5','6','7','8','9'};//1602:0-9 数字uchar code DispTab_2[]={'A','B','C','D','E','a','b','c','d','e'};//1602:A-e 字母uchar DispBuf[8]; //8字节的显示缓冲区char char_char_1[]={" "};//定义字符串char char_char_2[]={" "};//定义空字符串void delay(uint z)//1ms延时{uchar x,x1;for(;z>0;z--){for(x=0;x<114;x++){for(x1=0;x1<1;x1++);}}}void Timer0() interrupt 1{static uchar Count_50;//uchar temp;TH0=0xb7;TL0=0xff;//定时时间为20ms,每20ms中断一次Count_50++;if(Count_50==50)//20ms*50=1秒{ Seconds_Scintillation=~Seconds_Scintillation; led_1=~led_1;Count_50=0;Seconds++;if(Seconds==60){Seconds=0;Minutes++;if(Minutes==60){Minutes=0;Hours++;if(Hours==24){Hours=0;}}}}if(Seconds_Scintillation==1)//秒闪烁标志判断DispBuf[6]=':';elseDispBuf[6]=' ';DispBuf[0]=Hours/10;//转换成10进制显示DispBuf[1]=Hours%10;DispBuf[2]=Minutes/10;DispBuf[3]=Minutes%10;DispBuf[4]=Seconds/10;DispBuf[5]=Seconds%10;temp=DispBuf[0];DispBuf[0]=DispTab_1[temp];//查表取字符temp=DispBuf[1];DispBuf[1]=DispTab_1[temp];temp=DispBuf[2];DispBuf[2]=DispTab_1[temp];temp=DispBuf[3];DispBuf[3]=DispTab_1[temp];temp=DispBuf[4];DispBuf[4]=DispTab_1[temp];temp=DispBuf[5];DispBuf[5]=DispTab_1[temp];}void write_Directive(uchar a)//写指令{RS=0;RW=0;delay(1);E=0;DPDR=a;delay(1);E=1;delay(1);E=0;delay(1);}void write_Data(uchar a)//写数据{RS=1;RW=0;delay(1);E=0;DPDR=a;delay(1);E=1;delay(1);E=0;delay(1);}void init()//初始化{ uchar i;TMOD=0x01;TH0=0xb7;TL0=0xff;//定时时间为20ms,每20ms中断一次ET0=1; //开T0中断EA=1; //开总中断TR0=1; //T0开始运行DispBuf[6]=':';delay(15);write_Directive(0x38);delay(5);write_Directive(0x38);delay(5);write_Directive(0x38);write_Directive(0x01);write_Directive(0x02);//初始化后数据地址为0x80;即第一行,第一个位置write_Directive(0x0c);//不显示光标write_Directive(0x80+0x40);//第二行第一位地址for(i=0;i<16;i++){write_Data(char_char_1[i]);//显示字符串" "}}void write_Data_String()//显示时间函数{write_Directive(0x80+0x04);//第一行,第五个位置地址write_Data(DispBuf[0]);//第一行,第五个位置write_Data(DispBuf[1]);//第一行,第六个位置write_Data(DispBuf[6]);//第一行,第七个位置write_Data(DispBuf[2]);//第一行,第八个位置write_Data(DispBuf[3]);//第一行,第九个位置write_Data(DispBuf[6]);//第一行,第十个位置write_Data(DispBuf[4]);//第一行,第十一个位置write_Data(DispBuf[5]);//第一行,第十二个位置}void main(){init();while(1){write_Data_String();//调用写连续的16 个字符,1表示第一行;2表示第二行delay(100);//延时100ms,扫描一次}}液晶显示器以其微功耗、体积小、显示内容丰富、超薄轻巧的诸多优点,在袖珍式仪表和低功耗应用系统中得到越来越广泛的应用。
基于51单片机的用 LCD1602 显示时钟的程序
用LCD1602 显示的时钟2012-04-30 15:04有这样一个题目:求一个为51 单片机编写的LCD 电子时钟的设计,简单就好!希望说一下怎么设计这个时钟,都需要些什么东西,最重要的——把这个设计需要的程序写出来。
设计的任务:以单片机控制的时钟,在LCD 显示器上显示当前的时间。
设计的基本要求:1.使用文字型LCD 显示器显示当前时间。
2.显示格式为“时时:分分:秒秒”。
3.用4个功能键操作来设置当前时间。
各个功能键的功能如下:K1:进入设置现在的时间。
K2:设置小时。
K3:设置分钟。
K4:确认完成设置。
4. 程序执行后工作指示灯LED 闪烁,表示程序开始执行,LCD 显示“00:00:00”,然后开始计时。
题目链接:/question/416705477.html//==================================================提到设计时钟,很多人都想到了时钟芯片DS1302,都说它简单、准确。
其实,这是个误区。
仅仅使用一般的单片机,简单的编程,达到相同DS1302 的准确度,并不是难事。
如果不要求计算平闰年、不要求分清大小月、不要求计算星期几,只是要求一个简单的时钟(及日历),用DS1302,就是自寻烦恼。
大家可以打开题目链接,看看其中的一些答案,就可以看出使用DS1302 是多么的繁琐了,简直就是一场噩梦。
做而论道以前就使用普通的单片机和LCD1602 设计过《时钟与日历》,程序设计的非常合理,时间精度就完全取决于晶振的精度。
设计出来的时钟,几个月都差不上一秒。
针对这个题目,做而论道翻出了以前的设计,删节了一些不需要的功能,设计出了符合题目要求的时钟,用PROTEUS 仿真截图如下:程序用C 语言编写,全部代码如下://---------------------------------------------------#include<reg52.h>#define uchar unsigned char#define uint unsigned int#define KEY_IO P3#define LCD_IO P0sbit LCD_RS = P2^0;sbit LCD_RW = P2^1;sbit LCD_EN = P2^2;sbit SPK = P1^2;sbit LED = P2^4;bit new_s, modify = 0;char t0, sec = 50, min = 59, hour = 23;char code LCD_line1[] = "Designed by ZELD"; char code LCD_line2[] = "Timer: 00:00:00 "; char Timer_buf[] = "23:59:50";//---------------------------------------------------void delay(uint z){uint x, y;for(x = z; x > 0; x--) for(y = 100; y > 0; y--);//---------------------------------------------------void W_LCD_Com(uchar com) //写指令{LCD_RS = 0; LCD_IO = com; // LCD_RS和R/W都为低电平时,写入指令LCD_EN = 1; delay(5); LCD_EN = 0; //用EN输入一个高脉冲}//---------------------------------------------------void W_LCD_Dat(uchar dat) //写数据{LCD_RS = 1; LCD_IO = dat; // LCD_RS为高、R/W为低时,写入数据LCD_EN = 1; delay(5); LCD_EN = 0; //用EN输入一个高脉冲}//---------------------------------------------------void W_LCD_STR(uchar *s) //写字符串{while(*s) W_LCD_Dat(*s++);}//---------------------------------------------------void W_BUFF(void) //填写显示缓冲区{Timer_buf[7] = sec % 10 + 48; Timer_buf[6] = sec / 10 + 48;Timer_buf[4] = min % 10 + 48; Timer_buf[3] = min / 10 + 48;Timer_buf[1] = hour % 10 + 48;Timer_buf[0] = hour / 10 + 48;W_LCD_Com(0xc0 + 7); W_LCD_STR(Timer_buf);}//---------------------------------------------------uchar read_key(void){uchar x1, x2;KEY_IO = 255;x1 = KEY_IO;if (x1 != 255) {delay(100);x2 = KEY_IO;if (x1 != x2) return 255;while(x2 != 255) x2 = KEY_IO;if (x1 == 0x7f) return 0;else if (x1 == 0xbf) return 1;else if (x1 == 0xdf) return 2;else if (x1 == 0xef) return 3;else if (x1 == 0xf7) return 4;}return 255;//---------------------------------------------------void Init(){LCD_RW = 0;W_LCD_Com(0x38); delay(50);W_LCD_Com(0x0c);W_LCD_Com(0x06);W_LCD_Com(0x01);W_LCD_Com(0x80); W_LCD_STR(LCD_line1);W_LCD_Com(0xC0); W_LCD_STR(LCD_line2);TMOD = 0x01; //T0定时方式1TH0 = 0x4c;TR0 = 1; //启动T0PT0 = 1; //高优先级, 以保证定时精度ET0 = 1;EA = 1;}//---------------------------------------------------void main(){uint i, j;uchar Key;Init();while(1) {//-------------------------------if (new_s) { //如果出现了新的一秒, 修改时间new_s = 0; sec++; sec %= 60;if(!sec) { min++; min %= 60;if(!min) { hour++; hour %= 24;}}W_BUFF(); //写显示//-------------------------------if (!sec && !min) { //整点报时for (i = 0; i < 200; i++) {SPK = 0; for (j = 0; j < 100; j++);SPK = 1; for (j = 0; j < 100; j++);} }}//-------------------------------Key = read_key(); //读出按键switch(Key) { //分别处理四个按键case 0: modify = 1; break;case 1: if(modify) {min++; min %= 60; W_BUFF(); break;}case 2: if(modify) {hour++; hour %= 24; W_BUFF(); break;}case 3: modify = 0; break;} }}//---------------------------------------------------void timer0(void) interrupt 1 //T0中断函数, 50ms执行一次{TH0 = 0x4c;t0++; t0 %= 20; //20, 一秒钟if(t0 == 0) {new_s = 1; LED = ~LED;}if(modify) LED = 0;}//===================================================呵呵,全部程序,也不过120 行左右。
关于52单片机驱动74HC595控制LCD1602的程序
关于52单片机驱动74HC595控制LCD1602的程序谁能帮忙写个52单片机驱动74hc595控制LCD1602的程序#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#define LcdBus P0sbit LED1602_RS=P2^6; //LCD端口定义sbit LED1602_RW=P2^5 ;sbit LED1602_EN=P2^4 ;void LcdIni(void);void WrOp(uchar dat);void WrDat(uchar dat);void ChkBusy(void);void print_LCD(uchar disp[],uchar num);//延时n ms子程序void delayms(unsigned int n){unsigned int i,j;for(i=0;i<n;i++)for(j=0;j<120;j++);}main(){uchar disp1[16]={'S','u','n','J','i','e',' ','m','a','d','e','','a','t',' ',' '};uchar disp2[16]={'2','0','0','8',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};while(1){LcdIni();WrOp(0x80); //数据指针地址第一行print_LCD(disp1,16);WrOp(0xc0); //第二行print_LCD(disp2,4);delayms(3000);WrOp(0x01);}}/******************************************************************** **********************名称:led1602显示程序模块功能:驱动1602 包括数据口 P1 三个控制口编译:keil作者:孙杰时间:2008-8-9********************************************************************* **********************/void print_LCD(uchar disp[],uchar num) //显示数组disp 显示长度为num {uchar i;for(i=0;i<num;i++){WrDat(disp[i]);delayms(300);}}void LcdIni(){WrOp(0x38);WrOp(0x06); //光标加1WrOp(0x0f); //开显示光标闪烁// WrOp(0x0c); //开显示光标不闪烁}void WrOp(uchar dat){//uchar i;ChkBusy();LED1602_RS=0; //RS=0LED1602_RW=0; //RW=0LED1602_EN=0; //EN=0LcdBus=dat; //送数据LED1602_EN=1; //EN=1delayms(10); //延时LED1602_EN=0; //EN=0}void WrDat(uchar dat){//uchar i;ChkBusy();LED1602_RS=1; //rs=1LED1602_RW=0; //rw=0LED1602_EN=0; //en=0LcdBus=dat; //送数据LED1602_EN=1; //en=1delayms(10);; //延时LED1602_EN=0; //en=0}void ChkBusy(){LED1602_RS=0; //RS=0LED1602_RW=1; //RW=1LED1602_EN=1; //EN=1while(LcdBus&0x80); //送数据LED1602_EN=0; //en=0}74hc595驱动问题#define uc unsigned char#define ui unsigned int#include<iom128v.h>uc Bmp[]={/*------------------------------------------------------------------------------; 源文件 / 文字 :; 宽×高(像素): 64×8; 字模格式/大小 : 单色点阵液晶字模,横向取模,字节正序/64字节; 数据转换日期 : 2009-4-7 11:11:41------------------------------------------------------------------------------*/0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40 ,0x40,0x40,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x10 ,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x04,0x04,0x04,0x04,0x04,0x04 ,0x04,0x04,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x01,0x01,0x01,0x01,0x01,0x01 ,0x01,0x01};uc B1[8]={0};uc B2[8]={0};void delay(ui n) //延时函数{ui j;ui i;for(i=0;i<n;i++)for(j=0;j<20;j++);}void H_B1(uc h) //十六进制转换为二进制,转换后放在数组B1中{B1[7]=h&0x01;B1[6]=h&0x02;B1[5]=h&0x04;B1[4]=h&0x08;B1[3]=h&0x10;B1[2]=h&0x20;B1[1]=h&0x40;B1[0]=h&0x80;}void H_B2(uc h) //十六进制转换为二进制,转换后放在数组B2中{B2[0]=h&0x01;B2[1]=h&0x02;B2[2]=h&0x04;B2[3]=h&0x08;B2[4]=h&0x10;B2[5]=h&0x20;B2[6]=h&0x40;B2[7]=h&0x80;}void print(void) //扫描函数{uc byte=0;uc j=0;uc row=7; //扫第一行uc column;uc bit=0;uc h=0;PORTD=row; //行数赋给PDH_B1(Bmp[0]);while(1){for(row=7;row!=0xff;row--){PORTD=row; //行数赋给PDPORTF=0X00; //给一个扫描点PORTC=0xff;PORTC=0x00;PORTF=0XFF;for(byte=0;byte<8;byte++){H_B1(Bmp[byte+j]);for(bit=0;bit<8;bit++){//delay(2000);PORTC=0xff; //时钟上升沿//delay(1000);if(B1[bit]==0) PORTE=0Xff;//如果该点不应亮则74_138输出高阻else {PORTE=0X00; delay(40);}//否则输出低电平PORTF=0XFF; //扫描点后面通通熄灭//delay(2000);PORTC=0x00; //时钟下降沿}PORTG=0Xff;//delay(2000);PORTG=0X00;//bit=0;}j+=8;byte=0;}j=0;}}void main(void){DDRC=0XFF; //PC口为时钟输出DDRD=0XFF; //PD为行选,连74_138的ABC输入端DDRF=0XFF; //PF为列选,扫描点,接74_595的DS端DDRE|=0X80; //PE7为输出,74_138使能控制,低电平有效 DDRG =0Xff;PORTG=0X00;PORTE=0XFF; delay(5000); PORTE=0X00; //开机信号//PORTE=0X00;print();}这是我刚写的一个64*8的点阵扫描程序用74HC595做行选,但是没用锁存,可以显示,但亮度很低。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
基于52单片机控制的1602液晶电子时钟显示程序
关于利用52单片机制作1602液晶电子时钟显示的程序,网上也有很多资料,不过个人感觉还是挺乱的。
曾经我也是一名初学者,看过很多别人的资料,查找过很多书籍,一个个程序的摸索,经常被弄得头昏脑涨,深受其苦。
今天,我自己精心的整理了一份“基于52单片机控制的1602液晶电子时钟显示程序”的资料,程序每个点几乎都有注释,适合初学者学习,供有兴趣的朋友参考。
也算作为自己一直以来在网上搜索那么多资料而给大家的一点点回报吧。
这程序简单易懂,也有一些可改善的地方,比如写命令和写数据的函数可以合并等等。
大家可根据自己的爱好进行修改,多动手多尝试,相信你很快就能学会。
值得注意的是,1,此程序是利用52单片机控制,如果你的是51单片机,需要改动一下头文件#include<reg51.h> 的。
2,关于引脚,大家需要根据实际情况定义具体的引脚,不同的学习板,或者你自己焊接的板子,引脚都可能不一样。
3,本程序的日期是固定的,自己可以编写函数进行年月日显示。
由于本作者水平有限,错误疏漏之处在所难免,欢迎读者指正。
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit lcden=P3^4; //1602使能信号
sbit lcdrs=P3^5; //1602命令(0)/数据(1)选择端
sbit wr=P3^6; //1602读写选择端,一般为低电平(0)
sbit key1=P3^7; //定义功能按键,可根据实际情况改变
sbit key2=P2^0; //数字增加按键,也可根据实际情况改变
sbit dula=P2^6; //关闭实验板上数码管的段选,这两句可根据实际情况注释掉sbit wela=P2^7; //关闭实验板上数码管的段选
uchar temp,num,shi,fen,miao;
uchar code tabe[]="2013-07-20"; //固定日期,可扩展为动态
void delay(uint z) //延时1ms程序
{
uint i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
void write_com(uchar com) //写命令
{
lcdrs=0; //rs为低电平写命令
P0=com;
delay(5);
lcden=1; //高脉冲使能
delay(5);
lcden=0;
}
void write_data(uchar dat) //写数据
{
lcdrs=1; //rs为高电平写数据
P0=dat;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init() //初始化
{
EA=1; //开总中断
ET1=1; //开定时器1中断
TMOD=0x10; //设置TMOD参数
TH1=(65536-50000)/256; //给寄存器装初值
TL1=(65536-50000)%256;
TR1=1; //开启定时器1
num=0;
shi=0;
fen=0;
miao=0;
lcden=0;
dula=0;
wela=0;
wr=0; //写,低电平有效
write_com(0x38); //设置16*2显示,5*7点阵,8位数据接口
write_com(0x0C); //开显示,这里上下四句话需参考厂家提供的1602参数设置write_com(0x06); //写一个字符后地址指针加1,且光标加1,写一个字符时,整屏不动
write_com(0x01); //显示清屏,数据指针清0
}
void d1602(uchar add,uchar date) //给1602发送地址与数据
{
uchar date2,date1; //拆分个位与十位
date2=date/10;
date1=date%10;
write_com(0x80+0x40+add); //写指令,地址
write_data(date2+0x30);delay(5); //写数据,十位
write_data(date1+0x30);delay(5); //写数据,个位
}
void key() //按键函数
{
if(key1==0)
{
delay(5); //去抖延时
if(key1==0)
{
num++; //功能键按下次数
while(!key1); //松手判断
if(num==1) //第一次按下
{
TR1=0; //关定时器1,时钟暂停
write_com(0x8b+0x40); //地址写到显示秒位置
write_com(0x0f); //控制显示光标,光标闪烁
}
if(num==2) //第二次按下
{
write_com(0x88+0x40); //地址写到显示分位置
}
if(num==3) //第三次按下
{
write_com(0x85+0x40); //地址写到显示时位置
}
if(num==4) //第四次按下
{
num=0;
write_com(0x0c); //开显示,不显示光标,光标也不闪烁
TR1=1; //开启定时器1,时钟继续运行}
}
}
if(num!=0) //当有功能按键按下,才进入下面操作
{
if(key2==0) //增加按键按下,增加时或分或秒
{
delay(10); //去抖
if(key2==0)
{
while(!key2); //松手判断
if(num==1) //当功能键按下的次数是一次
{
miao++;
if(miao==60)
miao=0;
d1602(0x0a,miao); //改变一次,给1602送一次数据
write_com(0x10); //因为上面操作一次,光标加1,
} //这里是光标左移,保证闪烁位置不变
if(num==2)
{
fen++;
if(fen==60)
fen=0;
d1602(0x07,fen);
write_com(0x10);
}
if(num==3)
{
shi++;
if(shi==24)
shi=0;
d1602(0x04,shi);
write_com(0x10);
}
}
}
}
if(num==0) //当功能键没用被按下
{
d1602(0x04,shi); //一直送‘时’数据到相应位置
d1602(0x07,fen); //一直送‘分’数据到相应位置
d1602(0x0a,miao); //一直送‘秒’数据到相应位置}
}
void main() //主函数
{
uchar ctr;
init();
write_com(0x83); //第一行首地址
for(ctr=0;ctr<10;ctr++) //固定不变的日期显示,1602的第一行
{
write_data(tabe[ctr]);
delay(5);
}
write_com(0x86+0x40); //具体地址,写数据‘:’
write_data(':');delay(5);
write_com(0x89+0x40);
write_data(':');delay(5);
while(1)
{
key(); //不断的扫描按键
}
}
void timer() interrupt 3 //中断
{
TH1=(65536-50000)/256; //重装初值
TL1=(65536-50000)%256;
temp++; //累加计数,每次计数为50ms if(temp==20) //20次为1s
{
temp=0; //清零,一定别忘记
miao++; //秒
if(miao==60)
{
miao=0;
fen++; //分
if(fen==60)
{
fen=0;
shi++; //时
if(shi==24)
{
shi=0;
}
}
}
}
}。