基于51单片机 DS1302 LCD1602数字时钟显示

合集下载

DS1302+LCD1602显示程序

DS1302+LCD1602显示程序

/*头文件*/
#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define nop() _nop_()
sbit lcd_rs_port = P2^0; /*定义LCD控制端口*/
/****************************************************************
程序名称: LCD1602显示时间
函 数 名:W1302()
功 能:往DS1302写入数据
说 明:先写地址,后写命令/数据 (内部函数)
调 用:RTInputByte() , RTOutputByte()
入口参数:ucAddr: DS1302地址, ucData: 要写的数据
返 回 值:无
RTInputByte(ucAddr); /* 地址,命令 */
ucData = RTOutputByte(); /* 读1Byte数据 */
T_CLK = 1;
T_RST = 0;
return(ucData);
uchar data time_data_buff[7]={0x00,0x00,0x09,0x01,0x01,0x04,0x09};/*格式为: 秒 分 时 日 月 星期 年 */
uchar data lcd1602_line1[]={" 2000/00/00 000"};
uchar data lcd1602_line2[]={" 00:00:00 "};

用DS1302+LCD1602制作的时钟

用DS1302+LCD1602制作的时钟
void Read_RTC(void) //读取 日历
{
uchar i,*p;
p = RTC_RADD; //地址传递
for(i = 0 ; i < 7 ; i++) //分7次读取 秒分时日月周年
{
SJ[i] = Read_Ds1302(*p);
p++;
}
}
/*************************************************/
}
/*****************************************************/
/****LCD定位******************************************/
void LOCATE(uchar H , uchar L)
{
if(H == 1) //如果是第一行
{
LCD_RS = rs; //写指令/数据选择:低电平写指令,高电平写数据
LCD_RW = 0; //读写选择:低电平写,高电平读
LCD_E = 0; //关使能
LCD_DAT = c_d; //把指令/数据写入P1口
delay(5); //延时5ms
{
if(SDA)
temp |= 0x80; //每次传输低字节
SCK = 0;
temp>>=1; //右移一位
_nop_();
_nop_();
_nop_();
SCK = 1;
}
RST = 0;
_nop_(); //以下为DS1302复位的稳定时间

基于DS1302和LCD1602的可调数字钟

基于DS1302和LCD1602的可调数字钟

学习情境2-可调式数字钟之基于DS1302和LCD1602的可调数字钟☆点名,复习1、DS1302的引脚及其功能,以及DS1302与单片机的硬件连接?2、如何对DS1302读写数据,如何得到DS1302的时钟?☆新课讲授2.3 基于DS1302与LCD1602设计的可调数字钟上堂课程我们学会了使用DS1302,知道了如何在单片机系统中的连接,也详细的学习了如何得到DS1302的时钟,并且我们使用了16个数码管把年月日和时分秒实时地显示出来。

但数码管的显示毕竟有其自身的缺陷,现在在工业控制的各个环节,都使用液晶进行人机联系。

在日常生活中,我们对液晶显示器并不陌生。

液晶显示模块已作为很多电子产品的通用器件,如在计算器、万用表、电子表及很多家用电子产品中都可以看到,显示的主要是数字、专用符号和图形。

在单片机的人机交流界面中,一般的输出方式有以下几种:发光管、LED 数码管、液晶显示器。

发光管和LED数码管比较常用,软硬件都比较简单,在单片机系统中应用液晶显示器作为输出器件有以下几个优点:(1)显示质量高,由于液晶显示器每一个点在收到信号后就一直保持那种色彩和亮度,恒定发光,而不像阴极射线管显示器(CRT)那样需要不断刷新新亮点。

因此,液晶显示器画质高且不会闪烁。

(2)数字式接口,液晶显示器都是数字式的,和单片机系统的接口更加简单可靠,操作更加方便。

(3)体积小、重量轻,液晶显示器通过显示屏上的电极控制液晶分子状态来达到显示的目的,在重量上比相同显示面积的传统显示器要轻得多。

(4)功耗低,相对而言,液晶显示器的功耗主要消耗在其内部的电极和驱动IC上,因而耗电量比其它显示器要少得多。

2.3.1 LCD1602技术资料2.3.1.1 液晶显示简介1、液晶显示原理:液晶显示的原理是利用液晶的物理特性,通过电压对其显示区域进行控制,有电就有显示,这样即可以显示出图形。

液晶显示器具有厚度薄、适用于大规模集成电路直接驱动、易于实现全彩色显示的特点,目前已经被广泛应用在便携式电脑、数字摄像机、PDA移动通信工具等众多领域。

51单片机,DS1302时钟,1602显示,可调时钟剖析

51单片机,DS1302时钟,1602显示,可调时钟剖析

基于proteus的51单片机仿真实例八十一、实时时钟芯片DS1302应用实例1、DS1302引脚排列:如下图引脚说明:1)Vcc1:后备电源,VCC2:主电源。

在主电源关闭的情况下,也能保持时钟的连续运行。

DS1302由Vcc1或Vcc2两者中的较大者供电。

当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。

当Vcc2小于Vcc1时,DS1302由Vcc1供电。

2)X1、X2:振荡源,外接32.768kHz 晶振。

3)RST:复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。

RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。

当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。

如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。

上电运行时,在Vcc>2.0V之前,RST必须保持低电平。

只有在SCLK为低电平时,才能将RST置为高电平。

4)I/O为串行数据输入输出端(双向)。

5)SCLK为时钟输入端。

2、DS1302的控制字节DS1302 的控制字如下图所示。

控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。

3、数据输入输出(I/O)在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。

同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。

DS1302的寄存器DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见数据手册。

DS1302实时时钟模块,1602显示

DS1302实时时钟模块,1602显示

/******************* 说明:**************************将实时时钟数据通过LCD1602 显示基于51 单片机**************************************************/#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int uchar dis_time_buf[16]={0};//LCD1602 引脚定义// 采用8 位并行方式,DB0~DB7 连接至LCDDATA0~LCDDATA7sbit RS=P2A0;sbit RW=P2A1;sbit CS=P2A2;#define LCDDATA P0//DS1302 引脚定义sbit RST=P1A3;sbit IO=P1A2;sbit SCK=P1A1;//DS1302 地址定义#define ds1302_sec_add 0x80 // 秒数据地址#define ds1302_min_add 0x82 // 分数据地址#define ds1302_hr_add 0x84 // 时数据地址#define ds1302_date_add 0x86 // 日数据地址#define ds1302_month_add 0x88 // 月数据地址#define ds1302_day_add 0x8a // 星期数据地址#define ds1302_year_add 0x8c // 年数据地址#define ds1302_control_add 0x8e // 控制数据地址#define ds1302_charger_add 0x90#define ds1302_clkburst_add 0xbe// 初始时间定义uchar time_buf[8] = {0x20,0x10,0x06,0x01,0x23,0x59,0x55,0x02};// 初始时间2010年6月1号23 点59 分55 秒星期二// 功能:延时 1 毫秒// 入口参数:x// 出口参数:无//说明:当晶振为12M时,j<112 ;当晶振为11.0592M时,j<122void Delay_xms(uint x){uint i,j;for(i=0;i<x;i++)for(j=0;j<112;j++);// 功能:12us 延时//STC89C52为1T单片机,即1个时钟/机器周期,速度为AT89C52的12倍void Delay_xus(uint t){for(;t>0;t--){_nop_();}}//控制LCD写时序void LCD_en_write(void){CS=1;Delay_xus(20);CS=0;Delay_xus(20);}// 写指令函数void Write_Instruction(uchar command){RS=0;RW=0;CS=1;LCDDATA=command;LCD_en_write();// 写入指令数据}// 写数据函数void Write_Data(uchar Wdata){RS=1;RW=0;CS=1;LCDDATA=Wdata;LCD_en_write();// 写入数据}// 字符显示初始地址设置void LCD_SET_XY(uchar X,uchar Y){uchar address;if(Y==0) address=0x80+X;//Y=0, 表示在第一行显示,地址基数为0x80elseaddress=0xc0+X;//Y 非 0 时,表时在第二行显示,地址基数为 0xC0 Write_Instruction(address);// 写指令,设置显示初始地址}//在第X 行Y 列开始显示 Wdata 所对应的单个字符 void LCD_write_char(uchar X,uchar Y,uchar Wdata){LCD_SET_XY(X,Y)写 地址Write_Data(Wdata);// 写入当前字符并显示}// 清屏函数 void LCD_clear(void){Write_Instruction(0x01); Delay_xms(5);}// 显示屏初始化函数 void LCD_init(void){Write_Instruction(0x38); // 8bit interface,2line,5*7dotsDelay_xms(5);Write_Instruction(0x38); Delay_xms(5);Write_Instruction(0x38);Write_Instruction(0x08); //关显示,不显光标,光标不闪烁 Write_Instruction(0x01); //清屏 Delay_xms(5);//Write_Instruction(0x05); //Write_Instruction(0x06);//Write_Instruction(0x07);Delay_xms(5); // 写一字符,整屏右移 // 写一字符,整屏显示不移动// 写一字符,整屏左移//Write_Instruction(0x0B); Write_Instruction(0x0C);//Write_Instruction(0x0D); //Write_Instruction(0x0E); //Write_Instruction(0x0F); } //DS1302 初始化函数 void ds1302_init(void){Write_Instruction(0x04); // 写一字符,整屏显示不移动 // 关闭显示(不显示字符,只有背光亮) // 开显示,光标、闪烁都关闭// 开显示,不显示光标,但光标闪烁 // 开显示,显示光标,但光标不闪烁}//向DS1302写入一字节数据void ds1302_write_byte(uchar addr, uchar d){uchar i; RST=1;// 启动 DS1302 总线// 写入目标地址: addraddr = addr & 0xFE; // 最低位置零,寄存器 0 位为 0 时写,为 1 时读 for (i = 0; i < 8; i ++) {if (addr & 0x01) {IO=1;}else {IO=0;}SCK=1; //产生时钟 SCK=0;addr = addr >> 1;}// 写入数据: dfor (i = 0; i < 8; i ++) {if (d & 0x01) {IO=1;}else {IO=0;}SCK=1; // 产生时钟 SCK=0; d = d >> 1;}RST=O;〃停止 DS1302 总线}//从DS1302读出一字节数据uchar ds1302_read_byte(uchar addr) {uchar i,temp; RST=1;// 启动 DS1302 总线// 写入目标地址: addr addr = addr | 0x01;// 最低位置高,寄存器 0 位为 0 时写,为 1 时读for (i = 0; i < 8; i ++) {RST=0; SCK=0;//RST 脚置低 //SCK 脚置低if (addr & 0x01) { IO=1;}else { IO=0;}SCK=1;SCK=0;addr = addr >> 1;}// 输出数据:tempfor (i = 0; i < 8; i ++) { temp = temp >> 1; if (IO) {temp |= 0x80;}else {temp &= 0x7F; }SCK=1;SCK=0;}RST=0;//停止DS1302 总线return temp;}//向DS302写入时钟数据void ds1302_write_time(void) {ds1302_write_byte(ds1302_control_add,0x00); // 关闭写保护ds1302_write_byte(ds1302_sec_add,0x80); // 暂停时钟//ds1302_write_byte(ds1302_charger_add,0xa9); // 涓流充电ds1302_write_byte(ds1302_year_add,time_buf[1]); // 年ds1302_write_byte(ds1302_month_add,time_buf[2]); //月ds1302_write_byte(ds1302_date_add,time_buf[3]); // 日ds1302_write_byte(ds1302_hr_add,time_buf[4]); // 时ds1302_write_byte(ds1302_min_add,time_buf[5]); // 分ds1302_write_byte(ds1302_sec_add,time_buf[6]); // 秒ds1302_write_byte(ds1302_day_add,time_buf[7]); // 周ds1302_write_byte(ds1302_control_add,0x80); //打开写保护}//从DS302读出时钟数据void ds1302_read_time(void){time_buf[1]=ds1302_read_byte(ds1302_year_add); // 年time_buf[2]=ds1302_read_byte(ds1302_month_add); // 月time_buf[3]=ds1302_read_byte(ds1302_date_add); // 日time_buf[4]=ds1302_read_byte(ds1302_hr_add); // 时time_buf[5]=ds1302_read_byte(ds1302_min_add); // 分time_buf[6]=(ds1302_read_byte(ds1302_sec_add))&0x7f;// 秒,屏蔽秒的第7 位,避免超出59time_buf[7]=ds1302_read_byte(ds1302_day_add); // 周}void Display(void){LCD_write_char(3,0,dis_time_buf[0]+'0');LCD_write_char(4,0,dis_time_buf[1]+'0');LCD_write_char(5,0,dis_time_buf[2]+'0');LCD_write_char(6,0,dis_time_buf[3]+'0');LCD_write_char(7,0,'/');LCD_write_char(8,0,dis_time_buf[4]+'0');LCD_write_char(9,0,dis_time_buf[5]+'0');LCD_write_char(10,0,'/');LCD_write_char(11,0,dis_time_buf[6]+'0');LCD_write_char(12,0,dis_time_buf[7]+'0');LCD_write_char(15,0,dis_time_buf[14]+'0'); // 第 2 行显示LCD_write_char(3,1,dis_time_buf[8]+'0');LCD_write_char(4,1,dis_time_buf[9]+'0');LCD_write_char(5,1,':');LCD_write_char(6,1,dis_time_buf[10]+'0');LCD_write_char(7,1,dis_time_buf[11]+'0');LCD_write_char(8,1,':');LCD_write_char(9,1,dis_time_buf[12]+'0');LCD_write_char(10,1,dis_time_buf[13]+'0');}// 定时器中断函数void Timer2() interrupt 5// 定时器 2 是 5 号中断{static uchar t;TF2=0;t++;if(t==4) // 间隔200ms(50ms*4) 读取一次时间{t=0;ds1302_read_time(); // 读取时间dis_time_buf[0]=(time_buf[0]>>4); // 年dis_time_buf[1]=(time_buf[0]&0x0f);dis_time_buf[2]=(time_buf[1]>>4);dis_time_buf[3]=(time_buf[1]&0x0f);dis_time_buf[4]=(time_buf[2]>>4); // 月dis_time_buf[5]=(time_buf[2]&0x0f);dis_time_buf[6]=(time_buf[3]>>4); // 日dis_time_buf[7]=(time_buf[3]&0x0f);dis_time_buf[14]=(time_buf[7]&0x07); // 星期// 第 2 行显示dis_time_buf[8]=(time_buf[4]>>4); // 时dis_time_buf[9]=(time_buf[4]&0x0f);dis_time_buf[10]=(time_buf[5]>>4); // 分dis_time_buf[11]=(time_buf[5]&0x0f);dis_time_buf[12]=(time_buf[6]>>4); // 秒dis_time_buf[13]=(time_buf[6]&0x0f);}}// 定时器 2 初始化void Init_timer2(void){RCAP2H=0x3c;〃赋T2初始值0x3cb0,溢出20次为1秒,每次溢出时间为50ms RCAP2L=0xb0;TR2=1; //启动定时器 2ET2=1; // 打开定时器 2 中断EA=1; // 打开总中断}// 主函数void main(void){Delay_xms(50);// 等待系统稳定LCD_init(); //LCD 初始化LCD_clear(); // 清屏ds1302_init(); //DS1302 初始化Delay_xms(10);ds1302_write_time(); // 写入初始值Init_timer2(); // 定时器 2 初始化while(1){Display();}。

基于LCD1602和DS1302的时间显示程序

基于LCD1602和DS1302的时间显示程序

/*========================================================== ==使用1602液晶显示DS1302+S51时钟+温度显示zhaojun 2007/06/29=========================================================== ===声明:1. 1602驱动程序照搬明皓的,非常好用2. DS1302驱动程序是参考网友修改而来NS1602R(16*2)模拟口线接线方式连接线图:---------------------------------------------------| LCM-----51 | LCM-----51|LCM------51 || ----------------------------------------------- || DB0-----P0.0 | DB4-----P0.4 | RS-------P2.0 || DB1-----P0.1 | DB5-----P0.5 | RW-------P2.1 || DB2-----P0.2 | DB6-----P0.6 | E--------P2.2 || DB3-----P0.3 | DB7-----P0.7 | VLCD接1K电阻到GND |---------------------------------------------------DS1302 接线图Vcc2 CLK I/O /RST| | | |---------------| 8 7 6 5 || DS1302 || || 1 2 3 4 |---------------| | | |VCC1 GND1. 脚接+5V 2,3. 脚32768HZ晶振4. 脚接地5. 脚接S51的P1.2 6. 脚接S51的P1.1 7. 接S51的P1.08. 脚接后备电源,可以接老计算机主板上的3.6V电池,也可以通过二级管隔离接一个大容量电解电容电压在2.5V以上即可维持按键说明:1. 共三个键,低电平有效2. P1.4 和P1.5 同时按:初始化3. P1.6 端口按键:选择要调整的项目4. P1.5 端口按键:增加;P1.4端口按键:减少[注:AT89S51使用12M晶振]源代码:=================定义与申明=========================================================== ==*/#include "regx51.h"#include "string.h"#include "intrins.h"#define uchar unsigned char#define uint unsigned inttypedef unsigned char byte;typedef unsigned int word;//*********** 1602引脚定义引脚#define LCM_RS P2_0 // 数据/命令选择信号#define LCM_RW P2_1 // 读/写选择信号#define LCM_E P2_2 // 使能信号//*********** DS1302 时间显示定义部分sbit T_CLK=P1^0; //串行时钟输入sbit T_IO =P1^1; //串行数据端口sbit T_RST=P1^2; //复位端口//*********** 18B20温度显示定义部分sbit DQ=P3^3; //18B20 接P33口sbit ACC0=ACC^0;sbit ACC7=ACC^7;#define LCM_Data P0 //显示数据端口#define Busy 0x80 //用于检测LCM状态字中的Busy标识uchar id,timecount; //全局变量bit flag,sflag; //flag是时钟冒号闪烁标志,sflag是温度负号显示标志bit sec,min,hour,year,mon,day,weekk; //闪烁标志位//*********************函数申明void Disp_line1(void); // 显示屏幕第一行void Disp_line2(void); // 显示屏幕第二行void id_case1_key(); // id为1时的下一级选择void Set(uchar,uchar); // 根据选择调整相应项目void RTInputByte(uchar); /* 输入1Byte */uchar RTOutputByte(void); /* 输出1Byte */void W1302(uchar, uchar); // 向DS1302写入一个字节uchar R1302(uchar); // 从DS1302读出一个字节void Set1302(uchar * ); // 设置时间//******* 1602LCD驱动********************************************************** void WriteDataLCM(uchar WDLCM); //写数据void WriteCommandLCM(uchar WCLCM,BuysC); //写指令uchar ReadStatusLCM(void); //读状态void LCMInit(void); //LCM初始化void DisplayOneChar(uchar X, uchar Y, uchar DData); //按指定位置显示一个字符void DisplayListChar(uchar X, uchar Y, uchar code *DData); //按指定位置显示一串字符void Delay5Ms(void); //5ms延时void Delay400Ms(void); //400ms延时Read_Temperature(char,char);//温度显示void mychar(void); //显示自定义字符void adjust_res(char res); //res 分别等于0x1f, 0x3f, 0x5f 温度读数分辨率分别对应// 0.5, 0.25, 0.125//初始化后设置为:07年07月04日星期3 12点00分00秒// 12:00:00 XX. C// 07/07/04 Week.3unsigned char inittime[7]={0x00,0x00,0x12,0x04,0x07,0x03,0x07};// 秒分钟小时日月星期年uchar code week[]={"Week."};//星期显示//========================= 主函数======================================================= /*****************************************************函数名:main()功能:主函数说明:入口参数:无返回值:无*****************************************************/void main(void){Delay400Ms(); //启动等待,等LCM讲入工作状态LCMInit(); //LCM初始化Delay5Ms(); //延时片刻(可不要)mychar(); //显示自定义字符TMOD=0x01; //选择定时模式TH0=(65535-50000)/256;//取定时初值TL0=(65535-50000)%256;EA=1; //开中断TR0=1;ET0=1;W1302(0x90,0xa5); //打开充电二级管一个二级管串联一个2K电阻W1302(0x8e,0x80); //写保护,禁止写操作adjust_res(0x5f); //调整18B20的分辨率0x1f:0.5; 0x3f:0.25; 0x5f:0.125 while(1){if ((P1_4|P1_5)==0) // 初始化同时按下P1_4、P1_5{Delay5Ms(); // 适当延时,消除抖动if ((P1_4|P1_5)==0) Set1302(inittime); // 显示初始值}if (P1_6==0) // 设置和选择项目键{Delay5Ms(); // 适当延时,消除抖动if(P1_6==0){id++;if(id>7) id=0;} // 7个可调节项目循环调节while(P1_6==0);}switch(id) // 跳转到对应的项目进行设置{case 0:sec=0;Disp_line1(); Disp_line2();break;case 1: //调节年year=1;//设置年闪烁标志位Disp_line1(); Disp_line2();id_case1_key();break;case 2: //调节月year=0;mon=1;//设置月闪烁标志位Disp_line1(); Disp_line2();id_case1_key();break;case 3: //调节日mon=0;day=1;//设置日闪烁标志位Disp_line1(); Disp_line2();id_case1_key();break;case 4: //调节星期day=0;weekk=1;//设置星期闪烁标志位Disp_line1(); Disp_line2();id_case1_key();break;case 5: //调节小时weekk=0;hour=1;//设置小时闪烁标志位Disp_line1(); Disp_line2();id_case1_key();break;case 6: //调节分钟hour=0;min=1;//设置分钟闪烁标志位Disp_line1(); Disp_line2();id_case1_key();break;case 7: //调节秒min=0;sec=1;//设置秒钟闪烁标志位Disp_line1(); Disp_line2();id_case1_key();break;}}}//================================== 定时中断============================================= /*****************************************************函数名:void t0()功能:时间工作时,冒号闪烁说明:T0中断入口,方式1入口参数:无返回值:无*****************************************************/void t0(void) interrupt 1 using 0{TH0=(65535-50000)/256; //取50ms定时初值TL0=(65535-50000)%256;timecount++;if(timecount>9){timecount=0; //计时到,从先开始flag=~flag; //标志位取反}}//==================================== 项目设置=========================================== /*****************************************************函数名:void id_case1_key()功能:项目设置加减控制说明:P1.5和P1.4 <==> +和-入口参数:无返回值:无*****************************************************/ //id为1时的下一级选择void id_case1_key(){if (P1_5==0) //P1_5有按下,则数值增加(+){Delay5Ms(); //适当延时,消除抖动if(P1_5==0) Set(id,0); //根据选择调整相应项目if(id!=7) while(P1_5==0);}if (P1_4==0) //P1_4有按下,则数值减少(-){Delay5Ms(); //适当延时,消除抖动if(P1_4==0) Set(id,1); //根据选择调整相应项目if(id!=7) while(P1_4==0);}}/***************************************************** 函数名:void Set()功能:项目设置说明:sel_1=0时,数值加;sel_1=1时,数值减入口参数:sel和sel_1返回值:无*****************************************************/ //根据选择调整相应项目并写入DS1302void Set(uchar sel,uchar sel_1){signed char address,item;signed char max,mini;//偶数指令是写,奇数指令是读//最大值与最小值限定if(sel==7) {address=0x80; max=00;mini=0;} //秒if(sel==6) {address=0x82; max=59;mini=0;} //分钟if(sel==5) {address=0x84; max=23;mini=0;} //小时if(sel==3) {address=0x86; max=31;mini=1;} //日if(sel==2) {address=0x88; max=12;mini=1;} //月if(sel==1) {address=0x8c; max=99;mini=0;} //年if(sel==4) {address=0x8a; max=07;mini=1;} //星期//先从1302中读出数据,把数据转换成十进制进行加减设置;后从先转换回来写入1302中item=R1302(address+1)/16*10+R1302(address+1)%16;//从1302中读出1字节,再转换成十进制if (sel_1==0) item++; else item--; //sel_1=0则加,sel_1=1则减if(item>max) item=mini; //大于最大值,则赋最小值(循环)if(item<mini) item=max; //小于最小值,则赋最大值(循环)W1302(0x8e,0x00); //允许写操作W1302(address,item/10*16+item%10);//把调节好的十进制数据转换成十六进制后写入1302中W1302(0x8e,0x80); //写保护,禁止写操作}//========================================================== =============================/*****************************************************函数名:void Disp_line1()功能:显示时间和温度(XX:XX:XX XX.X C)说明:第一行显示数据处理入口参数:无返回值:无*****************************************************///屏幕显示第一行: 时间和温度显示void Disp_line1(void){Read_Temperature(10,0); //温度显示//冒号闪烁if(flag==0){DisplayOneChar(3,0,0x3a); DisplayOneChar(6,0,0x3a);} else{DisplayOneChar(3,0,0x20); DisplayOneChar(6,0,0x20);}if(sec==1) //秒闪烁标志位{if(flag==1){DisplayOneChar(7,0,R1302(0x81)/16+0x30); //显示秒十位DisplayOneChar(8,0,R1302(0x81)%16+0x30); //显示秒个位}else{DisplayOneChar(7,0,0x20); //显示秒十位DisplayOneChar(8,0,0x20); //显示秒个位}}else{DisplayOneChar(7,0,R1302(0x81)/16+0x30); //显示秒十位DisplayOneChar(8,0,R1302(0x81)%16+0x30); //显示秒个位}if(min==1) //分钟闪烁标志位{if(flag==1){DisplayOneChar(4,0,R1302(0x83)/16+0x30); //显示分钟十位DisplayOneChar(5,0,R1302(0x83)%16+0x30); //显示分钟个位}else{DisplayOneChar(4,0,0x20); //显示分钟十位DisplayOneChar(5,0,0x20); //显示分钟个位}}else{DisplayOneChar(4,0,R1302(0x83)/16+0x30); //显示分钟十位DisplayOneChar(5,0,R1302(0x83)%16+0x30); //显示分钟个位}if(hour==1) //小时闪烁标志位{if(flag==1){DisplayOneChar(1,0,R1302(0x85)/16+0x30);//显示小时十位DisplayOneChar(2,0,R1302(0x85)%16+0x30);//显示小时个位}else{DisplayOneChar(1,0,0x20); //显示小时十位DisplayOneChar(2,0,0x20); //显示小时个位}}else{DisplayOneChar(1,0,R1302(0x85)/16+0x30);//显示小时十位DisplayOneChar(2,0,R1302(0x85)%16+0x30);//显示小时个位}}/*****************************************************函数名:void Disp_line2()功能:显示日期和星期(XX/XX/XX Week.X)说明:第二行显示数据处理入口参数:无返回值:无*****************************************************/// 屏幕显示第二行日期和星期void Disp_line2(void){DisplayOneChar(3,1,0x2f); //显示固定字符DisplayOneChar(6,1,0x2f);DisplayListChar(10,1,week);if(year==1) //年闪烁标志位{if(flag==1){DisplayOneChar(1,1,R1302(0x8d)/16+0x30);//显示年十位DisplayOneChar(2,1,R1302(0x8d)%16+0x30);//显示年个位}else{DisplayOneChar(1,1,0x20); //显示年十位DisplayOneChar(2,1,0x20); //显示年个位}}else{DisplayOneChar(1,1,R1302(0x8d)/16+0x30);//显示年十位DisplayOneChar(2,1,R1302(0x8d)%16+0x30);//显示年个位}if(mon==1) //月闪烁标志位{if(flag==1){DisplayOneChar(4,1,R1302(0x89)/16+0x30);//显示月十位DisplayOneChar(5,1,R1302(0x89)%16+0x30);//显示月个位}else{DisplayOneChar(4,1,0x20); //显示月十位DisplayOneChar(5,1,0x20); //显示月个位}}{DisplayOneChar(4,1,R1302(0x89)/16+0x30);//显示月十位DisplayOneChar(5,1,R1302(0x89)%16+0x30);//显示月个位}if(day==1) //日闪烁标志位{if(flag==1){DisplayOneChar(7,1,R1302(0x87)/16+0x30);//显示日十位DisplayOneChar(8,1,R1302(0x87)%16+0x30);//显示日个位}else{DisplayOneChar(7,1,0x20); //显示日十位DisplayOneChar(8,1,0x20); //显示日个位}}else{DisplayOneChar(7,1,R1302(0x87)/16+0x30);//显示日十位DisplayOneChar(8,1,R1302(0x87)%16+0x30);//显示日个位}if(weekk==1) //星期闪烁标志位{if(flag==1){DisplayOneChar(15,1,R1302(0x8b)%16+0x30);//显示星期}else{DisplayOneChar(15,1,0x20); //显示星期}}{DisplayOneChar(15,1,R1302(0x8b)%16+0x30);//显示星期}}//================================ LCM1602控制部分=======================================/*****************************************************函数名:void WriteDataLCM()功能:向LCM1602中写入数据说明:将形参WDLCM中的数据写入LCM中入口参数:WDLCM返回值:无*****************************************************///写数据void WriteDataLCM(uchar WDLCM){ReadStatusLCM(); //检测忙LCM_Data = WDLCM;//写入数据到LCMLCM_RS = 1;LCM_RW = 0;LCM_E = 0; //若晶振速度太高可以在这后加小的延时LCM_E = 0; //延时LCM_E = 1;}/*****************************************************函数名:void WriteCommandLCM()功能:向LCM1602中写入指令说明:向LCM中写入指令;如果BuysC=0时,忽略忙检测,如果BuysC=1时,不忽略忙检测入口参数:WCLCM,BuysC返回值:无*****************************************************///写指令void WriteCommandLCM(uchar WCLCM,BuysC) //BuysC为0时忽略忙检测{if (BuysC) ReadStatusLCM(); //根据需要检测忙LCM_Data = WCLCM; //写入指令LCM_RS = 0;LCM_RW = 0;LCM_E = 0;LCM_E = 0;LCM_E = 1;}/*****************************************************函数名:uchar ReadStatusLCM()功能:读状态说明:判断LCM的工作状态;也可以不用此函数,用一段延时程序代替入口参数:无返回值:LCM_Data*****************************************************///读状态uchar ReadStatusLCM(void){LCM_Data = 0xFF; //LCM数据口先置1LCM_RS = 0;LCM_RW = 1;LCM_E = 0;LCM_E = 0;LCM_E = 1;while (LCM_Data & Busy); //检测忙信号.如果忙,则不执行return(LCM_Data);//不忙返回读取数据}/*****************************************************函数名:void LCMInit()功能:初始化LCM1602说明:LCM在工作前先要对显示屏初始化,否则模块无法正常工作入口参数:无返回值:五*****************************************************///LCM初始化void LCMInit(void){LCM_Data = 0;WriteCommandLCM(0x38,0); // 三次显示模式设置,不检测忙信号Delay5Ms();WriteCommandLCM(0x38,0); // 0x38指令表示:8位数据显示模式,俩行多显示Delay5Ms();WriteCommandLCM(0x38,0);Delay5Ms();WriteCommandLCM(0x38,1); // 显示模式设置,开始要求每次检测忙信号WriteCommandLCM(0x08,1); // 关闭显示WriteCommandLCM(0x01,1); // 显示清屏WriteCommandLCM(0x06,1); // 显示光标移动设置WriteCommandLCM(0x0C,1); // 显示开及光标设置}/*****************************************************函数名:void DisplayOneChar()功能:按指定坐标中写入数据说明:X-横坐标,Y-纵坐标入口参数:X,Y,DData返回值:*****************************************************///按指定位置显示一个字符void DisplayOneChar(uchar X, uchar Y, uchar DData){Y &= 0x01;X &= 0x0F; //限制X不能大于15,Y不能大于1if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;X |= 0x80; //算出指令码WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码WriteDataLCM(DData);}/*****************************************************函数名:void DisplayListChar()功能:向指定坐标中写入字符串说明:X-横坐标,Y-纵坐标入口参数:X,Y,*DData返回值:*****************************************************///按指定位置显示一串字符***原来的遇到空格0x20就不显示***void DisplayListChar(uchar X, uchar Y, uchar code *DData){uchar ListLength,j;ListLength = strlen(DData);//strlen:读取字符串的长度Y &= 0x1;X &= 0xF; //限制X不能大于15,Y不能大于1if (X <= 0xF) //X坐标应小于0xF{for(j=0;j<ListLength;j++){DisplayOneChar(X, Y, DData[j]); //显示单个字符X++;//横坐标加1,纵坐标不变}}}//=================================== 自定义字符==========================================/*****************************************************函数名:void mychar()功能:自定义字符--CGRAM说明:LCM1602字符库中没有温度符号,自定义温度符号入口参数:无返回值:无定义形式:1602中定义CGRAM的形式如下:---------------------------------------------------------------------------| CGRAM地址设置| 自定义的代码|| DB7 DB6 | DB5 DB4 DB3 | DB2 DB1 DB0 | DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 || 0 1 | 0 0 0 | X X X | 0 0 0 0 * 0 0 0 || 0 1 | 0 0 1 | X X X | 0 0 0 0 * 0 0 1 || ... | ... | ... | ... ... || 0 1 | 1 1 0 | X X X | 0 0 0 0 * 1 1 0 || 0 1 | 1 1 1 | X X X | 0 0 0 0 * 1 1 1 |---------------------------------------------------------------------------1. 1602共能定义8个5x8字符;2. CGRAM地址设置: X X X--DB2 DB1 DB0对应写入地址,1~8行;DB5 DB4 DB3对应自定义字符代码;DB7 DB6为指令码,不可变.3. 自定义的代码: 高4位DB7 DB6 DB5 DB4为0000时它的低3位DB2 DB1 DB0对应于第1-8个,DB3为无关项。

基于51单片机DS1302LCD1602数字时钟显示

基于51单片机DS1302LCD1602数字时钟显示
#include <reg51.h>
#include <intrins.h>
#include <string.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]="I LIKE MCU!";
sbit RS=P2^0;
dispaly_string(0x00,lcd_buffer1);
dispaly_string(0x40,lcd_buffer2);
}
}
delay(5);
}
void write_a_byte_tods1302(uchar x)
{
uchar i;
for(i=0;i<8;i++)
{
IO=x&0x01;
sclk=1;
sclk=0;
x=x>>1;
}
}
uchar get_a_byte_fromds1302()
{
uchar i,b=0x00;
for(i=0;i<8;i++)
uchar lcd_buffer2[]={"TIME 00:00:00 "};
uchar datetime[7];
void delay(uchar ms)
{
uchar i;
while(ms--)
for(i=0;i<120;i++);
}
//忙检测
uchar busy()
{
uchar test;
RW=1;
{

单片机时钟芯片DS1302在LCD1602上显示年月日时分秒

单片机时钟芯片DS1302在LCD1602上显示年月日时分秒

单片机设计实验内容摘要:单片机实验是通过Proteus仿真并且与Keil相结合使用控制单片机使其在仿真中完成一系列所设计的程序。

我们这个小组所做的实验是仿真一个数字时钟,通过DS1302这个芯片从计算机上读取时间信息,再由51单片机对数据进行处理、分配,将其输出在LCD1602上,实现简单的数字时钟的功能。

设计内容及要求:(1)根据设计课题的技术指标和给定条件,在教师指导下,能够独立而正确地进行方案论证和设计计算,要求概念清楚、方案合理、方法正确、步骤完整;(2)要求学生掌握单片机的设计内容、方法和步骤;(3)要求会查阅有关参考资料和手册等;(4)要求学会选择有关元件和参数;(5)要求学会绘制有关电路图和设计流程图;(6)要求学会编写设计说明书。

系统框图:硬件选择:1、AT89C51AT89C51是一种带4K字节FLASH存储器(FPEROM—Flash Programmable and Erasable Read Only Memory)的低电压、高性能CMOS 8位微处理器,俗称单片机。

AT89C2051是一种带2K字节闪存可编程可擦除只读存储器的单片机。

单片机的可擦除只读存储器可以反复擦除1000次。

该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。

由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,AT89C2051是它的一种精简版本。

AT89C51单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。

AT89C51外形及引脚排列主要特性:·与MCS-51 兼容·4K字节可编程FLASH存储器·寿命:1000写/擦循环·数据保留时间:10年·全静态工作:0Hz-24MHz·三级程序存储器锁定·128×8位内部RAM·32可编程I/O线·两个16位定时器/计数器·5个中断源·可编程串行通道·低功耗的闲置和掉电模式·片内振荡器和时钟电路特性概述:AT89C51 提供以下标准功能:4k 字节Flash 闪速存储器,128字节内部RAM,32 个I/O 口线,两个16位定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

#include <reg51.h>
#include <intrins.h>
#include <string.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]="I LIKE MCU!";
sbit RS=P2^0;
sbit RW=P2^1;
sbit EN=P2^2;
sbit IO=P1^0;
sbit sclk=P1^1;
sbit rst=P1^2;
uchar *week[]={"SUN","****","MON","TUS","WEN","THU","FRI","SAT"}; uchar lcd_buffer1[]={"DA TE 00-00-00 "};
uchar lcd_buffer2[]={"TIME 00:00:00 "};
uchar datetime[7];
void delay(uchar ms)
{
uchar i;
while(ms--)
for(i=0;i<120;i++);
}
//忙检测
uchar busy()
{
uchar test;
RW=1;
RS=0;
EN=1;
test=P0;
EN=0;
return test;
}
//写LCD命令
void writecmd(uchar cmd) {
while((busy()&0x80)==0x80); RS=0;
RW=0;
P0=cmd;
EN=1;
delay(5);
EN=0;
}
//发送数据
void writedata(uchar dat)
{
while((busy()&0x80)==0x80); RW=0;
RS=1;
P0=dat;
EN=1;
delay(5);
EN=0;
}
void init()
{
writecmd(0x38);
delay(5);
writecmd(0x01);
delay(5);
writecmd(0x06);
delay(5);
writecmd(0x0c);
delay(5);
}
void write_a_byte_tods1302(uchar x) {
uchar i;
for(i=0;i<8;i++)
{
IO=x&0x01;
sclk=1;
sclk=0;
x=x>>1;
}
}
uchar get_a_byte_fromds1302() {
uchar i,b=0x00;
for(i=0;i<8;i++)
{
b|= _crol_((uchar)IO,i);
sclk=1;
sclk=0;
}
return b/16*10+b%16;
}
uchar read_data(uchar addr)
{
uchar dat;
rst=0;sclk=0;rst=1;
write_a_byte_tods1302(addr);
dat=get_a_byte_fromds1302();
sclk=1;sclk=0;
return dat;
}
void gettime()
{
uchar i,addr=0x81;
for(i=0;i<8;i++)
{
datetime[i]=read_data(addr);
addr=addr+2;
}
void set_pos(uchar p)
{
writecmd(p|0x80);
}
void dispaly_string(uchar p,uchar *s)
{
uchar i;
set_pos(p);
for(i=0;i<16;i++)
{
writedata(s[i]);
delay(5);
}
}
void zhuanhuan(uchar d,uchar *a)
{
a[0]=d/10+'0';
a[1]=d%10+'0';
}
void main()
{
init();
while(1)
{
gettime();
zhuanhuan(datetime[6],lcd_buffer1+5);
zhuanhuan(datetime[4],lcd_buffer1+8);
zhuanhuan(datetime[3],lcd_buffer1+11);
strcpy(lcd_buffer1+13,week[datetime[5]]);
zhuanhuan(datetime[2],lcd_buffer2+5);
zhuanhuan(datetime[1],lcd_buffer2+8);
zhuanhuan(datetime[0],lcd_buffer2+11);
dispaly_string(0x00,lcd_buffer1);
dispaly_string(0x40,lcd_buffer2);
}
}。

相关文档
最新文档