1602LCD显示的秒表 C语言程序
基于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;当进行写模块操作,指向指令寄存器。
LCD1602液晶显示C程序
1、关于1602液晶的电气参数一般市场上的1602液晶使用的驱动器为HD44780U或HD44780S,市场上大部分液晶用的是后者。
HD44780S的供电电压为5V±10%,而HD44780U的供电电压为2.7V~5.5V。
也就是说,绝大部分1602液晶只能工作在5V电压下,其供电电压必须为5V。
经过试验发现,1602液晶的供电虽然必须为5V,但其控制总线和数据总线可以用3.3V电平(因为对于TTL电平,一般大于2.5V以上都算高电平,不过最可靠的是大于3.6V),只不过在3.3V电平下,数据的通信速度会大大降低,这一点需要在写驱动时注意。
需要时,可以将MCU的IO配置为漏极开路方式,用上拉电阻拉到5V电平;实在不能配置为漏极开路方式时,请查阅MCU的电气参数,在允许的条件下,直接使用电阻弱上拉也可以。
2、硬件连接1602液晶可以使用4位或8位通信模式,通信可以是双向的或单向的,双向通信主要是为了读取LCD忙标志和AC地址寄存器和DDRAM和CGRAM中的值,一般用处不大,因为1602不支持点阵绘图功能。
在连接时,注意4位通信方式下,LCD只使用DB7~DB4,一般情况下会使用MCU 某端口的高4位或低4位与之连接,注意写驱动时在必要的情况下对端口的其它几位要保护,防止破坏其数据;当然如果没有使用其它4位时则不必要保护(奇怪,不使用其它4位干嘛用4位通信方式嘛?)。
还要注意的是,如果需要双向通信,则必须选择既能做输入又能做输出的IO口,特别是对于RS、RW和E这三条控制线,若能选择支持位寻址的IO口则可以方便编程。
3、底层驱动问题通用1602液晶的时序如图:(1)、写时序(2)、读时序总的说来,按照这个时序图来编写驱动程序是不会出什么问题的,只是要深刻理解时序图中各参数的涵义。
编程中要特别关注E这根控制线。
写操作的时序应该是:①、RS=0(写指令寄存器)或RS=1(写数据寄存器);②、RW=0(写操作);③、将数据写到数据线上;④、E=1;⑤、E=0 。
1602lcd显示的秒表
目录1 概述 01.1 1602LCD研究的历史背景和意义 01.2 1602LCD研究的发展和现状 02 课题方案设计 02.1系统设计目的 02.2系统结构模块论证 (1)2.2.1 显示部分 (1)3 系统硬件设计 (1)3.1 总体设计 (1)3.2 单片机运行的最小系统 (2)3.2.1 电源电路 (2)3.2.2晶振电路 (2)3.2.3复位电路 (3)3.3 显示电路 (4)3.3.1引脚说明: (4)3.4 单片机STC89C52 (5)3.4.1主要特性 (5)3.4.2功能特性概述 (6)3.4.3主要引脚及芯片基本工作条件说明 (6)4 系统软件设计 (7)4.1 总流程图 (7)4.2 最小系统检测电路程序 (8)4.3 编程调试界面 (9)4.4 Proteus仿真结果 (9)5软硬件联调及调试结果 (10)5.1 实物图 (10)5.2 调试结果 (11)结束语 (12)参考文献 (12)附录2 1602LCD设计的秒表PCB图 (14)附录3 1602LCD设计的秒表Proteus仿真图 (15)附录4 1602LCD设计的秒表C语言程序清单 (15)附录5 基于单片机的1602LCD设计的秒表元器件目录表 (21)1 概述1.1 1602LCD研究的历史背景和意义LCD1602是16字乘以2行的字符型液晶模板。
其特点是:(1)位数多,可显示32位。
(2)显示内容丰富,可显示所有数字、字母、符号等192种ASCII码对应的字符。
(3)程序简单1.2 1602LCD研究的发展和现状液晶显示模块具有体积小、功耗低、显示内容丰富、超薄轻巧等优点,在袖珍式仪表和低功耗应用系统中得到广泛的应用。
目前字符型液晶显示模块已经是单片机应用设计中最常用的信息显示器件。
LCD1602液晶显示模块,它可以显示两行,每行16个字符,采用单+SV电源供电,外围电路配置简单,价格便宜,具有很高的性价比。
1602LCD显示的秒表 C语言程序
源程序代码://名称:用1602LCD设计的秒表//说明:首先按下K1键时开始计时,自此按下时暂停,第三次按下时继续累积计时,再次按下时停止计时,K2键用于清零秒表。
//#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#define delayNOP ( ) ﹛_nop_( ); _nop_( ); _nop_( ); _nop_( );﹜//LCD控制函数void LCD_Initialize( );void LCD_Set_POS(uchar);void LCD_Write_Date(uchar);void Display_String(uchar﹡,uchar);sbit K1 = P1^0;sbit K2 = P1^1;sbit BEEP = P3^0;sbit LCD_RS = P2^0;sbit LCD_RW = P2^1;sbit LCD_EN = P2^2;uchar KeyCount = 0;uchar code msg1[] = ﹛〞Second Watch 0 〞﹜;uchar code msg2[] = ﹛〞>>>> 0 〞﹜;uchar code Prompts[] [16] ={﹛〞:: 1- - - - > 〞﹜,﹛〞:: 1- - - - > ::2 〞﹜,﹛〞:: 1 - >2 ::3- - > 〞﹜,﹛〞:: 1 - >2 ::3- - >4 〞﹜};// 计时缓冲与显示缓冲uchar Time_Buffer[] ={0,0,0,0};uchar LCD_Display_Buffer[]={〞00: 00: 00:00〞}; //// 蜂鸣器//void Beep ()﹛uchar i,j = 70;for (i = 0;i< 180;i++ )﹛while(--j);BEEP = ~BEEP;﹜BEEP = 0;﹜//// 延时//void DelayX(uint ms){uchar i;while(ms--) for (i= 0;i< 120;i++);﹜//// 显示计时//void Show_Second( ){uchar i;LCD_Set_POS(0x45); //设置LCD显示起点for(i = 3;i != 0xff ;i--);{//将两位整数的1/100s,秒,分,时转换为8位数字字符LCD_Display_Buffer[2﹡i+1] = Time_Buffer[i] / 10 + ˊ0 ˊ;LCD_Display_Buffer[2﹡i] = Time_Buffer[i] % 10 + ˊ0 ˊ;//在 = 3,2,1,0时分别显示时,分,秒,1/100sLCD_Writer_Date(LCD_Display_Buffer[2﹡i+1])LCD_Writer_Date(LCD_Display_Buffer[2﹡i])LCD_Writer_Date(ˊ: ˊ)}}//// Time0中断//Void Time0( ) interrupt 1 using 0{THO = -10000 / 256;TLO = -10000 % 256;Time_Buffer[0] ++if(Time_Buffer[0] == 100){Time_Buffer[0] = 0; Time_Buffer[1]++;}if(Time_Buffer[1] == 60) //秒{Time_Buffer[1] = 0; Time_Buffer[2]++;}if(Time_Buffer[2] == 60) //分{Time_Buffer[2] = 0; Time_Buffer[3]++;}if(Time_Buffer[3] == 24) //时Time_Buffer[3] = 0;}////主函数//void main( ){uchar i;IE = 0x82;TMOD = 0x01;THO = -10000 / 256;TLO = -10000 % 256;LCD_Initialize( );Display_String(msg1,0x00);Display_String(msg2,0x40);While(1){if(k1 == 0){DelayX(100);i = ++KeyCount;switch (i){case 1:case 3: TRO = 1;Display_String(Prompts[i-1],0);Break;case 2:case 4: TRO = 0;Display_String(Prompts[i-1],0);break;default:TRO = 0;break;}While (K1 == 0); // 等待释放K1键Beep( );}elseif(K2 == 0){TRO = 0;KeyCount = 0;for(i = 0;i < 4; i++)Time_Buffer [i] = 0; // 清零计数缓冲Display_String(msg1,0);Beep( );DelayX(100);while (K2 == 0); // 等待释放K2键}Show_Second( );}}//// 1602LCD显示驱动函数//#include 〈reg51.h〉#include 〈intrins.h〉#define uchar unsigned char#define uint unsigned int#define DellayNOP( )﹛_nop_( ); _nop_( ); _nop_( ); _nop_( );﹜sbit LCD_RS = P2^0;sbit LCD_RW = P2^1;sbit LCD_EN = P2^2;bit LCD_Busy_Check( );void LCD_Initialize( );void LCD_Set_POS(uchar);void LCD_Write_Command(uchar);void LCD_Write_ Date(uchar);//// 延时//void DelayMS(uint ms){uchar t;while(ms--) for (t =0;t < 120;t++);}//// LCD忙检查//bit LCD_Busy_Check( );{bit Rsult;LCD_RS = 0; LCD_RW = 1; LCD_EN = 1;DelayNOP( );Result = (bit)(p0 ﹠ 0x80);LCD_EN = 0return Result;}//// 向LCD写指令//void LCD_Write_Command(uchar cmd);{while(LCD_Busy_Check() );LCD_RS = 0; LCD_RW = 0; LCD_EN = 0;_nop_( ); _nop_( );pO = cmd; DelayNOP( );LCD_EN = 1;DelayNOP( );LCD_EN = 0;}//// 向LCD写数据//void LCD_Write_Date(uchar str);{while(LCD_Busy_Check() );LCD_RS = 1; LCD_RW = 0; LCD_EN = 0;pO = str; DelayNOP( ); LCD_EN = 1;DelayNOP( );LCD_EN = 0;}//// 初始化LCD//void LCD_Initialize( );{DelayMS(5); LCD_Write_Command(0x38);DelayMS(5); LCD_Write_Command(0x0c);DelayMS(5); LCD_Write_Command(0x06);DelayMS(5); LCD_Write_Command(0x01);DelayMS(5);}//// 设置显示位置//void LCD_Set_POS(uchar Poition){LCD_Write_Command(Position ︱ 0x80);}////显示函数,在LCD指定行上显示字符串//void Display_String(uchar﹡str,uchar LineNO) {uchar k;LCD_Set_POS(LineNO);for (k = 0;k < 16;k++) LCD_Write_Date(str[k]) }。
基于51单片机的1602液晶屏的时钟显示完整程序
//基于51单片机的1602液晶屏的时钟显示完整程序#include <reg52.h>#define uchar unsigned char#define uint unsigned intsbit en=P2^6;sbit rs=P2^4;sbit rw=P2^5;uchar count,shi,fen,miao;void delay(unsigned int);void init();void write_com(unsigned char);void write_date(unsigned char);void write_sfm(uchar,uchar);uchar code table[]="2013-2-15";uchar code table1[]="23:59:55";void main(){init();while(1){if(count==20){count=0;miao++;if(miao==60){miao=0;fen++;if(fen==60){fen=0;shi++;if(shi==24){shi=0;}write_sfm(1,shi);}write_sfm(3,fen);}write_sfm(6,miao);}}// while(1);}void delay(unsigned int z) // 延时函数{unsigned int x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void init(){unsigned char num;en=0;rw=0;write_com(0x38); //设置点阵write_com(0x0c); //设置光标不闪烁write_com(0x06); //设置光标地址后移write_com(0x01); //清屏write_com(0x80); // 表示从第一行开始显示for(num=0;num<9;num++){write_date(table[num]);delay(20);}write_com(0x80+0x40);for(num=0;num<8;num++){write_date(table1[num]);delay(20);}TMOD=0x01;TH0=(65536-50000)/256;TL0=(65535-50000)%256;EA=1;ET0=1;TR0=1;}void write_com(unsigned char com) //送指令{rs=0;rw=0;en=0;P0=com;delay(5);en=1;delay(5);en=0;}void write_date(unsigned char date) //送数据{rs=1;en=0;rw=0;P0=date;delay(5);en=1;delay(5);en=0;}void time0() interrupt 1{TH0=(65536-50000)/256;TL0=(65535-50000)%256;count++;}void write_sfm(uchar add,uchar date) //将数据分离{unsigned char shi,ge;shi=date/10;ge=date%10;write_com(0x80+0x40+add);write_date(0x30+shi); //将数值转化为十六进制0是30。
LCD 1602静态显示程序(C语言例程)
_nop_();
_nop_();
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 0;
}
lcd_init()
{//LCD初始化设定
lcd_wcmd(0x38);//
delay(1);
lcd_wcmd(0x0c);//
delay(1);
lcd_wcmd(0x06);//
#include <reg51.h>
#include <intrins.h>
typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef bit BOOL ;
sbit rs= P2^0;//
sbit rw = P2^1;
sbit ep = P2^2;
* Description: *
*字符LCD显示演示程序*
*在第一行显示welcome *
*在第一行显示 *
* *
*******************************************************************************/
_nop_();
ep = 0;
}
lcd_pos(BYTE pos)
{//设定显示位置
lcd_wcmd(pos | 0x80);
}
lcd_wdat(BYTE dat)
{//写入字符显示数据到LCD
while(lcd_bz());
rs = 1;
rw = 0;
ep = 0;
P0 = dat;
液晶显示控制(1602)c语言实例
DB1 低4位三态、 双向数据总线 1位
9
DB2 低4位三态、 双向数据总线 2位
10 DB3 低4位三态、 双向数据总线 3位
11 DB4 高4位三态、 双向数据总线 4位
12 DB5 高4位三态、 双向数据总线 5位
13 DB6 高4位三态、 双向数据总线 6位
14 DB7 高4位三态、 双向数据总线 7位 (最高位)(也是busy flag)
4 可视角度
➢大多数光都是从屏幕中垂直射出来的,所以从某一个 较大的角度观看液晶显示器时,便不能看到原本的颜 色,甚至只能看到全白或全黑。为了解决这个问题, 到目前为止有三种比较流行的技术,分别是: TN+FILM、IPS(IN-PLANE -SWITCHING)和 MVA(MULTI-DOMAIN VERTICAL align MENT)。
(8)写指令38H:显示模式设置; (9)写指令08H:显示关闭;
(10)写指令01H:显示清屏; (11)写指令06H:显示光标移动设置; (12)写指令0CH:显示开及光标设置;
2011年春
LCD 1602初始化函数实例
void Initialize_LCD( )
{
Write_LCD_Command(0x38);
4 RS RS为寄存器选择,高电平1时选择数据寄 存器、低电平0时选择指令寄存器。
5 R/W R/W为读写信号线,高电平时进行读操作, 低电平时进行写操作。
6E
E(或EN)端为使能(enable)端,下降沿使 能。
2011年春
引脚 符号
功能说明
7
DB0 低4位三态、 双向数据总线 0位
(最低位)
8
(2)写指令: 输入:RS=L;RW=L; D0~D7=指令码;E=高脉冲
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); }。
LCD1602液晶秒表C51程序
LCD1602液晶秒表C51程序此程序是基于51hei单片机开发板上面写的,如需要移植到自己的电路上,修改相应的端口即可,开发板完整的电路图下载: 点这里(注意:只需要看1602部分即可,其他部分可以忽略)/*************************************************** *********************** @file main.c* @author xr* @date 2014年5月8日22:11:33 -- 2014年5月9日12:03:49* @version V1.2.3* @brief LCD1602液晶跑表单片机STC89C52RC MCU 晶振 11.0592MHZ************************************************* ***********************/#include ;/* 系统时钟 */#define SYS_XTAL (11059200UL/12)/* 定时器T0重载值 */unsigned char thr0, tlr0;unsigned char thr1, tlr1;/* 跑表计数 */unsigned char timer[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; //分别表示跑表的各个位上的数字bit flag10ms = 0;extern bit stopflag;//跑表走停标志位extern void InitalLCD1602();extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char * str);extern void KeyDriver();extern void KeyScan();void DisplayTimer();void ConfigTimer0(unsigned int xms);void ConfigTimer1(unsigned int xms);/* 主函数main() */void main(void){ConfigTimer0(10); //定时10msConfigTimer1(1);InitalLCD1602();LcdShowStr(0, 0, "stopwatch");LcdShowStr(2, 1, "0000000.00s"); //液晶初始化显示LcdShowStr(10, 0, "stop!");while (1){KeyDriver();DisplayTimer();if ((flag10ms == 1) && (stopflag == 1)){flag10ms = 0;timer[0]++;if (timer[0] >; 9){timer[0] = 0;timer[1]++;if (timer[1] >; 9){timer[1] = 0;timer[2]++;if (timer[2] >; 9) {timer[2] = 0;timer[3]++;if (timer[3] >; 9) {timer[3] = 0;timer[4]++;if (timer[4] >; 9) {timer[4] = 0;timer[5]++;if (timer[5] >; 9) {timer[5] = 0;timer[6]++;if (timer[6] >; 9) {timer[6] = 0;timer[7]++;if (timer[7] >; 9){timer[7] = 0;timer[8]++;if (timer[8] >; 9){timer[8] = 0;}}}}}}}}}}}}/* 将跑表时间显示到液晶上 */ void DisplayTimer(){unsigned char str[20];/* 分解timer */str[0] = timer[8] + '0';str[1] = timer[7] + '0';str[2] = timer[6] + '0';str[3] = timer[5] + '0';str[4] = timer[4] + '0';str[5] = timer[3] + '0';str[6] = timer[2] + '0';str[7] = '.';str[8] = timer[1] + '0';str[9] = timer[0] + '0';str[10] = '\0';LcdShowStr(2, 1, str);}/* 定时器T0配置 */void ConfigTimer0(unsigned int xms) {unsigned long tmp;tmp = (SYS_XTAL * xms) / 1000;tmp = 65536-tmp + 18;thr0 = (unsigned char)(tmp >;>; 8) ; tlr0 = (unsigned char)tmp;TMOD &= 0xF0; //清零T0控制位TMOD |= 0x01; //定时器方式1TH0 = thr0;TL0 = tlr0;TR0 = 1; //开启timer0ET0 = 1; //开启T0中断EA = 1; //开启总中断}/* 配置定时器T1 */void ConfigTimer1(unsigned int xms) {unsigned long tmp;tmp = (SYS_XTAL * xms) / 1000;tmp = 65536 - tmp + 18;thr1 = (unsigned char)(tmp >;>; 8); tlr1 = (unsigned char)tmp;TMOD &= 0x0F;TMOD |= 0x10;TH1 = thr1;TL1 = tlr1;TR1 = 1;ET1 = 1;EA = 1;}/* 定时器T0中断服务 */void Timer0_ISP() interrupt 1{TH0 = thr0;TL0 = tlr0;flag10ms = 1; //定时10ms}/* 定时器T1中断服务 */void Timer1_ISP() interrupt 3{TH1 = thr1;TL1 = tlr1; //定时1msKeyScan();}/*************************************************** *********************** @file Lcd1602.c* @author xr* @date 2014年5月7日13:33:17* @version V1.2.3* @brief LCD1602液晶底层驱动************************************************* ***********************/#include ;//LCD1602_IOsbit LCD1602_RS = P1^0;sbit LCD1602_RW = P1^1;sbit LCD1602_EN = P1^5;#define LCD1602_DB P0/* 液晶忙碌等待 */void LCD1602Wait(){unsigned char sta;LCD1602_DB = 0xFF;//总线拉高,检测液晶状态字LCD1602_RS = 0;LCD1602_RW = 1;do{LCD1602_EN = 1;sta = LCD1602_DB;LCD1602_EN = 0;//避免液晶输出数据} while (sta & 0x80);//状态字最高位STA7 == 0空闲,1忙碌}/* 液晶写命令 */void LCD1602WriteCmd(unsigned char cmd){LCD1602Wait();LCD1602_RS = 0;LCD1602_RW = 0;LCD1602_EN = 0;LCD1602_DB = cmd;LCD1602_EN = 1;LCD1602_EN = 0;}/* 液晶写数据 */void LCD1602WriteData(unsigned char dat){LCD1602Wait();LCD1602_RS = 1;LCD1602_RW = 0;LCD1602_EN = 0;LCD1602_DB = dat;LCD1602_EN = 1;LCD1602_EN = 0;}/* 液晶初始化 */void InitalLCD1602(){LCD1602WriteCmd(0x38);LCD1602WriteCmd(0x0C);LCD1602WriteCmd(0x06);LCD1602WriteCmd(0x01);//清屏}/* 写数据到液晶上,字符串str,坐标(x, y),地址addr */void LcdShowStr(unsigned char x, unsigned char y, unsigned char * str){unsigned char addr;if (y == 0){addr = 0x00 + x;}else{addr = 0x40 + x;}LCD1602WriteCmd(addr | 0x80);while (*str != '\0'){LCD1602WriteData(*str++);}}/*************************************************** *********************** @file keyboard.c* @author xr* @date 2014年5月8日22:11:33 -- 2014年5月9日12:03:49* @version V1.2.3* @brief 按键驱动单片机STC89C52RC MCU 晶振11.0592MHZ************************************************* ***********************/#include ;/* 按键输出输入端口定义 */sbit KEY_IN1 = P2^4;sbit KEY_IN2 = P2^5;sbit KEY_IN3 = P2^6;sbit KEY_IN4 = P2^7;sbit KEY_OUT1 = P2^3;sbit KEY_OUT2 = P2^2;sbit KEY_OUT3 = P2^1;sbit KEY_OUT4 = P2^0;extern unsigned char timer[9]; //分别表示跑表的各个位上的数字/* 按键当前状态 */unsigned char volatile keySta[4][4] = {{1, 1, 1, 1},{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};/* 按键对应标准PC键盘编码 */const unsigned char code keyCodeMap[4][4] = {{'1', '2', '3', 0x26}, /* 数字键 1, 2, 3 和向上键 */{'4', '5', '6', 0x25}, /* 数字键 4, 5, 6 和向左键 */{'7', '8', '9', 0x28}, /* 数字键 7, 8, 9 和向下键 */{'0', 0x1B, 0x0D, 0x27} /* 数字键 0 和向右键*/};bit stopflag = 0;//跑表走停标志位 0 停止,1运行void KeyAction(unsigned char keycode);void LcdShowStr(unsigned char x, unsigned char y, unsigned char * str);/* 按键驱动函数 */void KeyDriver(){/* 上一次按键的备份值 */static unsigned char keybackup[4][4] = {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};for (i = 0; i < 4; i++){for (j = 0; j < 4; j++){if (keySta[i][j] != keybackup[i][j]) //当前按键状态和上一次的按键状态不同{ //按键有动作if (keybackup[i][j] != 0) //上一次按键是弹起 {KeyAction(keyCodeMap[i][j]); //当前按键是想、按下}keybackup[i][j] = keySta[i][j]; //备份当前按键值}}}}/* 按键扫描函数 */void KeyScan(){static unsigned char keyout = 0;//按键行索引static unsigned char keybuf[4][4] = {{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}};/* 按键消抖 */keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN1;keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN2;keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN3;keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN4;/* 更新按键的值 */for (i = 0; i < 4; i++){if ((keybuf[keyout][i] & 0x1F) == 0x1F){//五次检测按键的值都是1keySta[keyout][i] = 1;}else if ((keybuf[keyout][i] & 0x1F) == 0x00) {//五次检测的按键值都是0keySta[keyout][i] = 0;}}/* 按键行索引++ */keyout++;keyout &= 0x03;//到4归零/* 根据按键索引选择行按键进行扫描 */switch (keyout){case 0: KEY_OUT1 = 0; KEY_OUT4 = 1;//选择第一行按键case 1: KEY_OUT2 = 0; KEY_OUT1 = 1;case 2: KEY_OUT3 = 0; KEY_OUT2 = 1;case 3: KEY_OUT4 = 0; KEY_OUT3 = 1;default: break;}}/* 按键动作函数 */void KeyAction(unsigned char keycode){unsigned char i = 0;if (keycode == 0x1B) //ESC{/* 跑表复位 */stopflag = 0;for (i = 0; i < 9; i++){timer[i] = 0;}LcdShowStr(2, 1, "0000000.00s"); LcdShowStr(10, 0, "reset!");}else if (keycode == 0x0D) //回车键跑表走停{if (stopflag == 0){stopflag = 1;LcdShowStr(10, 0, "start!");}else{stopflag = 0;LcdShowStr(10, 0, "stop! "); //多写入一个空格}}}。
1602LCD简单时钟显示实验C语言
tmp=dispbuf[1];
tmp=word[tmp];
lcd_wmd(tmp);
tmp=dispbuf[0];
tmp=word[tmp];
lcd_wmd(tmp);
}
/*********************键盘子程序***********************/
uchar keypro(void)
{
uchar scanl,scanh;
P1=0xf0;
if((P3&0xf0)!=0xf0)
{
delay();
if((P1&0xf0)!=0xf0)
{
scanl=0xfe;
while((scanl&0x10)!=0)
{
P1=scanl;
if((P3&0xf0)!=0xf0)
{
scanh=(P1&0xf0)|0x0f;
return (~scanh)+(~scanl);
}
else scanl=(scanl<<1)|0x01;
}
/*******写命令**********/
void lcd_wmc(uchar i)
{
P0=i;
RS=0;
RW=0;
E=0;
delay();
E=1;
}
/*******写数据***********/
void lcd_wmd(uchar i)
dispbuf[5]=11;
}
//更新显示缓冲区及调用显示程序
if(counter==0)
(完整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代码根目录下。
基于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 行左右。
1602液晶显示(年月日时分秒星期)
电子钟—1602液晶显示(年月日时分秒星期)/* 以下是电子钟的c51源程序,用1602液晶显示,虽然程序很庞大,但容易看懂。
改程序花了我两三天的时间才弄好的,现在放在此分享。
*/#include<AT89X52.H>#include<intrins.h>#define uchar unsigned char#define uint unsigned int#define T 49998#define T1 64536sbit rs=P2^0;sbit rw=P2^1;sbit en=P2^2;uchar key,n,loca=0,allow=0,cout;uchar week;uchar time[6]={0,6,15,12,30,0}; //对应、月、日、时、分、秒?uint year=2009;void delay(uint ms){uint i;for(;ms>0;ms--){for(i=246;i>0;i--);}}void timer0() interrupt 1{TH0=(65536-T)/256;TL0=(65535-T)%256;n++;}void time_addsec(){if(20<=n){n=0;time[5]++; //产生秒}}uchar key_scan(){uchar i,j,key,temp;uchar code scan[]={0xfe,0xfd,0xfb,0xf7};uchar code keyb[]={0x7e,0xbe,0xde,0xee,0x7d,0xbd,0xdd,0xed,0x7b,0xbb,0xdb,0xeb,0x77,0xb7,0xd7,0xe7};for(i=0;i<4;i++){P3=scan[i];_nop_();temp=P3;if(temp!=scan[i]){for(j=0;j<16;j++){if(keyb[j]==P3){delay(50);// while(keyb[j]==P3);//松手操作// delay(20);// while(keyb[j]==P3);key=j+1;break;}if(keyb[j] != P3){key=0;}}}}return key;}bit lcd_bz()//1602检忙{bit v;rs=0;rw=1;en=1;_nop_();v=(bit)(P0&0x80);en=0;return v;}void lcd_wcmd(uchar cmd)//1602写命令{while(lcd_bz());rs=0;rw=0;en=0;_nop_();P0=cmd;_nop_();en=1;_nop_();_nop_();en=0;_nop_();rs=0;}void lcd_wdat(uchar dat)//1602写数据{while(lcd_bz());rs=1;rw=0;en=0;_nop_();P0=dat;_nop_();en=1;_nop_();;en=0;}void lcd_wstr(uchar *str)//1602写字符串{uchar i;for(i=0;str[i]!='\0';i++){lcd_wdat(str[i]);}}void lcd_pos(uchar pos)//光标定位{while(lcd_bz());lcd_wcmd(pos|0x80);}/*void lcd_cur(){switch(loca){case 0 : lcd_pos(0x46); case 1 : lcd_pos(0x49); case 2 : lcd_pos(0x05); case 3 : lcd_pos(0x08); case 4 : lcd_pos(0x0b); }}*/void lcd_rmove()//光标右移{if(1==allow){if(loca >= 0 && loca < 5) {loca++;}}}void lcd_lmove(){if(1==allow){if(loca > 0 && loca <= 5) {loca--;}}}void lcd_addtime()//调时间加{uint dat ;if(1==allow)switch(loca){case 0 :{dat=year;dat++;year=dat;delay(100);break;}case 1 :{dat=time[1];dat++;if(dat>12)dat=1;time[1]=dat;delay(100);break; }case 2 :{dat=time[2];dat++;if(dat>30)dat=1;time[2]=dat;delay(100);break; }case 3 :{dat=time[3];dat++;if(dat>24)dat=1;time[3]=dat;delay(100);break; }case 4 :{dat=time[4];dat++;if(dat>60)dat=1;time[4]=dat;delay(100);break; }case 5 :{dat=time[5];dat++;if(dat>60)dat=1;time[5]=dat;delay(100);break; }}}void lcd_detime()//调时间减{int dat ;if(1==allow)switch(loca){case 0 :{dat=year;dat--;if(dat<0)dat=2000;year=dat;delay(100);break;}case 1 :{dat=time[1];dat--;if(dat<0)dat=12;time[1]=dat;delay(100);break; }case 2 :{dat=time[2];dat--;if(dat<0)dat=30;time[2]=dat;delay(100);break; }case 3 :{dat=time[3];dat--;if(dat<0)dat=23;time[3]=dat;delay(100);break; }case 4 :{dat=time[4];dat--;if(dat<0)dat=59;time[4]=dat;delay(100);break; }case 5 :{dat=time[5];dat--;if(dat<0)dat=59;time[5]=dat;delay(100);break;}}}void function(){uchar key=key_scan();switch(key){case 5 : lcd_lmove();break;case 6 : lcd_rmove();break;case 7 : lcd_addtime();break;case 8 : lcd_detime();break;case 9 : lcd_wcmd(0x0f);allow=1;break; //显示光标case 10 : lcd_wcmd(0x0c);allow=0;break; //关闭光标}}bit year_tell() //判断是否闰年是1 否0{if((year%4 == 0 && year%100 !=0) || year%400 == 0) return 1;else return 0;}uint count1(uint year , uchar mon , uchar day)//以下count1到count3都是为了计算对应的星期{uint m;switch(mon){case 1 : m=366-day; break;case 2 : m=335-day; break;case 3 : m=306-day; break;case 4 : m=275-day; break;case 5 : m=245-day; break;case 6 : m=214-day; break;case 7 : m=184-day; break;case 8 : m=153-day; break;case 9 : m=122-day; break;case 10 : m=92-day; break;case 11 : m=61-day; break;case 12 : m=31-day; break;default : ;}if(!(year%4 == 0 && year%100 != 0 || year%400 == 0)){if(mon<=2){m=m-1;}}return(m);}uint count2(uint year , uchar mon , uchar day){uint m;if(year%4 == 0 && year%100 != 0 || year%400 == 0){m=366-count1(year , mon , day);}else{m=365-count1(year , mon , day);}return m;}uint count3(uint year1 , uint year2){uint m=0;uchar i;uint n=year2-year1;for(i=1;i<n;i++){if((year1+i)%4 == 0 && (year1+i)%100 != 0 || (year1+i)%400 == 0) {m+=366;}else{m+=365;}}return m;}uchar week_tell()//判断对应的星期{uchar w;w=(count1(1901,1,7)+count2(year,time[1],time[2])+count3(1901,year)+1)%7; if(w!=0)return w;else return 7;}void timecount()//时间计算{if(time[5]>=60) //sec{time[5]=0;time[4]++;}if(time[4]>=60)//min{time[4]=0;time[3]++;}if(time[3]>=24)//hour{time[3]=0;time[2]++; //day}switch(time[1]) //mon{case 1 : if(time[2]>=31){time[2]=0; time[1]++;}case 2 :if(1==year_tell()){if(time[2]>29){time[2]=0; time[1]++;}}else{if(time[2]>28){time[2]=0; time[1]++;}}case 3 : if(time[2]>=31){time[2]=0; time[1]++;}case 4 : if(time[2]>=30){time[2]=0; time[1]++;}case 5 : if(time[2]>=31){time[2]=0; time[1]++;}case 6 : if(time[2]>=30){time[2]=0; time[1]++;} case 7 : if(time[2]>=31){time[2]=0; time[1]++;} case 8 : if(time[2]>=31){time[2]=0; time[1]++;} case 9 : if(time[2]>=30){time[2]=0; time[1]++;} case 10 : if(time[2]>=31){time[2]=0; time[1]++;} case 11 : if(time[2]>=30){time[2]=0; time[1]++;} case 12 : if(time[2]>=31){time[2]=0; time[1]++;} }if(time[1]>12){time[1]=0;year++;}}/*void lcd_clear(){lcd_wcmd(0x01);_nop_();}*/void lcd_display(uchar p)//液晶显示{uchar i,j;uchar str_com[14];str_com[13]=year/1000;str_com[12]=(year/100)%10;str_com[11]=(year%100)/10;str_com[10]=year%10;str_com[9]=time[1]/10;str_com[8]=time[1]%10;str_com[7]=time[2]/10;str_com[6]=time[2]%10;str_com[5]=time[3]/10;str_com[4]=time[3]%10;str_com[3]=time[4]/10;str_com[2]=time[4]%10;str_com[1]=time[5]/10;str_com[0]=time[5]%10;if(0==p)//非设定状态{lcd_pos(0x07);for(i=0,j=0;i<8;i++,j++){if(2==i || 5==i){lcd_wdat(':');j--;}elselcd_wdat(str_com[j]+48);}lcd_pos(0x49);for(i=6,j=6;i<16;i++,j++){if(8==i || 11==i){lcd_wdat('-');j--;}elselcd_wdat(str_com[j]+48);}delay(1 );lcd_wcmd(0x06);lcd_pos(0x4c);switch(week_tell()){case 1 : lcd_wstr("Mon");break;case 2 : lcd_wstr("Tue");break;case 3 : lcd_wstr("Wen");break;case 4 : lcd_wstr("Thu");break;case 5 : lcd_wstr("Fri");break;case 6 : lcd_wstr("Sat");break;case 7 : lcd_wstr("Sun");break;}delay(1 );lcd_wcmd(0x04);}else if(1==p)//时间设定状态{lcd_pos(0x07);lcd_wdat(str_com[0]+48);lcd_wdat(str_com[1]+48);switch(loca) //下面是让光标定在选择位,以便光标稳定的闪烁{case 0 : lcd_pos(0x43);break; case 1 : lcd_pos(0x46);break; case 2 : lcd_pos(0x49);break; case 3 : lcd_pos(0x01);break; case 4 : lcd_pos(0x04);break; case 5 : lcd_pos(0x07);break; }}}void lcd_init()//液晶初始化{delay(15);lcd_wcmd(0x38);delay(5);lcd_wcmd(0x38);delay(5);lcd_wcmd(0x38);while(lcd_bz());lcd_wcmd(0x0e);while(lcd_bz());lcd_wcmd(0x01);}void init(){TMOD=0x11;TH0=(65536-T)/256;TL0=(65536-T)%256;TH1=T1;TL1=T1;EA=1;TR0=1;ET0=1;TR1=0;ET1=1;}main(){init();lcd_init();while(1){// delay(3);// lcd_clear();delay(1 );lcd_wcmd(0x04);time_addsec();timecount();function();lcd_display(1);cout++;if(cout>=50){cout=0;lcd_display(0);}}}//程序到此结束,估计看了有点晕,不过没关系,程序是没有错的,定时很准,经调试在几个小时之后也达到分秒不差,晶振是12M。
1602显示秒表
/**********************BST-V51实验开发板例程************************* 平台:BST-V51 + Keil U3 + STC89C52* 名称:1602显示秒表******************************************************************* ** 描述:** ** 上电后液晶屏先显示信息,接着按下K3,定时开始,再次按下** ** K3暂停,第3次按下显示累积计时,第4次按下暂停计时,任何时候按下K4* * ** 计数清零。
** ** *************************************************************************/#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intuchar KeyCount=0;sbit K3 = P3^6;sbit K4 = P3^7;sbit BEEP = P2^3; //蜂鸣器uchar code cdis1[ ] = {" STOPWA TCH 0 "};uchar code cdis2[ ] = {" BST-V51 "};uchar code cdis3[ ] = {"TIME "};uchar code cdis4[ ] = {" BEGIN COUNT 1 "};uchar code cdis5[ ] = {" PAUSE COUNT 2 "};uchar code cdis6[ ] = {" BEGIN COUNT 3 "};uchar code cdis7[ ] = {" PAUSE COUNT 4 "};uchar code cdis8[ ] = {" "};sbit LCD_RS = P1^0;sbit LCD_RW = P1^1;sbit LCD_EN = P2^5;#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};uchar display[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00};uchar display2[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/********************************************************* 延时函数*********************************************************/void Delay(uint num)//延时函数{while( --num );}/********************************************************* 蜂鸣器响一声**********************************************************/ void beep(){unsigned char y;for (y=0;y<180;y++){BEEP=!BEEP; //BEEP取反Delay(70);}BEEP=1; //关闭蜂鸣器}/********************************************************* 延时函数1*********************************************************/ void delay1(int ms){unsigned char n;while(ms--){for(n = 0; n<250; n++){_nop_();_nop_();_nop_();_nop_();}}}/*********************************************************** ** 检查LCD忙状态* * lcd_busy为1时,忙,等待。
基于LCD1602显示屏设计一个具有复位功能的秒表
今日做一个简单1602应用案例—-设计一个秒表。
要求:具有秒表启动和复位功能按键,秒表计时时间实时显示在LCD1602。
1.系统的硬件电路原理图:2.系统的程序设计2.1 头文件、全局变量和函数的声明#include “LCD_1602.h”#includeunsigned char Disp_Buffer[10];//这个可以稍微设置大一点,不影响结果显示,显示的时候遇到字符串结束标志就结束//定义二个位变量,分别对应按键开始按键和停止复位按键sbit key_set=P3^2;sbit key_reset=P3^3;unsigned char TIme_count=0;unsigned int TIme_S=0;void TImer_inial();//定时器初始化void delay(unsigned int i);//延时函数void start();//启动秒表void stop();//停止复位秒表void second_cal_show();//秒的计算与显示2.2 主程序主程序主要完成显示屏的初始化和初始化显示、定时器的初始化,注意定时初始化的时候不启动。
启动有开始按键控制,不按下开始键不启动定时器。
初始化完了,在while循环中调用start();确定是否启动定时器,调用stop();根据按键状态确定是否停止秒表并复位;调用second_cal_show(); 进行秒的计算和显示。
void main(){InitLcd1602();LcdShowStr(0, 0, “Current : 0 S”);LcdShowStr(0, 1, “Last: 0 S”);TImer_inial();while(1){start();stop();second_cal_show();}}2.3 子程序2.3.1 初始定时器:定时器T0工作在模式1,定时器定时时间0.02秒。
void timer_inial(){TMOD = 0X01;//TH0=0XB8;//定时0.02sTL0=0X00;}2.3.2 延时函数:软件延时,主要用按键软件消抖//延时函数void delay(unsigned int i){unsigned int k;for(k=0;k2.3.3 启动函数:检测按键是否按下,按键如果按下则启动定时器T0,并从0开始计数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
源程序代码://名称:用1602LCD设计的秒表//说明:首先按下K1键时开始计时,自此按下时暂停,第三次按下时继续累积计时,再次按下时停止计时,K2键用于清零秒表。
//#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#define delayNOP ( ) ﹛_nop_( ); _nop_( ); _nop_( ); _nop_( );﹜//LCD控制函数void LCD_Initialize( );void LCD_Set_POS(uchar);void LCD_Write_Date(uchar);void Display_String(uchar﹡,uchar);sbit K1 = P1^0;sbit K2 = P1^1;sbit BEEP = P3^0;sbit LCD_RS = P2^0;sbit LCD_RW = P2^1;sbit LCD_EN = P2^2;uchar KeyCount = 0;uchar code msg1[] = ﹛〞Second Watch 0 〞﹜;uchar code msg2[] = ﹛〞>>>> 0 〞﹜;uchar code Prompts[] [16] ={﹛〞:: 1- - - - > 〞﹜,﹛〞:: 1- - - - > ::2 〞﹜,﹛〞:: 1 - >2 ::3- - > 〞﹜,﹛〞:: 1 - >2 ::3- - >4 〞﹜};// 计时缓冲与显示缓冲uchar Time_Buffer[] ={0,0,0,0};uchar LCD_Display_Buffer[]={〞00: 00: 00:00〞}; //// 蜂鸣器//void Beep ()﹛uchar i,j = 70;for (i = 0;i< 180;i++ )﹛while(--j);BEEP = ~BEEP;﹜BEEP = 0;﹜//// 延时//void DelayX(uint ms){uchar i;while(ms--) for (i= 0;i< 120;i++);﹜//// 显示计时//void Show_Second( ){uchar i;LCD_Set_POS(0x45); //设置LCD显示起点for(i = 3;i != 0xff ;i--);{//将两位整数的1/100s,秒,分,时转换为8位数字字符LCD_Display_Buffer[2﹡i+1] = Time_Buffer[i] / 10 + ˊ0 ˊ;LCD_Display_Buffer[2﹡i] = Time_Buffer[i] % 10 + ˊ0 ˊ;//在 = 3,2,1,0时分别显示时,分,秒,1/100sLCD_Writer_Date(LCD_Display_Buffer[2﹡i+1])LCD_Writer_Date(LCD_Display_Buffer[2﹡i])LCD_Writer_Date(ˊ: ˊ)}}//// Time0中断//Void Time0( ) interrupt 1 using 0{THO = -10000 / 256;TLO = -10000 % 256;Time_Buffer[0] ++if(Time_Buffer[0] == 100){Time_Buffer[0] = 0; Time_Buffer[1]++;}if(Time_Buffer[1] == 60) //秒{Time_Buffer[1] = 0; Time_Buffer[2]++;}if(Time_Buffer[2] == 60) //分{Time_Buffer[2] = 0; Time_Buffer[3]++;}if(Time_Buffer[3] == 24) //时Time_Buffer[3] = 0;}////主函数//void main( ){uchar i;IE = 0x82;TMOD = 0x01;THO = -10000 / 256;TLO = -10000 % 256;LCD_Initialize( );Display_String(msg1,0x00);Display_String(msg2,0x40);While(1){if(k1 == 0){DelayX(100);i = ++KeyCount;switch (i){case 1:case 3: TRO = 1;Display_String(Prompts[i-1],0);Break;case 2:case 4: TRO = 0;Display_String(Prompts[i-1],0);break;default:TRO = 0;break;}While (K1 == 0); // 等待释放K1键Beep( );}elseif(K2 == 0){TRO = 0;KeyCount = 0;for(i = 0;i < 4; i++)Time_Buffer [i] = 0; // 清零计数缓冲Display_String(msg1,0);Beep( );DelayX(100);while (K2 == 0); // 等待释放K2键}Show_Second( );}}//// 1602LCD显示驱动函数//#include 〈reg51.h〉#include 〈intrins.h〉#define uchar unsigned char#define uint unsigned int#define DellayNOP( )﹛_nop_( ); _nop_( ); _nop_( ); _nop_( );﹜sbit LCD_RS = P2^0;sbit LCD_RW = P2^1;sbit LCD_EN = P2^2;bit LCD_Busy_Check( );void LCD_Initialize( );void LCD_Set_POS(uchar);void LCD_Write_Command(uchar);void LCD_Write_ Date(uchar);//// 延时//void DelayMS(uint ms){uchar t;while(ms--) for (t =0;t < 120;t++);}//// LCD忙检查//bit LCD_Busy_Check( );{bit Rsult;LCD_RS = 0; LCD_RW = 1; LCD_EN = 1;DelayNOP( );Result = (bit)(p0 ﹠ 0x80);LCD_EN = 0return Result;}//// 向LCD写指令//void LCD_Write_Command(uchar cmd);{while(LCD_Busy_Check() );LCD_RS = 0; LCD_RW = 0; LCD_EN = 0;_nop_( ); _nop_( );pO = cmd; DelayNOP( );LCD_EN = 1;DelayNOP( );LCD_EN = 0;}//// 向LCD写数据//void LCD_Write_Date(uchar str);{while(LCD_Busy_Check() );LCD_RS = 1; LCD_RW = 0; LCD_EN = 0;pO = str; DelayNOP( ); LCD_EN = 1;DelayNOP( );LCD_EN = 0;}//// 初始化LCD//void LCD_Initialize( );{DelayMS(5); LCD_Write_Command(0x38);DelayMS(5); LCD_Write_Command(0x0c);DelayMS(5); LCD_Write_Command(0x06);DelayMS(5); LCD_Write_Command(0x01);DelayMS(5);}//// 设置显示位置//void LCD_Set_POS(uchar Poition){LCD_Write_Command(Position ︱ 0x80);}////显示函数,在LCD指定行上显示字符串//void Display_String(uchar﹡str,uchar LineNO) {uchar k;LCD_Set_POS(LineNO);for (k = 0;k < 16;k++) LCD_Write_Date(str[k]) }。