51单片机DS1302时钟LCD1602显示(可以按键设置时钟)

您所在的位置:网站首页 屏幕上显示秒表时钟怎么设置 51单片机DS1302时钟LCD1602显示(可以按键设置时钟)

51单片机DS1302时钟LCD1602显示(可以按键设置时钟)

2024-07-07 16:28| 来源: 网络整理| 查看: 265

DS1302实时时钟具有能计算2100年之前的秒、分、时、日、日期、星期、月、年的能力,还有闰年调整的能力。

图1:DS1302引脚示意图在这里插入图片描述 其中: X1、X2:32.768KHz晶振接入引脚。 GND:地。 :复位引脚,低电平有效,操作时高电平。 I/O:数据输入/输出引脚,具有三态功能。 SCLK:串行时钟输入引脚。 Vcc1:工作电源引脚。 Vcc2:备用电源引脚。 接入电池断电时提供1302电源

图2:控制寄存器 控制寄存器 图3:日历、时钟寄存器 在这里插入图片描述 在这里插入图片描述 图4:单字节读写时序 在这里插入图片描述 LCD时序图(写命令(RS=L):设置显示坐标,写数据(RS=H)) 在这里插入图片描述 LCD1602关键性的指令设置 1.清屏指令 在这里插入图片描述 功能: 清除液晶显示器,即将 DDRAM 的内容全部填入"空白"的 ASCII 码 20H; 光标归位,即将光标撤回液晶显示屏的左上方; 将地址计数器(AC)的值设为 0。

2.进入模式设置指令

在这里插入图片描述 功能 : 设定每次定入 1 位数据后光标的移位方向 , 并且设定每次写入的一个字符是否移动。参数设定的情况如下所示: 位名 设置 I/D 0=写入新数据后光标左移 1=写入新数据后光标右移 S 0=写入新数据后显示屏不移动 1=写入新数据后显示屏整体右 移 1 个字符

3:显示开关控制指令 在这里插入图片描述 功能:控制显示器开/关、光标显示/关闭以及光标是否闪烁。参数设定的情 况如下: 位名 设置 D 0=显示功能关 1=显示功能开 C 0=无光标 1=有光标 B 0=光标闪烁 1=光标不闪烁

4.功能设定指令 在这里插入图片描述 功能:设定数据总线位数、显示的行数及字型。参数设定的情况如下: 位名 设置 DL 0=数据总线为 4 位 1=数据总线为 8 位 N 0=显示 1 行 1=显示 2 行 F 0=5×7 点阵/每字符 1=5×10 点阵/每字符

5:显示字符地址

在这里插入图片描述 要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,例如第二行第一个字符的地址是 40H, 那么是否直接写入 40H 就可以将光标定位 在第二行第一个字符的位置呢?这样不行,因为写入显示地址时要求最高位 D7 恒定为高电平 1 所以实际写入的数据应该是 01000000B(40H) +10000000B(80H)=11000000B(C0H)。在 1602 中我们就用前 16 个就行了。第二行也一样用前 16 个地址。

/* 实验效果 :1602显示时钟,按K3进入时钟设置,按K1选择设置的时分秒日月,按K2选择 选择设置加1。 */ #include #include #define lcd1602data P0 typedef unsigned char u8; typedef unsigned int u16; sbit E=P2^7; //设置液晶端口 使能信号 sbit RW=P2^5; //读写选择 读:H/写:L sbit RS=P2^6; //数据命令选择 数据:H/命令:L sbit key1=P3^1; sbit key2=P3^0; sbit key3=P3^2; sbit SCLK=P3^6; //设置时钟端口 sbit IO=P3^4; sbit RST=P3^5; u16 read[]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; //设置秒分时日月周年读寄存器 u16 write[]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //设置秒分时日月周年写寄存器 u8 time[]={0x30,0x30,0x22,0x08,0x02,0x05,0x19}; //存放初始时间 u16 setmark,setplace; //setmark检测key3是否按下,setplace选择要调整的时间块。 void delay_ms(u16 n); void initConfiguration(); void lcdDisplay(); void lcdwrite_com(u8 datas); void lcdwrite_datas(u8 datas); void lcdinit(); void writebyte(u8 address,u8 datas); u8 readbyte(u8 address); void ds1302init(); void read_time(); void main() { u16 i; initConfiguration(); //初始化 lcdinit(); ds1302init(); while(1) { if(setmark==0) //时钟正常运作 { read_time(); } else //调整时间 { if(key1==0) { delay_ms(1); if(key1==0) { setplace++; //按下key1要调整的时间块加一 setplace%=7; } while(i9) //换成BCD码。 { time[setplace]=time[setplace]+6; } if((time[setplace]>=0x60)&&(setplace=0x24)&&(setplace==2)) //小时只能到23 { time[setplace]=0; } if((time[setplace]>=0x32)&&(setplace==3)) //日只能到31 { time[setplace]=0; } if((time[setplace]>=0x13)&&(setplace==4)) //月只能到12 { time[setplace]=0; } if((time[setplace]>=0x7)&&(setplace==5)) //周只能到7 { time[setplace]=1; } } while((i0;n--) { for(a=199;a>0;a--) { for(b=1;b>0;b--) { ; } } } } void initConfiguration() //初始化外部中断0 { EA=1; IT0=1; EX0=1; } void init0() interrupt 0 //按下key3时间保持不变 { delay_ms(10); if(key3==0) { setmark=~setmark; setplace=0; ds1302init(); } } void lcdDisplay() //显示函数 { lcdwrite_com(0x80+0x00); //确定写数据的位置 lcdwrite_datas('2'); lcdwrite_datas('0'); lcdwrite_datas('0'+time[6]/16); //写入年份的高位 lcdwrite_datas('0'+(time[6]&0x0f)); //低位 lcdwrite_datas('-'); lcdwrite_datas('0'+time[4]/16); lcdwrite_datas('0'+(time[4]&0x0f)); //里面的小括号很重要 lcdwrite_datas('-'); lcdwrite_datas('0'+time[3]/16); lcdwrite_datas('0'+(time[3]&0x0f)); lcdwrite_com(0x8c); lcdwrite_datas('0'+(time[5]&0x07)); lcdwrite_com(0xc0); //跳线帽Joe接vcc lcdwrite_datas('0'+time[2]/16); lcdwrite_datas('0'+(time[2]&0x0f)); lcdwrite_datas('-'); lcdwrite_datas('0'+time[1]/16); lcdwrite_datas('0'+(time[1]&0x0f)); lcdwrite_datas('-'); lcdwrite_datas('0'+time[0]/16); lcdwrite_datas('0'+(time[0]&0x0f)); } void lcdwrite_com(u8 datas) //lcd液晶写入指令操作 模拟时序 { E=0; RW=0; RS=0; lcd1602data=datas; delay_ms(1); E=1; //delay_ms(1); E=0; } void lcdwrite_datas(u8 datas) //lcd液晶写入数据操作 { E=0; RW=0; RS=1; lcd1602data=datas; delay_ms(1); //延时不能太长否则调整不灵敏 E=1; //delay_ms(1); E=0; } void lcdinit() //LCD液晶初始化 { lcdwrite_com(0x38); //8位总线,显示两行,5x7点阵 lcdwrite_com(0x0c); //开显示功能,无关标 lcdwrite_com(0x06); //光标右移,即数据依次右移 lcdwrite_com(0x01); //清屏 lcdwrite_com(0x80); //第一个数据位置 } void writebyte(u8 address,u8 datas) //在寄存器里写时间数据,模拟时序 { u8 i; RST=0; _nop_(); SCLK=0; _nop_(); RST=1; _nop_(); for(i=0;i>=1; SCLK=1; _nop_(); SCLK=0; _nop_(); } for(i=0;i>=1; SCLK=1; _nop_(); SCLK=0; _nop_(); } RST=0; } u8 readbyte(u8 address) //读寄存器里的时间数据 { u8 i,datas,dat; RST=0; //_nop_(); SCLK=0; //_nop_(); RST=1; //_nop_(); for(i=0;i>=1; SCLK=1; _nop_(); SCLK=0; _nop_(); } //_nop_(); for(i=0;i>1)|(dat


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3