LCD12864单片机电子万年历程序
- 格式:doc
- 大小:94.50 KB
- 文档页数:31
#include<reg52.H>#include<intrins.h>#include<math.h>////////////////////////////////////////DS18B20#define uchar unsigned char#define uint unsigned intsbit DQ = P1 ^ 0; // 定义DS18B20的单总线#define Lcd_Bus P0sbit LCD_RS=P2^7; //数据/命令选择sbit LCD_RW=P2^6; //读写控制sbit LCD_EN=P2^5; //片选信号#define LCD_DA TA P0 //8 bit数据线#define LOW 0#define HIGH 1//初始化指令#define CLEAR_SCREEN 0x01 //清屏指令:清屏且AC值为00H#define AC_INIT 0x02 //将AC设置为00H。
且游标移到原点位置#define CURSE_ADD 0x06 //设定游标移到方向及图像整体移动方向(默认游标右移,图像整体不动)#define FUN_MODE 0x30 //工作模式:8位基本指令集#define DISPLAY_ON 0x0c //显示开,显示游标,且游标位置反白#define DISPLAY_OFF 0x08 //显示关#define CURSE_DIR 0x14 //游标向右移动:AC=AC+1#define SET_CG_AC 0x40 //设置AC,范围为:00H~3FH#define SET_DD_AC 0x80#define FUN_MODEK 0x36 //扩展指令集,8位指令#define X1address 0x80 //上半屏X轴起始地址#define X2address 0x88 //下半屏X轴起始地址#define Y address 0x80 //Y轴起始地址#define Set_Column 0x40#define Set_Page 0xB8uchar code shu[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};uchar code xingqi[]="星期";uchar code hanzishu[]="一二三四五六日";unsigned char TempData = 0;double DS18B20Data;uint jiemian=0;//////////////////////////////////////////DS1302sbit DS1302_RST = P1^4;sbit DS1302_IO = P1^3;sbit DS1302_SCK = P1^2;unsigned char table[]={0X00,0X18,0X0c,0X15,0X06,0X01,0X0a};//0s 24min 12hour 14ri 5yue 5zhou 2010nianunsigned char data table1[7];//uchar code table2[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};uchar code shuzi[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,};unsigned char aa,bb;uchar miaoge,miaoshi,fenge,fenshi,shige,shishi,rige,rishi,yuege,yueshi,zhou,niange,nianshi;uchar shezhinum=0;//unsigned char shi,ge;////////////////////////////////////////////////键盘扫描sbit key_mnue = P3^7;sbit key_jia = P2^0;sbit key_jian = P2^1;sbit key_enter= P2^2;uchar key_number=0;//int nian,yue,ri,shi,fen;/////////////////////////////////////////////////红外sbit HW_IRQ = P3 ^ 2; // 定义38KHz一体化红外接收头与CPU的连接unsigned char DT;static unsigned char data IRCode[3],IRCON,IRCON2;//////////////////////////////////////////////////蜂鸣器sbit BEEP =P1^1;/****************************************************************************** *************** 函数名称:DS18B20_Delay()* 功能:DS18B20软件延时专用* 入口参数:count 延时参数,值越大,延时越长* 出口参数:无******************************************************************************* **************/void DS18B20_Delay(uint count) //延时函数{while(count--);}/****************************************************************************** *************** 函数名称:DS18B20_Init()* 功能:DS18B20初始化* 入口参数:无* 出口参数:返回值为1则初始化成功* 返回值为0则初始化失败******************************************************************************* **************/uchar DS18B20_Init(void){uchar x = 0;DQ = 1; // DQ复位DS18B20_Delay(8); // 稍做延时DQ = 0; // 单片机将DQ拉低DS18B20_Delay(80); // 精确延时,大于480usDQ = 1; // 拉高总线DS18B20_Delay(14); // 稍做延时后x = DQ; // 若x=0则初始化成功,若x=1则初始化失败DS18B20_Delay(20);return (~x);}/****************************************************************************** *************** 函数名称:DS18B20_Read1Byte()* 功能:从DS18B20读一个字节* 入口参数:无* 出口参数:从DS18B20读出的一个字节******************************************************************************* **************/uchar DS18B20_Read1Byte(void){uchar i = 0;uchar dat = 0;for(i=8;i>0;i--){DQ = 0; // 给脉冲信号dat >>= 1;DQ = 1; // 给脉冲信号if(DQ) dat |= 0x80;DS18B20_Delay(4);}return (dat);}/****************************************************************************** *************** 函数名称:DS18B20_Write1Byte()* 功能:向DS18B20写一个字节* 入口参数:dat 要写入DS18B20的一字节数据* 出口参数:无******************************************************************************* **************/void DS18B20_Write1Byte(uchar dat){uchar i = 0;for(i=8;i>0;i--){DQ = 0;DQ = dat&0x01;DS18B20_Delay(5);DQ = 1;dat>>=1;}}/****************************************************************************** *************** 函数名称:Read_Disp_Temperature()* 功能:读取并显示温度* 入口参数:无* 出口参数:无******************************************************************************* **************/double Read_Disp_Temperature(void){uint a = 0, b = 0, c = 0,d = 0,e = 0, t = 0;double tt = 0;DS18B20_Init();DS18B20_Write1Byte(0xCC); // 跳过读序号列号的操作DS18B20_Write1Byte(0x44); // 启动温度转换DS18B20_Init();DS18B20_Write1Byte(0xCC); // 跳过读序号列号的操作DS18B20_Write1Byte(0xBE); // 读取温度寄存器a = DS18B20_Read1Byte();b = DS18B20_Read1Byte();t = b;t <<= 8;t = t | a;//tt = t * 0.0625;return t;}//***************************************************************** //函数名称:delay(uint t)延时函数。
51单片机做的12864万年历这是我花了一个星期时间做的万年历;一开始是一些图片,后面是这个制作的C语言源程序;希望大家稀饭:Main.c#include "reg52.h"#include "macroconst.h"#include "keyscan.h"#include "screen.h"#include "18b20.h"#include "ds1302.h"#include "atao_12864.h"#include "24c02.h"idata unsigned char state1[1];unsigned char screennum=1;//屏幕号#define time_task_sec 200 //节拍200Hz#define clock 24000000 //晶振#define max_task 4 //最大任务数idata unsigned char task_delay[4];#define task_delay0 time_task_sec/1 //2赫兹18b20 #define task_delay1 time_task_sec/5 //10赫兹屏幕#define task_delay2 time_task_sec/3 //4赫兹1302 #define task_delay3 time_task_sec/20 //20赫兹键盘void init(){unsigned char i;init18b20();ds1302_init();initina1(); //---------------------------LCD字库初始化程序RdFromROM(state1,8,1);state[0]=state1[0]; //-------界面RdFromROM(state1,15,1);state[1]=state1[0];//------- 闹钟RdFromROM(state1,11,1);key_sound=state1[0];//-------按键音// state[2]=state1[2];// state[3]=state1[3];screennum=1;//------默认一号屏for(i=0;i<max_task;i++)//清除任务延时{task_delay[i]=0;}TMOD=0x11;EA=1;TH0=255-clock/time_task_sec/12/526;TL0=255-clock/time_task_sec/12%526;ET0=1;TR0=1;}void main(){init();while(1){ if(task_delay[0]==0){readtemp(); task_delay[0]=task_delay0;} if(task_delay[3]==0){MenuCheckKey();task_delay[3]=task_delay1;}if(task_delay[1]==0){screen_select(screennum);task_delay[1]=task_delay1;} if(task_delay[2]==0){ds1302_read_time(); task_delay[2]=task_delay0;} }}void timer0() interrupt 1{uchar i=0;TH0=255-clock/time_task_sec/12/526;TH1=255-clock/time_task_sec/12%526;for(i=0;i<max_task;i++)if(task_delay[i]) task_delay[i]--; // miao=21,fen=33,xiaomiao=94;if(ma_start==1){tt++;if(tt==8){tt=0;xiaomiao++;if(xiaomiao==99){xiaomiao=0;miao++;if(miao==60){miao=0;fen++;if(fen==99){fen=0;}}}}}}Screen.c:#include "reg52.h"#include "macroconst.h"#include "delay.h"#include "18b20.h"#include "atao_12864.h"#include "ds1302.h"#include "24c02.h"#include "festival.h"#include "keyscan.h"idata unsigned char miao=0,fen=78,xiaomiao=0,tt=0;idata unsigned char bai,shi,ge,shinian,genian,shiyue,geyue,shiri,geri,shishi,geshi,shifen,gefen,shimi ao,gemiao;idata unsigned char Number[4];unsigned char code mainmenu[]={" 主菜单""3.查询 4.温度""1.调时 2.秒表""5.设置 6.返回"};unsigned char code setmenu[]={" 设置""3.查温 4.按键""1.界面 2.闹铃""5.报时 6.返回"};void gettime(){shinian=(time_buf1[1]%100)/10;genian=(time_buf1[1]%100)%10;shiyue=(time_buf1[2])/10;geyue=(time_buf1[2])%10;shiri=(time_buf1[3])/10;geri=(time_buf1[3])%10;shishi=(time_buf1[4])/10;geshi=(time_buf1[4])%10;shifen=(time_buf1[5])/10;gefen=(time_buf1[5])%10;shimiao=(time_buf1[6])/10;gemiao=(time_buf1[6])%10;}void screen_select(uchar num){// initina1();gettime() ;if(num==1) //----------主界面{Lcd_Set_Post(1,0);TransferData(shinian+48,1);//----------------------年TransferData(genian+48,1);TransferData('/',1);TransferData(shiyue+48,1);//----------------------月TransferData(geyue+48,1);TransferData('/',1);TransferData(shiri+48,1);//----------------------日TransferData(geri+48,1);Lcd_Set_Post(1,4);if(state[1]==1)//----------------闹铃的状态图标{TransferData(' ',1);TransferData(14,1);}Lcd_Set_Post(1,5);if(key_sound==1){TransferData(13,1);}if(state[0]==0){Lcd_Set_Post(1,7); //----------------农历年nian(0);Lcd_Set_Post(2,0);//----------------------- 农历日月LCD_WRITE_CHAR("农历");Conversion(0,time_buf[1],time_buf[2],time_buf[3]);TransferData(month_moon/16+'0',1);TransferData(month_moon%16+'0',1);TransferData('/',1);TransferData(day_moon/16+'0',1);TransferData(day_moon%16+'0',1);}if(state[0]==1){Lcd_Set_Post(3,5);}else {Lcd_Set_Post(2,5);}LCD_WRITE_CHAR("星期");//----------------------星期if(time_buf1[7]==7) {LCD_WRITE_CHAR("日");}if(time_buf1[7]==6) {LCD_WRITE_CHAR("六");}if(time_buf1[7]==5) {LCD_WRITE_CHAR("五");}if(time_buf1[7]==4) {LCD_WRITE_CHAR("四");}if(time_buf1[7]==3) {LCD_WRITE_CHAR("三");}if(time_buf1[7]==2) {LCD_WRITE_CHAR("二");}if(time_buf1[7]==1) {LCD_WRITE_CHAR("一");}Lcd_Set_Post(3,0);TransferData(shishi+48,1);//----------------------时TransferData(geshi+48,1);TransferData(58,1);TransferData(shifen+48,1);//----------------------分TransferData(gefen+48,1);TransferData(58,1);TransferData(shimiao+48,1);//----------------------秒TransferData(gemiao+48,1);if(state[0]==0){bai=(temph/100); //---------------------------------温度shi=(temph%100)/10;ge=(temph%100)%10;Lcd_Set_Post(3,4);if(zerotemp==0){TransferData(' ',1);TransferData(' ',1);} Lcd_Set_Post(3,5);TransferData(shi+48,1);TransferData(ge+48,1);TransferData('.',1);TransferData(templ+48,1);TransferData(0xa1,1);TransferData(0xe6,1);Lcd_Set_Post(4,0);festival(time_buf[2],time_buf[3],time_buf[4]);//农历}}if(num==3)//----------主菜单{Lcd_Set_Post(1,0);//--------设置显示位置LCD_WRITE_CHAR(mainmenu);}if(num==4)//----------设置菜单{Lcd_Set_Post(1,0);//--------设置显示位置LCD_WRITE_CHAR(setmenu);}if(num==5)//----------时间设置{Lcd_Set_Post(1,2);//--------设置显示位置LCD_WRITE_CHAR("时间设置");Lcd_Set_Post(2,1);TransferData(shinian+48,1);//----------------------年TransferData(genian+48,1);LCD_WRITE_CHAR("年");TransferData(shiyue+48,1);//----------------------月TransferData(geyue+48,1);LCD_WRITE_CHAR("月");TransferData(shiri+48,1);//----------------------日TransferData(geri+48,1);LCD_WRITE_CHAR("日");TransferData(time_buf1[7]+48,1);//---------------星期Lcd_Set_Post(3,2);TransferData(shishi+48,1);//--------------------时TransferData(geshi+48,1);LCD_WRITE_CHAR("时");TransferData(shifen+48,1);//---------------------分TransferData(gefen+48,1);LCD_WRITE_CHAR("分");TransferData(shimiao+48,1);//--------------------秒TransferData(gemiao+48,1);}if(num==6)//----------秒表{uchar shi1,shi2,shi3,ge1,ge2,ge3;Lcd_Set_Post(1,3);//--------设置显示位置LCD_WRITE_CHAR("秒表");Lcd_Set_Post(3,2);shi1=fen/10;ge1=fen%10;TransferData(shi1+48,1);TransferData(ge1+48,1);TransferData(':',1);shi2=miao/10;ge2=miao%10;TransferData(shi2+48,1);TransferData(ge2+48,1);TransferData(':',1);shi3=xiaomiao/10;ge3=xiaomiao%10;TransferData(shi3+48,1);TransferData(ge3+48,1);}if(num==8){Lcd_Set_Post(1,2);//--------农历查询LCD_WRITE_CHAR("温度查询");Lcd_Set_Post(3,0);//--------农历查询LCD_WRITE_CHAR("最高温度"); TransferData(':',1);RdFromROM(Number,0,4);if(Number[3]==0){TransferData('-',1);}Lcd_Set_Post(3,5);TransferData(Number[0]+48,1); TransferData(Number[1]+48,1); TransferData('.',1);TransferData(Number[2]+48,1); TransferData(0xa1,1);TransferData(0xe6,1); Lcd_Set_Post(4,0);//--------农历查询LCD_WRITE_CHAR("最低温度"); TransferData(':',1);RdFromROM(Number,4,4);if(Number[3]==0){TransferData('-',1);}Lcd_Set_Post(4,5);TransferData(Number[0]+48,1); TransferData(Number[1]+48,1); TransferData('.',1);TransferData(Number[2]+48,1); TransferData(0xa1,1);TransferData(0xe6,1); }if(num==9)//----------界面菜单{Lcd_Set_Post(1,2);//--------设置显示位置LCD_WRITE_CHAR("界面选择");Lcd_Set_Post(2,0);TransferData(1+48,1);TransferData('.',1);LCD_WRITE_CHAR("多功能界面");Lcd_Set_Post(3,0);TransferData(2+48,1);TransferData('.',1);LCD_WRITE_CHAR("简洁界面");}。
摘要:介绍利用单片机控制液晶显示模块显示电子万年历,给出硬件设计电路,和软件编程设计,通过Proteus软件,对硬件电路和软件编程进行仿真,具有一定的实用价值。
关键词:单片机液晶显示模块C51编程液晶显示模块在各种测量仪器、测量装置、显示仪表等日用电子产品中的应用越来越广泛,并且对器件的测量精度和显示精度的要求也越来越高,尤其是对时间的测量不但要准确,而且需要读取数值更直观更方便。
本文介绍由单片机AT89C52和DS1302控制12864点阵液晶显示模块实现电子万年历的设计,并且用Proteus软件对整个电路进行模拟和仿真。
1系统构成本系统设计中使用的单片机为AT89C52,其内部是8位的CPU,8KB片内ROM以及256B的可使用的片内RAM,32根并行I/O接口,两个16位的定时/计数器,五个中断源,两个中断优先级的内部结构。
其中单片机的外围电路有复位电路,时钟电路。
其次还用到美国DALLAS公司推出的高性能、低功耗、带RAM 的实时时钟电路DS1302,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。
采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。
本系统里用12864LCD显示模块来显示万年历的年月日、星期及时间信息,该液晶模块使用KS0108控制器,5V电压驱动,带有背光,内置8192个16×16点阵,128个字符及64×128点阵显示RAM。
与外部CPU接口采用并行或者串行两种控制方式。
单片机在控制液晶显示模块的接口方式主要有两种方式,直接访问方式和间接访问方式,直接访问方式是把液晶显示模块作为存储器或I/O设备直接连接到单片机总线上。
而间接访问方式是把液晶显示模块作为终端与单片机的并行接口连接,而单片机通过对该并行接口的操作实现对液晶显示。
一般在进行液晶显示模块的控制时,采用间接访问的方式。
#include <reg51.h> // 该程序具有显示日期、月份、日期和时间功能#include<stdio.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned int#define sint signed int#define disp_off 0x3e //显示关#define disp_on 0x3f //显示开#define disp_x 0xb8 //页地址为0页#define disp_z 0xc0 //行地址为0行#define disp_y 0x40 //列地址为0列#define comm 0 //命令标志位#define dat1 1 //数据标志位#define data_ora P0 //液晶12864的数据端与单片机的P0相连sbit di =P2^0; //Data or Instrument Select,H:写数据,L:写指令sbit rw =P2^1; //Write or Read,H:read,L:writesbit e =P2^4; //读写使能sbit cs1=P2^2; //cs1=H,选择左半屏sbit cs2=P2^3; //cs2=H,选择右半屏sbit clk=P1^0; //8563 clksbit dat=P1^1; //8563 datauchar fen=0x42,miao=0x38,shi=0x17,riqi=0x02,//设置时间用yuefen=0x09,xingqi=0x00,nian=0x07,zhongduan;//设置时间用uchar code tabma[10][16]=//阴码点阵格式、取模方式为列行式、逆向取模(低位在前),//十六进制输出,中文16*16,英文8*16 宋体{//0(0) 1(1) 2(2) 3(3) 4(4) 5(5) 6(6) 7(7) 8(8) 9(9){0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00}, /*"0",0*/{0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00}, /*"1",1*/{0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00}, /*"2",2*/{0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00}, /*"3",3*/{0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00}, /*"4",4*/{0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00}, /*"5",5*/{0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00}, /*"6",6*/{0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00}, /*"7",7*/{0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00}, /*"8",8*/{0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00}, /*"9",9*/ };uchar code tab2ma[7][32]=// 日(0) 一(1) 二(2) 三(3) 四(4) 五(5) 六(6){{0x00,0x00,0x00,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x3F,0x00,0x00,0x00,0x00}, /*"日",0*/{0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /*"一",1*/{0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x04,0x00,0x00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x18,0x10,0x00}, /*"二",2*/{0x00,0x04,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x04,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00}, /*"三",3*/{0x00,0xFE,0x02,0x02,0x02,0xFE,0x02,0x02,0xFE,0x02,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x7F,0x28,0x24,0x23,0x20,0x20,0x20,0x21,0x22,0x22,0x22,0x22,0x7F,0x00,0x00}, /*"四",4*/{0x00,0x02,0x82,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0xC2,0x82,0x02,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x30,0x20,0x00}, /*"五",5*/{0x10,0x10,0x10,0x10,0x10,0x91,0x12,0x1E,0x94,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x40,0x20,0x10,0x0C,0x03,0x01,0x00,0x00,0x01,0x02,0x0C,0x78,0x30,0x00,0x00}, /*"六",6*/ };uchar code nianma[]=//年(0) 月(1) 日(2) 星(3) 期(4){0x40,0x20,0x10,0x0C,0xE3,0x22,0x22,0x22,0xFE,0x22,0x22,0x22,0x22,0x02,0x00,0x00,0x04,0x04,0x04,0x04,0x07,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x04,0x04,0x00}; /*"年",0*/ uchar code yuema[]={0x00,0x00,0x00,0x00,0x00,0xFF,0x11,0x11,0x11,0x11,0x11,0xFF,0x00,0x00,0x00,0x00,0x00,0x40,0x20,0x10,0x0C,0x03,0x01,0x01,0x01,0x21,0x41,0x3F,0x00,0x00,0x00,0x00}; /*"月",1*/ uchar code rima[]={0x00,0x00,0x00,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x3F,0x00,0x00,0x00,0x00}; /*"日",2*/ uchar code xingqima[]={0x00,0x00,0x00,0xBE,0x2A,0x2A,0x2A,0xEA,0x2A,0x2A,0x2A,0x2A,0x3E,0x00,0x00,0x00,0x00,0x48,0x46,0x41,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0x49,0x49,0x41,0x40,0x00, /*"星",3*/0x00,0x04,0xFF,0x54,0x54,0x54,0xFF,0x04,0x00,0xFE,0x22,0x22,0x22,0xFE,0x00,0x00,0x42,0x22,0x1B,0x02,0x02,0x0A,0x33,0x62,0x18,0x07,0x02,0x22,0x42,0x3F,0x00,0x00}; /*"期",4*///时(0) 分(1) 秒(2)uchar code shima[]={0x00,0xFC,0x44,0x44,0x44,0xFC,0x10,0x90,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x00,0x00,0x07,0x04,0x04,0x04,0x07,0x00,0x00,0x03,0x40,0x80,0x7F,0x00,0x00,0x00,0x00}; /*"时",0*/uchar code fenma[]={0x80,0x40,0x20,0x98,0x87,0x82,0x80,0x80,0x83,0x84,0x98,0x30,0x60,0xC0,0x40,0x00,0x00,0x80,0x40,0x20,0x10,0x0F,0x00,0x00,0x20,0x40,0x3F,0x00,0x00,0x00,0x00,0x00}; /*"分",1*/uchar code miaoma[]={0x12,0x12,0xD2,0xFE,0x91,0x11,0xC0,0x38,0x10,0x00,0xFF,0x00,0x08,0x10,0x60,0x00,0x04,0x03,0x00,0xFF,0x00,0x83,0x80,0x40,0x40,0x20,0x23,0x10,0x08,0x04,0x03,0x00}; /*"秒",2*/void delay(sint n); //延时程序void xie_start(); //开始条件void xie_stop(); //停止条件bit xie1(uchar shu); //向8563中写入1个字uchar du1(); //从8563中读出1个字uchar du(); //从8563中读出时间和日期uchar xie(); //向8563中设置时间和日期//uchar xie_dingshi(); //8563定时器设置//uchar xie_fangbo_dingshi(); //8563的方波设置void delay1 (uint ms); //延时void wr_lcd (uchar dat_comm,uchar content); //向12864中写命令//uchar rd_lcd (); //读12864数据void chk_busy (); //忙闲检测void lat_disp (uchar data1,uchar data2); //写点钟//void img_disp (uchar code *img) ; //显示图像void chn_disp (uchar x,uchar y,uchar xl,uchar yl,uchar row_xl,uchar row_yl,uchar code *chn);//显示汉字void init_lcd (); //12864初始化void disp(); //128显示程序//-------------主函数--------------------void main(){uchar ml=0;init_lcd (); //LCD初始化lat_disp(0x00,0x00);xie(); //预设时间用,设置好时间后可以屏蔽for(;;){du(); //读8563的时间lat_disp(0x00,0x00);disp(); //显示时间delay1(100);}}//-------------------延时---------------------------//void delay(sint n){for(n;n>0;n--);}/////////////////////以下是PCF8563读写/////////////////////以下是PCF8563读写/* I2C的起始条件,在时钟端SCK为高电平时,数据端SDA发生由高到低的变化,为起始条件,启动I2C总线。
/***************************************************************系统名称:电子万年历日期:2008,7,18功能描述:LCD12864串行模式显示,DS1302读取时间年月份,18B20 读取温度****************************************************************/#include <reg51.h>#include <intrins.h>#include <stdio.h>#define uchar unsigned char#define uint unsigned int/*------------LCD12864相关声明-----------------------------*/#define com 0#define dat 1sbit cs =P1^6;sbit sid=P1^4;sbit sck=P1^2;uchar code TAB1[]={"电字钟w418781840"};//第一行初始化.uchar code TAB2[]={"20 年月日"}; //第二行uchar code TAB3[]={"星期: : "}; //第三行uchar code TAB4[]={"室温: ℃"}; //第四行/*----------------------DS1302相关声明-------------------------*/char TAB_1302[]={ 0x00,0x29,0x02, //秒:分:时.0x18,0x06,0x06,0x08}; //日:月:星期:年.uchar code TAB_XQ[]={"一二三四五六日"};//把DS1302数字日期转换为中文字符. sbit T_CLK=P2^4; /* 实时时钟的时钟线引脚*/sbit T_IO=P2^5; /* 实时时钟的数据线*/sbit T_RST=P2^6; /* 实时时钟的复位线引脚*/uchar bdata datbyte;sbit datbyte0=datbyte^0;sbit datbyte7=datbyte^7;/*--------------18B20相关声明-------------------------------*/uchar dis1[16];sbit DQ=P1^0; /*DS18B20温度检测*//*----------键盘相关声明-------------------------------------*/sbit key=P3^2; //功能键sbit key1=P3^3; //只有加1键uchar sum,keyflag=0; //调用时,分,秒,标志,调用键盘处理标志./*--------------以下为LCD12864相关函数--------------------------*//**************************************************************函数名称:void delay1ms(uint x)函数功能: 延时1MS***************************************************************/void delay1ms(uint x){uint i,j;for(i=0;i<x;i++)for(j=0;j<120;j++);}/************************************************************** 函数名称:void w_12864byte(uchar byte)函数功能: 写字节**************************************************************/ void w_12864byte(uchar byte){uchar i;for(i=0;i<8;i++){sck=0;byte<<=1;sid=CY;sck=1;}}/************************************************************** 函数名称:uchar r_12864byte(void)函数功能: 读字节***************************************************************/ uchar r_12864byte(void){uchar i,temp1,temp2;temp1 = 0;temp2 = 0;for(i=0;i<8;i++){temp1=temp1<<1;sck = 0;sck = 1;sck = 0;if(sid) temp1++;}for(i=0;i<8;i++){temp2=temp2<<1;sck = 0;sck = 1;sck = 0;if(sid) temp2++;}return ((0xf0&temp1)+(0x0f&temp2));}/************************************************************** 函数名称:void c_12864busy( void )函数功能: 检测忙函数**************************************************************/ void c_12864busy( void ){dow_12864byte(0xfc); //11111,RW(1),RS(0),0while(0x80&r_12864byte());}/************************************************************** 函数名称:void w_12864(bit dat_com,uchar byt)函数功能: 写入函数***************************************************************/ void w_12864(bit dat_com,uchar byt){uchar temp;if(dat_com==0) //为零,写入指令temp=0xf8; //11111,RS(0),RW(0),0else //否则,写入数据temp=0xfa; //11111,RS(1),RW(0),0cs=1;c_12864busy();w_12864byte(temp);w_12864byte(byt&0xf0); //写入高四位w_12864byte(byt<<4); //写入低四位cs=0;}/************************************************************** 函数名称:void init_12864(void)函数功能:初始化12864***************************************************************/ void init_12864(void){w_12864(com,0x30); //基本指令功能.w_12864(com,0x0c); //显示打开,关光标,反白关.w_12864(com,0x01); //清屏指令.w_12864(com,0x06); //AC自动加一}/*----------------以下为DS1302相关函数-------------------------*//************************************************************** 函数名称:void w_1302byte(uchar date)函数功能:写一个字节(上升沿)***************************************************************/ void w_1302byte(uchar date){ uchar i;datbyte=date;for(i=0;i<8;i++){ T_IO=datbyte0; //写最低位T_CLK=0;T_CLK=1;datbyte>>=1;}}/************************************************************** 函数名称:uchar r_1302byte(void)函数功能:读一个字节(下降沿)***************************************************************/ uchar r_1302byte(void){ uchar i;datbyte=0;for(i=0;i<8;i++){ datbyte7=T_IO; //读最低位T_CLK=1;T_CLK=0;datbyte>>=1;}return(datbyte);}/*************************************************************** 函数名称:void write_1302(uchar addr,uchar date)函数功能: 指定位置写数据****************************************************************/ void write_1302(uchar addr,uchar date){ T_RST=0;T_CLK=0;T_RST=1;w_1302byte(addr);w_1302byte(date);T_CLK=0;T_RST=0;}/************************************************************** 函数名称:uchar read_1302(uchar addr)函数功能: 指定位置读数据****************************************************************/ uchar read_1302(uchar addr){ uchar dat1,dat2,temp;T_RST=0;T_CLK=0;T_RST=1;w_1302byte(addr);temp=r_1302byte();T_RST=0;T_CLK=0;dat1=temp/16;dat2=temp%16;temp=dat1*10+dat2;return(temp);}/***************************************************************函数名称:void init_1302(void)函数功能: 初始化*****************************************************************/ void init_1302(void){ uchar i;uchar addr=0x80;write_1302(0x8e,0x00);for(i=0;i<7;i++){write_1302(addr,TAB_1302[i]);addr+=2;}write_1302(0x8e,0x80);}/**************************************************************** 函数名称:void get_1302(void)功能说明:读取DS1302时钟信息.*****************************************************************/ void get_1302(void){ uchar i,addr=0x81;for(i=0;i<7;i++){ TAB_1302[i]=read_1302(addr);addr+=2;}}/*---------------以下为18B20相关函数-----------------------------*//******************************************************************函数名称:void delay (uint x)功能说明:若机器周期为1us,则本延时程序为延时4*x(us)******************************************************************/ void delay (uint x) //本板延时8us{while (--x);}/***************************************************************** 函数名称:uchar bus_rest(void)功能说明:产生单总线系统信号的总线复位信号,并返回总线上是否存在单总线器件信息******************************************************************/ uchar bus_rest(void){uchar presence;DQ=0; //将DQ信号线拉低delay(29); //持续48USDQ=1; //释放总线delay(3); //等待从设备将总线拉低presence=DQ; //保存当前总线状态delay(25); //等待总线初始化过程结束return presence;//返回是否有从设备将总线拉低}/**************************************************************** 函数名称:uchar r_1820BYTE(void)功能说明:向单总线读取一个数据字节*****************************************************************/ uchar r_1820BYTE(void){uchar i=0;uchar date = 0;for (i=8;i>0;i--){DQ = 0; // 将DQ信号线拉低启动读时隙DQ=1;// 释放总线,等待从机动车辆返回数据位delay(1); //越接近15us越好; 准备采样总线上的信号date>>=1 ;if (DQ)date=date|0x80;delay(6);}return(date);}/***************************************************************** 函数名称:void w_1280Byte(uchar bytevalue)功能说明:向单总线写一个数据字节******************************************************************/ void w_1280Byte(uchar bytevalue){uchar i;for(i=0;i<8;i++){DQ=0; // 将DQ信号线拉低启动读时隙DQ=bytevalue&0x01; //delay(5);//等待写时隙结束DQ=1; //释放bytevalue>>=1;}delay(5); ////等待写时隙结束}/***************************************************************** 函数名称:uint read_T(void)功能说明:读取1820温度*******************************************************************/ uint read_T(void){uchar a=0;uchar b=0;uint t=0;bus_rest();w_1280Byte(0xCC); // 跳过读序号列号的操作;w_1280Byte(0x44); // 启动温度转换,模数转化;bus_rest();w_1280Byte(0xCC); //跳过读序号列号的操作;a=r_1820BYTE();// 低8位b=r_1820BYTE();// 高8位t=(b*256)+a;return(t);}/**************************************************************函数名称:void show_T(uint temp)函数功能:显示温度**************************************************************/void show_T(uint temp){int i;float ftemp;ftemp = temp* 0.0625;w_12864(com,0x98+3);for(i=0;i<5;i++)w_12864(dat,dis1[i]); //写入温度}/*---------------以下为显示相关函数--------------------------*//******************************函数名称: void fenli(uchar x,uchar y,uchar val)功能描述: 指定位置写入数据********************************/void fenli(uchar x,uchar y,uchar val){ uchar ge,shi,addr,i=0;if(val==5)//星期数字显示的转换为中文{w_12864(com,0x88+2);for(i=0;i<2;i++){if(TAB_1302[5]==0)w_12864(dat,TAB_XQ[i]);if(TAB_1302[5]==1)w_12864(dat,TAB_XQ[2+i]);if(TAB_1302[5]==2)w_12864(dat,TAB_XQ[3+i]);if(TAB_1302[5]==3)w_12864(dat,TAB_XQ[5+i]);if(TAB_1302[5]==4)w_12864(dat,TAB_XQ[7+i]);if(TAB_1302[5]==5)w_12864(dat,TAB_XQ[9+i]);if(TAB_1302[5]==6)w_12864(dat,TAB_XQ[11+i]);}}else{shi=TAB_1302[val]/10;//分离十位ge=TAB_1302[val]%10;if(x==1)x=0x80;if(x==2)x=0x90;if(x==3)x=0x88;if(x==4)x=0x98;addr=x+y;w_12864(com,addr);//指定位置w_12864(dat,0x30+shi);//写入w_12864(dat,0x30+ge);}}/*************************************************************函数名称:void display(void)功能描述: 显示函数**************************************************************/ void display(void){ get_1302(); //读1302fenli(3,7,0); //读秒fenli(3,5,1); //读分fenli(3,3,2); //读时fenli(2,5,3); //读日fenli(2,3,4); //读月fenli(3,2,5); //读星期fenli(2,1,6); //读年}/*---------------按键处理相关函数--------------------------*//************************************************************ 函数名称:void scanner()功能描述: 按键函数*************************************************************/ void scanner(){ uchar i,j;if(!key) //功能键按下{ delay1ms(500); //延时500MSif(!key) //还按下,退出时间调整{ keyflag=0; //标志位为0sum=0; //清0w_12864(com,0x0c);//清闪烁for(i=0;i<7;i++)//十进制转十六进制{ j=TAB_1302[i]/10;TAB_1302[i]=TAB_1302[i]%10;TAB_1302[i]=TAB_1302[i]+16*j;}init_1302(); //写入1302while(!key); //等待释放delay1ms(10); //延时消抖}else //500MS内放开{ keyflag=1; //标志为1,进行时间调整sum++; //功能键加1if(sum==8)sum=0;switch(sum){ case 1: //{ w_12864(com,0x98+7);w_12864(com,0x0f);break;}case 2: //为2,年闪烁w_12864(com,0x90+1);break;case 3: //月闪烁w_12864(com,0x90+3);break;case 4: //日闪烁w_12864(com,0x90+5);break;case 5: //星期闪烁w_12864(com,0x88+2);break;case 6: //分闪烁w_12864(com,0x88+5);break;case 7: //时闪烁w_12864(com,0x88+3);break;}}}if(sum) //功能键按下{if(!key1){ delay1ms(10);if(!key1){ while(!key1);//等待加1键释放delay1ms(10);if(sum==1){ //备用}if(sum==2){ TAB_1302[6]++;if(TAB_1302[6]==100)TAB_1302[6]=0;fenli(2,1,6);w_12864(com,0x90+1);//闪烁归位}if(sum==3){ TAB_1302[4]++;if(TAB_1302[4]==13)TAB_1302[4]=1;fenli(2,3,4);w_12864(com,0x90+3);}if(sum==4){ TAB_1302[3]++;if(TAB_1302[3]==32)TAB_1302[3]=1;fenli(2,5,3);w_12864(com,0x90+5);}if(sum==5){ TAB_1302[5]++;if(TAB_1302[5]==7)TAB_1302[5]=0;fenli(3,2,5);w_12864(com,0x88+2);}if(sum==6){ TAB_1302[1]++;if(TAB_1302[1]==60)TAB_1302[1]=0;fenli(3,5,1);w_12864(com,0x88+5);}if(sum==7){ TAB_1302[2]++;if(TAB_1302[2]==24)TAB_1302[2]=0;fenli(3,3,2);w_12864(com,0x88+3);}}}}}//============================================================= void init(void){uchar i;init_12864();init_1302();while(TAB1[i]!='\0'){w_12864(dat,TAB1[i]);i++;}i=0;w_12864(com,0x90);while(TAB2[i]!='\0'){w_12864(dat,TAB2[i]);i++;}i=0;w_12864(com,0x88);while(TAB3[i]!='\0'){w_12864(dat,TAB3[i]);i++;}i=0;w_12864(com,0x98);while(TAB4[i]!='\0'){w_12864(dat,TAB4[i]);i++;}}/************************************************************* 函数名称:主函数函数功能:**************************************************************/ main(){init();while(1){scanner(); //检测键盘if(!keyflag) //标志为0{ display(); //调用显示show_T(read_T()); //显示温度delay1ms(500);}}}。
51单片机做的12864万年历Main.c#include "reg52.h"#include "macroconst.h"#include "keyscan.h"#include "screen.h"#include "18b20.h"#include "ds1302.h"#include "atao_12864.h"#include "24c02.h"idata unsigned char state1[1]。
unsigned char screennum=1。
//屏幕号#define time_task_sec 200 //节拍200Hz#define clock 24000000 //晶振#define max_task 4 //最大任务数idata unsigned char task_delay[4]。
#define task_delay0 time_task_sec/1 //2赫兹18b20 #define task_delay1 time_task_sec/5 //10赫兹屏幕#define task_delay2 time_task_sec/3 //4赫兹1302 #define task_delay3 time_task_sec/20 //20赫兹键盘void init(>{unsigned char i。
init18b20(>。
ds1302_init(>。
initina1(>。
//---------------------------LCD字库初始化程序 RdFromROM(state1,8,1>。
state[0]=state1[0]。
//-------界面RdFromROM(state1,15,1>。
12864LCD+DS1302万年历设计proteus仿真(2011-05-18 23:09:40)标签:it原理图程序代码//DS1302与12864设计的可调式电子日历与时钟//#include<reg51.h>#include<intrins.h>#include<string.h>#define uchar unsigned char#define uint unsigned intextern void LCD_Initialize();extern void Display_A_Char_8x16(ucharP,ucharL,uchar *M)reentrant; extern void Display_A_WORD(ucharP,ucharL,uchar *M)reentrant;//在调整日期时间时,用该位决定是否反白显示//extern bit Reverse_Display;sbit SDA =P1^0; //DS1302数据线sbit CLK =P1^1; //DS1302时钟线sbit RST =P1^2; //DS1302复位线sbit K1 =P3^4; //选择sbit K2 =P3^5; //加sbit K3 =P3^6; //减sbit K4 =P3^7; //确定uchartCount =0;//一年中每月的天数,2月的天数由年份决定ucharMonthsDays[]={0,31,0,31,30,31,30,31,31,30,31,30,31};//所读取的日期时间ucharDateTime[7];//当前调整的时间对象:秒,分,时,日,月,年(0,1,2,3,4,6)//5对应星期,星期调节由年月日调整自动完成char Adjust_Index=-1;//水平与垂直偏移ucharH_Offset=10,V_Page_Offset=0;//年月日,星期,时分秒汉字点阵(16*16)------uchar code DATE_TIME_WORDS[]={//0x40,0x20,0x10,0x0C,0xE3,0x22,0x22,0x22,0xFE,0x22,0x22,0x22,0x22,0x02,0x00,0x00, 0x04,0x04,0x04,0x04,0x07,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x04,0x04,0x00, //0x00,0x00,0x00,0x00,0x00,0xFF,0x11,0x11,0x11,0x11,0x11,0xFF,0x00,0x00,0x00,0x00,0x00,0x40,0x20,0x10,0x0C,0x03,0x01,0x01,0x01,0x21,0x41,0x3F,0x00,0x00,0x00,0x00,//0x00,0x00,0x00,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x3F,0x00,0x00,0x00,0x00,//0x00,0x00,0x00,0xBE,0x2A,0x2A,0x2A,0xEA,0x2A,0x2A,0x2A,0x2A,0x3E,0x00,0x00,0x00, 0x00,0x48,0x46,0x41,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0x49,0x49,0x41,0x40,0x00,//0x00,0x04,0xFF,0x54,0x54,0x54,0xFF,0x04,0x00,0xFE,0x22,0x22,0x22,0xFE,0x00,0x00,0x42,0x22,0x1B,0x02,0x02,0x0A,0x33,0x62,0x18,0x07,0x02,0x22,0x42,0x3F,0x00,0x00,//0x00,0xFC,0x44,0x44,0x44,0xFC,0x10,0x90,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x00,0x00,0x07,0x04,0x04,0x04,0x07,0x00,0x00,0x03,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,//0x80,0x40,0x20,0x98,0x87,0x82,0x80,0x80,0x83,0x84,0x98,0x30,0x60,0xC0,0x40,0x00,0x00,0x80,0x40,0x20,0x10,0x0F,0x00,0x00,0x20,0x40,0x3F,0x00,0x00,0x00,0x00,0x00,//0x12,0x12,0xD2,0xFE,0x91,0x11,0xC0,0x38,0x10,0x00,0xFF,0x00,0x08,0x10,0x60,0x00,0x04,0x03,0x00,0xFF,0x00,0x83,0x80,0x40,0x40,0x20,0x23,0x10,0x08,0x04,0x03,0x00,//0x00,0x02,0x02,0xF2,0x12,0x12,0x12,0x12,0xF2,0x02,0x02,0x02,0xFE,0x02,0x02,0x00, 0x00,0x00,0x00,0x07,0x02,0x02,0x02,0x02,0x07,0x10,0x20,0x40,0x3F,0x00,0x00,0x00,//0x20,0x21,0xEE,0x04,0x00,0x00,0xFF,0x29,0xA9,0xBF,0xA9,0xA9,0x01,0xFF,0x00,0x00, 0x00,0x00,0x1F,0x88,0x44,0x30,0x0F,0x00,0x0F,0x04,0x04,0x4F,0x80,0x7F,0x00,0x00,//0x00,0x02,0x02,0x02,0x02,0x82,0x7E,0x22,0x22,0x22,0x22,0xF2,0x22,0x02,0x02,0x00,0x00,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x20,0x60,0x20,0x1F,0x00,0x00,0x00,0x00,//0x00,0x00,0xFE,0x02,0x22,0x22,0x22,0x22,0xFA,0x22,0x22,0x22,0xE2,0x02,0x02,0x00, 0x40,0x30,0x0F,0x00,0x40,0x20,0x18,0x06,0x01,0x00,0x20,0x60,0x3F,0x00,0x00,0x00,//0x00,0x02,0x82,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0xC2,0x82,0x02,0x00,0x00,0x00, 0x20,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x30,0x20,0x00,//0x42,0x42,0xFE,0x42,0x42,0xE0,0x00,0xFF,0x00,0x42,0x42,0xFE,0x42,0x42,0x42,0x00, 0x10,0x10,0x0F,0x88,0x49,0x20,0x18,0x07,0x20,0x20,0x20,0x3F,0x20,0x20,0x20,0x00,//0x00,0xFE,0x22,0x52,0x8E,0x00,0xC4,0xB4,0x8C,0xE7,0x84,0x84,0x84,0x84,0x04,0x00, 0x00,0xFF,0x02,0x04,0x23,0x10,0x0C,0x40,0x80,0x7F,0x00,0x02,0x04,0x18,0x30,0x00,/0x00,0x10,0x10,0x92,0x72,0xA2,0xA2,0xF2,0xAA,0xAA,0x66,0xA2,0x12,0x18,0x00,0x00, 0x10,0x08,0x06,0x01,0x04,0x44,0x84,0x7F,0x04,0x04,0x04,0x01,0x06,0x18,0x08,0x00,};//星期几的汉字点阵(16*16)uchar code WEEKDAY[]={//0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,///0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,///0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,///0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,};//半角数字点阵(8*16)uchar code DIGITS[]={////0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,///0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,///0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,///0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00, };//向DS1302写、读一字节--------//向DS1302写入一字节void Write_A_Byte_TO_DS1302(uchar x){uchar i;for (i=0;i<8;i++){SDA=x&1;CLK=1;CLK=0;x>>=1;}}//从DS1302读取一字节uchar Get_A_Byte_FROM_DS1302(){uchari,b,t;for(i=0;i<8;i++){b>>=1;t=SDA;b|=t<<7;CLK=1;CLK=0;}//BCD码转换return b/16*10+b;}//DS1302指定位置读数据ucharRead_Data(ucharaddr){uchardat;RST=0;CLK=0;RST=1;Write_A_Byte_TO_DS1302(addr);dat=Get_A_Byte_FROM_DS1302();CLK=1;RST=0;return dat;}//向DS1302某地址写入数据void Write_DS1302(ucharaddr,uchardat){CLK=0;RST=1;Write_A_Byte_TO_DS1302(addr);Write_A_Byte_TO_DS1302(dat);CLK=0;RST=0;}//设置时间void SET_DS1302(){uchar i;Write_DS1302(0x8E,0x00);//秒分时日月年依次写入for(i=0;i<7;i++){//秒的起始地址10000000(0x80),//后续依次是分,时,日,月,周,年,写入地址每次递增2 Write_DS1302(0x80+2*i,(DateTime[i]/10<<4)|(DateTime[i])); }Write_DS1302(0x8E,0x80);}//读取当前日期时间void GetTime(){uchar i;for(i=0;i<7;i++){DateTime[i]=Read_Data(0x81+2*i);}}//判断是否为闰年ucharisLeapYear(uint y){return(y%4==0&&y0!=0)||(y@0==0);}//----------------------------------------void RefreshWeekDay(){uinti,d,w=5;for(i=2000;i<2000+DateTime[6];i++){d=isLeapYear(i)?366:365;w=(w+d)%7;}d=0;for (i=1;i<DateTime[4];i++)d+=MonthsDays[i];d+=DateTime[3];DateTime[5]=(w+d)%7+1;}//年月日时分秒++--void DateTime_Adjust(char x){switch(Adjust_Index){case 6://年00-99if(x==1&&DateTime[6]<99) DateTime[6]++;if(x==-1&&DateTime[6]>0)DateTime[6]--;//获取2月天数MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28; //如果年份变化后当前月份的天数大于上限则设为上限if(DateTime[3]>MonthsDays[DateTime[4]])DateTime[3]=MonthsDays[DateTime[4]];RefreshWeekDay();//刷新星期break;case 4://月01-12if(x==1&&DateTime[4]<12)DateTime[4]++;if(x==-1&&DateTime[4]>1)DateTime[4]--;//获取2月天数MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28;//如果年份变化后当前月份的天数大于上限则设为上限if(DateTime[3]>MonthsDays[DateTime[4]])DateTime[3]=MonthsDays[DateTime[4]];RefreshWeekDay();//刷新星期break;case 3://日00-28/29/30/31;调节前首先根据年份得出该年中2月的天数MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28;//根据当前月份决定调节日期的上限if(x==1&&DateTime[3]<MonthsDays[DateTime[4]])DateTime[3]++;if(x==-1&&DateTime[3]>0)DateTime[3]--;RefreshWeekDay();//刷新星期break;case 2://时if(x==1&&DateTime[2]<23)DateTime[2]++;if(x==-1&&DateTime[2]>0)DateTime[2]--;break;case 1://分if(x==1&&DateTime[1]<59)DateTime[1]++;if(x==-1&&DateTime[1]>0)DateTime[1]--;break;case 0://秒if(x==1&&DateTime[0] <59) DateTime[0]++;if(x==-1&&DateTime[0] >0) DateTime[0]--;break;}}//定时器0每秒刷新LCD显示void T0_INT() interrupt 1{TH0=-50000/256;TL0=-50000%6;if(++tCount!=2)return;tCount=0;//年(后两位)Reverse_Display=Adjust_Index==6;Display_A_Char_8x16(V_Page_Offset,16+H_Offset,DIGITS+DateTime[6]/10*16); Display_A_Char_8x16(V_Page_Offset,24+H_Offset,DIGITS+DateTime[6]*16);//月Reverse_Display=Adjust_Index==4;Display_A_Char_8x16(V_Page_Offset,48+H_Offset,DIGITS+DateTime[4]/10*16); Display_A_Char_8x16(V_Page_Offset,56+H_Offset,DIGITS+DateTime[4]*16);//日Reverse_Display=Adjust_Index==3;Display_A_Char_8x16(V_Page_Offset,80+H_Offset,DIGITS+DateTime[3]/10*16); Display_A_Char_8x16(V_Page_Offset,88+H_Offset,DIGITS+DateTime[3]*16);//星期Reverse_Display=Adjust_Index==5;Display_A_Char_8x16(V_Page_Offset+3,104+H_Offset, WEEKDAY+DateTime[5]*16-16);//时Reverse_Display=Adjust_Index==2;Display_A_Char_8x16(V_Page_Offset+6,16+H_Offset,DIGITS+DateTime[2]/10*16); Display_A_Char_8x16(V_Page_Offset+6,24+H_Offset,DIGITS+DateTime[2]*16);//分Reverse_Display=Adjust_Index==1;Display_A_Char_8x16(V_Page_Offset+6,48+H_Offset,DIGITS+DateTime[1]/10*16); Display_A_Char_8x16(V_Page_Offset+6,56+H_Offset,DIGITS+DateTime[1]*16);//秒Reverse_Display=Adjust_Index==0;Display_A_Char_8x16(V_Page_Offset+6,80+H_Offset,DIGITS+DateTime[0]/10*16); Display_A_Char_8x16(V_Page_Offset+6,88+H_Offset,DIGITS+DateTime[0]*16);} //键盘中断(INT0)void EX_INT0() interrupt 0{if (K1 == 0) //选择调整对象{if (Adjust_Index == -1 || Adjust_Index == 0) Adjust_Index = 7;Adjust_Index--;if (Adjust_Index == 5) Adjust_Index = 4; //跳过对星期的调整}elseif (K2 == 0)DateTime_Adjust( 1); //加elseif (K3 == 0)DateTime_Adjust( -1 ); //减elseif (K4 == 0) //确定{SET_DS1302();Adjust_Index = -1;}}void main(){//液晶初始化LCD_Initialize();//显示年的固定前两位Display_A_Char_8x16(V_Page_Offset,0+H_Offset,DIGITS+2*16);Display_A_Char_8x16(V_Page_Offset,8+H_Offset,DIGITS);//显示固定汉字:年月日,星期,时分秒Display_A_WORD(V_Page_Offset,32+H_Offset,DATE_TIME_WORDS+0*32); Display_A_WORD(V_Page_Offset,64+H_Offset,DATE_TIME_WORDS+1*32); Display_A_WORD(V_Page_Offset,96+H_Offset,DATE_TIME_WORDS+2*32); Display_A_WORD(V_Page_Offset+3,72+H_Offset,DATE_TIME_WORDS+3*32); Display_A_WORD(V_Page_Offset+3,88+H_Offset,DATE_TIME_WORDS+4*32); Display_A_WORD(V_Page_Offset+6,32+H_Offset,DATE_TIME_WORDS+5*32); Display_A_WORD(V_Page_Offset+6,64+H_Offset,DATE_TIME_WORDS+6*32); Display_A_WORD(V_Page_Offset+6,96+H_Offset,DATE_TIME_WORDS+7*32); Display_A_WORD(V_Page_Offset+2,0+H_Offset,DATE_TIME_WORDS+8*32); Display_A_WORD(V_Page_Offset+2,16+H_Offset,DATE_TIME_WORDS+9*32); Display_A_WORD(V_Page_Offset+2,32+H_Offset,DATE_TIME_WORDS+10*32); Display_A_WORD(V_Page_Offset+2,48+H_Offset,DATE_TIME_WORDS+11*32); Display_A_WORD(V_Page_Offset+4,0+H_Offset,DATE_TIME_WORDS+12*32); Display_A_WORD(V_Page_Offset+4,16+H_Offset,DATE_TIME_WORDS+13*32); Display_A_WORD(V_Page_Offset+4,32+H_Offset,DATE_TIME_WORDS+14*32); Display_A_WORD(V_Page_Offset+4,48+H_Offset,DATE_TIME_WORDS+15*32);//允许INT0,T0中断IE=0x83;IP=0x01;IT0=0x01;TH0=-50000/256;TL0=-50000/256;TR0=1;while(1){//如果未执行调整操作则正常读取当前时间if(Adjust_Index==-1)GetTime();}}// 名称:12864LCD显示驱动程序(不带字库)//------------------------------------------------------------- #include <reg51.h>#include <intrins.h>#define unchar unsigned char#define uint unsigned int#define LCD_DB_PORT P0 //液晶DB0-DB7 #define LCD_START_ROW 0xC0 //起始行#define LCD_PAGE 0xB8 //页指令#define LCD_COL 0x40 //列指令//液晶引脚定义sbit DI =P2^0 ;sbit RW =P2^1 ;sbit E =P2^2 ;sbit CS1 =P2^3 ;sbit CS2 =P2^4 ;sbit rst =P2^5 ;bit Reverse_Display =0;//----------------------------------------------------------- //检查LCD是否忙//-----------------------------------------------------------bit LCD_Check_Busy (){LCD_DB_PORT =0xFF;RW =1; _nop_(); DI =0;E =1;_nop_(); E =0;return (bit) (P0 & 0x80);}//-----------------------------------------------------------// 向LCD发送命令//-----------------------------------------------------------void LCD_Write_Command( unchar c){while (LCD_Check_Busy ());LCD_DB_PORT =0xFF; RW =0; _nop_();DI =0;LCD_DB_PORT = c; E =1; _nop_();E =0;}//-----------------------------------------------------------//向LCD发送数据//-----------------------------------------------------------//向LCD发送数据void LCD_Write_Data(uchar d ){while(LCD_Check_Busy());LCD_DB_PORT = 0xFF;RW = 0; _nop_();DI = 1;//根据Reverse_Display决定是否反相显示if (! Reverse_Display) LCD_DB_PORT = d; else LCD_DB_PORT = ~d;E = 1 ;_nop_(); E = 0;}//初始化LCDvoid LCD_Initialize(){CS1 = 1; CS2 = 1;LCD_Write_Command(0x38);LCD_Write_Command(0x0F);LCD_Write_Command(0x01);LCD_Write_Command(0x06);LCD_Write_Command(LCD_START_ROW);}void Common_Show(ucharP,ucharL,ucharW,uchar *r)reentrant {uchar i;if(L<64)//显示在左半屏或左右半屏{CS1=1; CS2=0;LCD_Write_Command( LCD_PAGE+P);LCD_Write_Command(LCD_COL + L);if(L+W<64){for(i=0;i<W;i++) LCD_Write_Data(r[i]);}else//如果月结则跨越左右半屏显示{for(i=0;i<64-L;i++) LCD_Write_Data(r[i]);CS1=0;CS2=1;LCD_Write_Command(LCD_PAGE+P);LCD_Write_Command(LCD_COL);for(i=64-L;i<W;i++) LCD_Write_Data(r[i]);}}else // 全屏显示在右半屏{CS1=0;CS2=1;LCD_Write_Command(LCD_PAGE + P);LCD_Write_Command(LCD_COL+L-64);for (i=0;i<W;i++)LCD_Write_Data(r[i]);}}//显示一个8X16点阵字符//void Display_A_Char_8X16(ucharP,ucharL,uchar *M) reentrant {Common_Show( P, L, 8, M );Common_Show( P +1,L,8,M+8 );}//显示一个16x16点阵汉字void Display_A_WORD(ucharP,ucharL,uchar *M) reentrant {Common_Show( P, L, 16, M); //显示汉字上半部分Common_Show( P + 1,L, 16, M +16); //显示汉字下半部分}。
毕业设计报告(论文)报告(论文)题目:基于单片机的电子万年历的设计作者所在系部:电子工程系作者所在专业:通信工程作者所在班级: B10231作者姓名:作者学号:指导教师姓名:完成时间: 2014年6月10日北华航天工业学院教务处制摘要本文介绍了基于STC89C52单片机的电子万年历的软硬件设计方法。
采用从软件设计、软件仿真到硬件实验板仿真进而焊接硬件电路的设计步骤完成了本课题。
本系统以STC89C52单片机为核心控制器,用串行时钟芯片DS1302来记录时间,它能够以秒为单位进行计时。
万年历显示部分采用LCD12864,可以在12864上同时显示年、月、日、时、分、秒,星期、阴阳历、天干地支以及实时温度,此外本系统还具有时间校准、整点半点报时和闹钟功能。
本文详尽叙述了系统中所用到的各种软硬件的特点,并就软硬件设计过程中出现的种种问题做出了思考,并最终一一解决,在单片机设计万年历这一成熟的产品领域里,应用所学知识,做出了自己的有益尝试。
关键词:单片机 STC89C52 万年历 DS1320 LCD12864AbstractThis paper introduces the hardware structure of an electronic calendar based on STC89C52 single-chip microcomputer and a software and hardware design method.The use of design steps from software design, software simulation to hardware experiment simulation and hardware circuit board weldin completed this topic.System’s controller is STC89C52 single-chip microcomputer, serial clock chip DS1302 is usede to record the time for calender, it can be to time the time in seconds, but also has an automatic leap year compensation and other more functions. Calendar using intuitive digital display, which is on the LCD12864 display year, month, day,hour, minute, second and week, at the same time,the solar calendar, lunar calendar and real-time temperature can be displayed, moreover,it has time calibration function and alarm clock function, and so on.This paper describes the characteristics of the system using a variety of software and hardware in details,and I gradually considered and solved some problems appeared in the process of Software and hardware design.In the mature product eara of SCM calender design, I apply relevant knowledge and has made a beneficial attempt.Keyword:single-chip microcomputer STC89C52 DS1320 electronic calendar 12864目录第1章绪论 (6)1.1课题产生背景及其意义 (6)1.2电子万年历的研究现状与发展趋势 (6)1.3本课题主要流程和论文章节安排 (7)1.4小结 (7)第2章课题设计方案选择 (8)2.1单片机电子万年历系统概述 (8)2.2单片机方案选择 (8)2.3计时方案选择 (9)2.4显示方案选择 (9)2.5温度传感器方案选择 (10)2.6按键方案选择 (10)2.7报时方案选择 (10)2.8课题设计流程说明 (11)2.9小结 (11)第3章软件设计部分 (12)3.1模块化程序设计简介 (12)3.2主程序流程描述 (12)3.2各子程序设计 (13)3.2.1 DS1302时钟子程序 (14)3.2.2 LCD12864显示子程序 (15)3.2.3 DS18B20温度传感器子程序 (17)3.2.4 独立按键子程序 (18)3.2.5 阳历转阴历显示程序 (20)3.2.6 干支纪年子程序 (21)3.2.7 星期计算子程序 (21)3.2.8 延时子程序 (22)3.3程序调试的常见问题说明 (22)3.4实验板仿真 (23)3.5小结 (23)第4章硬件设计部分 (24)4.1硬件设计整体框架 (24)4.2单片机最小系统设计 (24)4.3外围电路设计 (25)4.3.1 温度传感器电路 (25)4.3.2 时钟电路 (25)4.3.3 按键电路与蜂鸣器电路 (26)4.3.4 12864显示电路 (26)4.4小结 (27)第5章结论 (28)5.1课题成果 (28)5.1.1 焊接实物图展示 (28)5.1.2上电实物图展示 (28)5.2可改进部分 (29)5.3课题收获 (29)致谢 (30)参考文献 (31)附录 (32)基于单片机的电子万年历的设计第1章绪论1.1 课题产生背景及其意义上世纪九十年代以来,电子技术的发展势头强劲,它使得人类社会发生了深刻变革,并且到目前为止这种变革依然在迅猛发展,而半导体技术的发展使得摩尔定律所预言的发展周期越来越短,电子产品竞争激烈,产品更新速度更是让人应接不暇。
基于单片机和12864LCD模块的万年历设计与仿真作者:陈红李玮来源:《中小企业管理与科技·上旬刊》2011年第12期摘要:介绍利用单片机控制液晶显示模块显示电子万年历,给出硬件设计电路,和软件编程设计,通过Proteus软件,对硬件电路和软件编程进行仿真,具有一定的实用价值。
关键词:单片机液晶显示模块 C51编程液晶显示模块在各种测量仪器、测量装置、显示仪表等日用电子产品中的应用越来越广泛,并且对器件的测量精度和显示精度的要求也越来越高,尤其是对时间的测量不但要准确,而且需要读取数值更直观更方便。
本文介绍由单片机AT89C52和DS1302控制12864点阵液晶显示模块实现电子万年历的设计,并且用Proteus软件对整个电路进行模拟和仿真。
1 系统构成本系统设计中使用的单片机为AT89C52,其内部是8位的CPU,8KB片内ROM以及256B的可使用的片内RAM,32根并行I/O接口,两个16位的定时/计数器,五个中断源,两个中断优先级的内部结构。
其中单片机的外围电路有复位电路,时钟电路。
其次还用到美国DALLAS公司推出的高性能、低功耗、带RAM的实时时钟电路DS1302,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。
采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。
本系统里用12864LCD显示模块来显示万年历的年月日、星期及时间信息,该液晶模块使用KS0108控制器,5V电压驱动,带有背光,内置8192个16×16点阵,128个字符及64×128点阵显示RAM。
与外部CPU接口采用并行或者串行两种控制方式。
单片机在控制液晶显示模块的接口方式主要有两种方式,直接访问方式和间接访问方式,直接访问方式是把液晶显示模块作为存储器或I/O设备直接连接到单片机总线上。
而间接访问方式是把液晶显示模块作为终端与单片机的并行接口连接,而单片机通过对该并行接口的操作实现对液晶显示。
基于51单片机的设计:源代码调试通过主函数部分:包含头文件,液晶18b20和DS1302的初始化#include<reg52.h>#include"12864.h"#include"ds1302.h"#include"18b20.h"#define uchar unsigned char#define uint unsigned intvoid main(){uchar i;lcd_init();b20_init();ds1302_init();ds1302_write_time();while(1){write_com(0x80);dis("★★mage心寒★★");get_temperature();b20_display();ds1302_read_time();for(i=1;i<8;i++)tempdata[i]=time_buf1[i];ds1302_display();}}12864控制部分:#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit rs=P2^4;sbit e=P2^6;sbit rw=P2^5;uchar i,j,num,aa;void delayms(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void write_com(uchar com) {rs=0;P0=com;delayms(5);e=1;delayms(5);e=0;}void write_data(uchar date) {rs=1;P0=date;delayms(5);e=1;delayms(5);e=0;}void dis(unsigned char code *s) { while(*s>0){ write_data(*s);s++;delayms(5);}}void lcd_init(){rw=0;e=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);write_com(0x80);}/*lcd_display(){write_com(0x80);dis("12864 液晶,,,,");delayms(100);write_com(0x90);dis("安徽建筑工业学院");delayms(100);write_com(0x88);dis("电子创新实验室");delayms(100);write_com(0x98);dis("mage心寒");delayms(1000);write_com(0x01);}*/DS1302部分:#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intuchar time_buf2[16];uchar tempdata[8];uchar num;sbit sck=P3^6;sbit sda=P3^4;sbit rst=P3^5;#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 0xbeunsigned char time_buf1[] = {20,10,8,26,15,57,56,4};//年月日时分秒周unsigned char time_buf[16] ;//空年月日时分秒周/*向DS1302写入一字节数据*/void ds1302_write_byte(uchar add, uchar d) {uchar i;rst=1; /*启动DS1302总线*//*写入目标地址:addr*/add= add & 0xfe;/*最低位置零*/for (i = 0; i < 8; i ++) {if (add & 0x01) {sda=1;}else {sda=0;}sck=1;sck=0;add = add >> 1;}/*写入数据:d*/for (i = 0; i < 8; i ++) {if (d & 0x01) {sda=1;}else {sda=0;}sck=1;sck=0;d = d >> 1;}rst=0; /*停止DS1302总线*/ }/*从DS1302读出一字节数据*/uchar ds1302_read_byte(uchar add){uchar i;uchar temp;rst=1; /*启动DS1302总线*//*写入目标地址:addr*/add = add | 0x01;/*最低位置高*/for (i = 0; i < 8; i ++) {if (add & 0x01) {sda=1;;}else {sda=0;}sck=1;sck=0;add = add >> 1;}/*输出数据:temp*/for (i = 0; i < 8; i ++) {temp = temp >> 1;if (sda==1) {temp |= 0x80;}else {temp &= 0x7f;}sck=1;sck=0;}rst=0; /*停止DS1302总线*/return temp;}/*向DS302写入时钟数据*/void ds1302_write_time(){unsigned char i,tmp;for(i=1;i<8;i++){ //BCD处理tmp=time_buf1[i]/10;time_buf[i]=time_buf1[i]%10;time_buf[i]=time_buf[i]+tmp*16;}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(){uchar i,tmp;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); //秒time_buf[7]=ds1302_read_byte(ds1302_day_add); //周for(i=1;i<8;i++){ //BCD处理tmp=time_buf[i]/16;time_buf1[i]=time_buf[i]%16;time_buf1[i]=time_buf1[i]+tmp*10;}}/*DS302初始化函数*/void ds1302_init(){rst=0; /*RST脚置低*/sck=0; /*SCK脚置低*/}void write_sfm(uchar date){uchar shi,ge;shi=date/10;ge=date%10;//write_com(0x90+add);write_data(0x30+shi);write_data(0x30+ge);}void write_nyr(uchar date){uchar shi,ge;shi=date/10;ge=date%10;//write_com(0x90+add);write_data(0x30+shi);write_data(0x30+ge);}void write_xq(uchar date){//write_com(0x90+add);switch(date){case 1:write_data('M');break;case 2:write_data('T');break;case 3:write_data('W');break;case 4:write_data('T');break;case 5:write_data('F');break;case 6:write_data('S');break;case 7:write_data('s');break;}}void ds1302_display(){write_com(0x88);//write_nyr(tempdata[1]);write_nyr(tempdata[2]);write_data('-');write_nyr(tempdata[3]);write_data(' ');write_sfm(tempdata[4]);write_data(':');write_sfm(tempdata[5]);write_data(':');write_sfm(tempdata[6]);write_data(' ');write_xq(tempdata[7]);//if((tempdata[4]==0x13)&&(tempdata[5]==0x38)&&(tempdata[6]==0x00))//beez=1;//if((tempdata[4]==0x13)&&(tempdata[5]==0x38)&&(tempdata[6]==0x05))//beez=0;write_com(0x98);if ( tempdata[2] == 0x01 && tempdata[3] == 0x01 ){ dis("Happy New Y ear!!"); }//1月if ( tempdata[2] == 0x02 && tempdata[3] == 0x02 ){ dis(" 世界湿地日"); }//2月if ( tempdata[2] == 0x02 && tempdata[3] == 0x0d ){ dis(" 明天情人节了"); }if ( tempdata[2] == 0x02 && tempdata[3] == 0x0e ){ dis("今天是情人节"); }if ( tempdata[2] == 0x03 && tempdata[3] == 0x01 ){ dis(" 国际海豹日"); }//3月if ( tempdata[2] == 0x03 && tempdata[3] == 0x03 ){ dis(" 全国爱耳日"); }if ( tempdata[2] == 0x03 && tempdata[3] == 0x08 ){ dis(" 3.8妇女节"); }if ( tempdata[2] == 0x03 && tempdata[3] == 0x0c ){ dis("植树节"); }if ( tempdata[2] == 0x03 && tempdata[3] == 0x0e){ dis(" 国际警察日"); }if ( tempdata[2] == 0x03 && tempdata[3] == 0x0f ){ dis(" 消费者权益日"); }if ( tempdata[2] == 0x03 && tempdata[3] == 0x11 ){ dis(" 国际航海日"); }if ( tempdata[2] == 0x03 && tempdata[3] == 0x15 ){ dis(" 世界森林日"); }if ( tempdata[2] == 0x03 && tempdata[3] == 0x16 ){ dis(" 世界水日"); }if ( tempdata[2] == 0x03 && tempdata[3] == 0x17 ){ dis(" 世界气象日"); }if ( tempdata[2] == 0x03 && tempdata[3] == 0x18 ){ dis("世界防治结核病日"); }if ( tempdata[2] == 0x04 && tempdata[3] == 0x01 ){ dis("愚人节小心上当"); }//4if ( tempdata[2] == 0x04 && tempdata[3] == 0x07 ){ dis(" 世界卫生日"); }if ( tempdata[2] == 0x04 && tempdata[3] == 0x08 ){ dis(" 复活节"); }if ( tempdata[2] == 0x04 && tempdata[3] == 0x0d ){ dis(" 黑色星期五"); }if ( tempdata[2] == 0x05 && tempdata[3] == 0x01 ){ dis(" 劳动节放假"); }//5if ( tempdata[2] == 0x05 && tempdata[3] == 0x04 ){ dis(" 青年节"); }if ( tempdata[2] == 0x05 && tempdata[3] == 0x08 ){ dis(" 世界红十字日"); }if ( tempdata[2] == 0x05 && tempdata[3] == 0x05 ){ dis("近日注意母亲节"); }if ( tempdata[2] == 0x05 && tempdata[3] == 0x15 ){ dis(" 国际家庭日"); }if ( tempdata[2] == 0x05 && tempdata[3] == 0x1f ){ dis(" 世界无烟日"); }if ( tempdata[2] == 0x06 && tempdata[3] == 0x01 ){ dis(" 国际儿童节"); }//6 if ( tempdata[2] == 0x06 && tempdata[3] == 0x05 ){ dis(" 世界环境日"); }if ( tempdata[2] == 0x06 && tempdata[3] == 0x1a ){ dis("国际禁毒日"); }if ( tempdata[2] == 0x06 && tempdata[3] == 0x06 ){ dis(" 全国爱眼日"); }if ( tempdata[2] == 0x06 && tempdata[3] == 0x0d ){ dis("近日注意父亲节"); }if ( tempdata[2] == 0x06 && tempdata[3] == 0x0f ){ dis("近日注意父亲节"); }if ( tempdata[2] == 0x07 && tempdata[3] == 0x01 ){ dis("香港回归记念日"); }//7 if ( tempdata[2] == 0x07 && tempdata[3] == 0x07 ){ dis("抗日战争记念日"); }if ( tempdata[2] == 0x07 && tempdata[3] == 0x0b ){ dis(" 世界人口日"); }if ( tempdata[2] == 0x08 && tempdata[3] == 0x01 ){ dis(" 八一建军节"); }//8 if ( tempdata[2] == 0x08 && tempdata[3] == 0x08 ){ dis(" 中国男子节"); }if ( tempdata[2] == 0x08 && tempdata[3] == 0x0f ){ dis("抗战胜利记念日"); }if ( tempdata[2] == 0x09 && tempdata[3] == 0x10 ){ dis(" 中国教师节"); }//9 if ( tempdata[2] == 0x09 && tempdata[3] == 0x12 ){ dis("九·一八事变记念"); }if ( tempdata[2] == 0x09 && tempdata[3] == 0x14 ){ dis(" 国际爱牙日"); }if ( tempdata[2] == 0x09 && tempdata[3] == 0x1b ){ dis(" 世界旅游日"); }if ( tempdata[2] == 0x0a && tempdata[3] == 0x01 ){ dis("中国国庆节"); }//10 if ( tempdata[2] == 0x0a && tempdata[3] == 0x04 ){ dis("世界动物日"); }if ( tempdata[2] == 0x0a && tempdata[3] == 0x18 ){ dis("联合国日"); }if ( tempdata[2] == 0x0a && tempdata[3] == 0x0c ){ dis("明天国际教师节"); }if ( tempdata[2] == 0x0a && tempdata[3] == 0x0d ){ dis("国际教师节"); }if ( tempdata[2] == 0x0b && tempdata[3] == 0x0a ){ dis("世界青年节"); }//11 if ( tempdata[2] == 0x0b && tempdata[3] == 0x11 ){ dis(" 世界学生节"); }if ( tempdata[2] == 0x0c && tempdata[3] == 0x01 ){ dis("世界艾滋病日"); }//12 if ( tempdata[2] == 0x0c && tempdata[3] == 0x17 ){ dis("明晚平安夜"); }if ( tempdata[2] == 0x0c && tempdata[3] == 0x18 ){ dis("今晚平安夜"); }if ( tempdata[2] == 0x0c && tempdata[3] == 0x19 ){ dis("圣诞快乐"); }else{if ( tempdata[4] >= 0x04 && tempdata[4] <0x06 ){ dis("★★__▲▲__凌晨"); }if ( tempdata[4]>=0x06&&tempdata[4] <=0x08 ){ dis("☆○__▲△__早晨"); }if ( tempdata[4] >= 0x08 && tempdata[4] < 0x0c){ dis("__●__▲▲__上午"); }if ( tempdata[4] >= 0x0c&&tempdata[4]<=0x0d) { dis("____▲●▲__中午"); }if (tempdata[4] >= 0x0d&&tempdata[4] <0x12){ dis("__▲▲__●__下午"); }if (tempdata[4] >= 0x12&&tempdata[4] <0x16){ dis("△▲__●☆__晚上"); }if ( tempdata[4] >= 0x16&&tempdata[4] <=0x17){ dis("△▲__★☆__夜里"); }if ( tempdata[4] >= 0x00 && tempdata[4] <=0x04 ){ dis("__★▲▲★__深夜"); }}}DS18B20部分:#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义#include<math.h>#include<intrins.H>#define uchar unsigned char#define uint unsigned intsbit DQ=P1^3;//ds18b20 端口uint temp;uchar flag_get,count,num,minute,second,aa,bb,cc,dd,ee;uchar code tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //7段数码管段码表共阳void delay1(uchar MS);unsigned int ReadTemperature(void);void Init_DS18B20(void);unsigned char ReadOneChar(void);void WriteOneChar(unsigned char dat);void delay(unsigned int i);void b20_display(){write_com(0x90);dis("温度:");write_data(aa);//write_com(0x80+0x01);write_data(0x30+bb);//write_com(0x80+0x02);write_data(0x30+cc);//write_com(0x80+0x03);write_data(0x30+dd);//write_com(0x80+0x04);write_data('.');//write_com(0x80+0x05);write_data(0x30+ee);//write_com(0x80+0x06);write_data('C');//write_com(0x80+0x06);}void b20_init(){TMOD|=0x01;//定时器设置TH0=0xef;TL0=0xf0;IE=0x82;TR0=1;}void get_temperature(){unsigned char TempH,TempL;bb=TempH/100; //百位温度cc=(TempH%100)/10; //十位温度dd=(TempH%100)%10; //个位温度,带小数点ee=TempL;// display();if(flag_get==1) //定时读取当前温度{temp=ReadTemperature();if(temp&0x8000){aa='-';//负号标志temp=~temp; // 取反加1temp +=1;}elseaa='+';TempH=temp>>4;TempL=temp&0x0F;TempL=TempL*6/10;//小数近似处理flag_get=0;}}void tim(void) interrupt 1 using 1//中断,用于数码管扫描和温度检测间隔{TH0=0xef;//定时器重装值TL0=0xf0;num++;if (num==50){num=0;flag_get=1;//标志位有效second++;if(second>=60){second=0;minute++;}}}void delay(unsigned int i)//延时函数{while(i--); //延迟1us}void Init_DS18B20(void){unsigned char x=0;DQ = 1; //DQ复位delay(8); //稍做延时DQ = 0; //单片机将DQ拉低delay(80); //精确延时大于480usDQ = 1; //拉高总线delay(10);x=DQ; //稍做延时后如果x=0则初始化成功x=1则初始化失败delay(5);}/******************************************************************/ /* 读一个字节*/ /******************************************************************/ unsigned char ReadOneChar(void){unsigned char i=0;unsigned char dat = 0;for (i=8;i>0;i--){DQ = 0; // 给脉冲信号dat>>=1;DQ = 1; // 给脉冲信号if(DQ)dat|=0x80;delay(5);}return(dat);}/******************************************************************//* 写一个字节*//******************************************************************/ void WriteOneChar(unsigned char dat){unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;delay(5);DQ = 1;dat>>=1;}delay(5);}/******************************************************************//* 读取温度*//******************************************************************/ unsigned int ReadTemperature(void){unsigned char a=0;unsigned int b=0;unsigned int t=0;Init_DS18B20();WriteOneChar(0xCC); // 跳过读序号列号的操作WriteOneChar(0x44); // 启动温度转换delay(200);Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器)前两个就是温度a=ReadOneChar(); //低位b=ReadOneChar(); //高位b<<=8; t=a+b;return(t); }。
LCD12864.c#include "reg52.h"#include "intrins.h"#define uchar unsigned char#define uint unsigned int#define LCD_DB_PORT P0 //液晶DB0~DB7 #define LCD_START_ROW 0xc0 //起始行#define LCD_PAGE 0xb8 //页指令#define LCD_COL 0x40 //列指令//液晶引脚定义sbit LCD_DI=P2^0;sbit LCD_RW=P2^1;sbit LCD_E=P2^2;sbit LCD_CS1=P2^3;sbit LCD_CS2=P2^4;sbit LCD_RST=P2^5;bit Reverse_Display=0;//检查LCD是否忙bit LCD_Check_Busy(void){ LCD_DB_PORT=0xff;LCD_RW=1; _nop_(); LCD_DI=0;LCD_E=1; _nop_(); LCD_E=0;return(bit)(P0&0x80);}//向LCD发送命令void LCD_Write_Command(uchar c){ while(LCD_Check_Busy());LCD_DB_PORT=0xff; LCD_RW=0; _nop_(); LCD_DI=0;LCD_DB_PORT=c; LCD_E=1; _nop_(); LCD_E=0;}//向LCD发送数据void LCD_Write_Data(uchar d){ while(LCD_Check_Busy());LCD_DB_PORT=0xff;LCD_RW=0;_nop_();LCD_DI=1;//根据Reverse_Display决定是否反相显示if(!Reverse_Display)LCD_DB_PORT=d;else LCD_DB_PORT=~d;LCD_E=1;_nop_();LCD_E=0;}//初始化LCDvoid LCD_Initialize(void){ LCD_CS1=1;LCD_CS2=1;LCD_Write_Command(0x38);LCD_Write_Command(0x0f);LCD_Write_Command(0x01);LCD_Write_Command(0x06);LCD_Write_Command(LCD_START_ROW);}//通用显示函数//从第P页第L列开始显示W个字节数据,数据在r所指向的缓冲//每字节8位是垂直显示的,高位在下,低位在上//每个8*128的矩形区域为一页//整个LCD右由64*64的左半屏和64*64的右半屏构成void Common_Show(uchar P,uchar L,uchar W,uchar *r){ uchar i;if(L<64) //显示在左半屏或左右半屏{ LCD_CS1=1;LCD_CS2=0;LCD_Write_Command(LCD_PAGE+P);LCD_Write_Command(LCD_COL+L);if(L+W<64) //全部显示在左右半屏{ for(i=0;i<W;i++)LCD_Write_Data(r[i]);}else //如果越界则跨左右半屏显示{ for(i=0;i<64-L;i++)LCD_Write_Data(r[i]); //左半屏显示LCD_CS1=0;LCD_CS2=1; //右半屏显示LCD_Write_Command(LCD_PAGE+P);LCD_Write_Command(LCD_COL);for(i=64;i<W;i++)LCD_Write_Data(r[i]);}}else //全部显示在右半屏{ LCD_CS1=0;LCD_CS2=1;LCD_Write_Command(LCD_PAGE+P);LCD_Write_Command(LCD_COL+L-61);for(i=0;i<W;i++)LCD_Write_Data(r[i]);}}//显示8*16点阵字符void Display_A_Char_8X16(uchar P,uchar L,uchar *M) { Common_Show(P,L,8,M);Common_Show(P+1,L,8,M+8);}//显示一个16*16点阵汉字void Display_A_WORD(uchar P,uchar L,uchar *M) { Common_Show(P,L,16,M); //显示汉字上半部分Common_Show(P+1,L,16,M+16);}Main.c#include "reg52.h"#include "intrins.h"#include "string.h"#include "LCD_12864.c"#define uchar unsigned char#define uint unsigned int/*extern void LCD_Initialize(void);extern void Display_A_Char_8X16(uchar P,uchar L,uchar *M); extern void Display_A_WORD(uchar P,uchar L,uchar *M);//在调整日期时间时,用该位决定是否反白显示extern bit Reverse_Display=0;*/sbit SDA=P1^0; //DS1302数据线sbit CLK=P1^1; //DS1302时钟线sbit RST=P1^2; //DS1302复位线sbit k1=P3^4; //选择sbit k2=P3^5; //加sbit k3=P3^6; //减sbit k4=P3^7; //确定uchar tCount=0;//一年中每个月的天数,2月的天数由年份决定uchar MonthsDays[]={0,31,0,31,30,31,30,31,31,30,31,30,31};//所读取的日期时间uchar DateTime[7];//当前调整的时间对象:秒,分,时,日,月,年(0,1,2,3,4,6)//5对应星期,星期调节由年月日调整自动完成char Adjust_Index=-1;//水平与垂直偏移uchar H_Offset=10,V_Page_Offset=0;//年月日,星期,时分秒汉字点阵(16*16)------------------------------- uchar code DATE_TIME_WORDS[]={/*-- 文字: 年--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x00,0x20,0x18,0xC7,0x44,0x44,0x44,0x44,0xFC,0x44,0x44,0x44,0x44,0x 04,0x00,0x00,0x04,0x04,0x04,0x07,0x04,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x 04,0x04,0x00,/*-- 文字: 月--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x00,0x00,0x00,0xFE,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0xFE,0x 00,0x00,0x00,0x80,0x40,0x30,0x0F,0x02,0x02,0x02,0x02,0x02,0x02,0x42,0x82,0x7F,0x/*-- 文字: 日--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x00,0x00,0x00,0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE,0x00,0x 00,0x00,0x00,0x00,0x00,0x00,0xFF,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xFF,0x00,0x 00,0x00,0x00,/*-- 文字: 星--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x00,0x00,0x00,0xBE,0x2A,0x2A,0x2A,0xEA,0x2A,0x2A,0x2A,0x3E,0x00, 0x00,0x00,0x00,0x00,0x44,0x42,0x49,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0x49,0x41,0x 40,0x00,0x00,/*-- 文字: 期--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x00,0x04,0xFF,0x24,0x24,0x24,0xFF,0x04,0x00,0xFE,0x22,0x22,0x22,0xF E,0x00,0x00,0x88,0x48,0x2F,0x09,0x09,0x19,0xAF,0x48,0x30,0x0F,0x02,0x42,0x82,0x 7F,0x00,0x00,/*-- 文字: 时--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x00,0xFC,0x84,0x84,0x84,0xFC,0x00,0x10,0x10,0x10,0x10,0x10,0xFF,0x0x00,0x3F,0x10,0x10,0x10,0x3F,0x00,0x00,0x01,0x06,0x40,0x80,0x7F,0x0 0,0x00,0x00,/*-- 文字: 分--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x80,0x40,0x20,0x90,0x88,0x86,0x80,0x80,0x80,0x83,0x8C,0x10,0x20,0x 40,0x80,0x00,0x00,0x80,0x40,0x20,0x18,0x07,0x00,0x40,0x80,0x40,0x3F,0x00,0x00,0x 00,0x00,0x00,/*-- 文字: 秒--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x24,0x24,0xA4,0xFE,0x23,0x22,0x00,0xC0,0x38,0x00,0xFF,0x00,0x08,0x 10,0x60,0x00,0x08,0x06,0x01,0xFF,0x01,0x06,0x81,0x80,0x40,0x40,0x27,0x10,0x0C,0x 03,0x00,0x00,};//星期几的汉字点阵(16*16)----------------------------------uchar code WEEDDAY_WORDS[]={/*-- 文字: 日--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x00,0x00,0x00,0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE,0x00,0x 00,0x00,0x00,0x00,0x00,0x00,0xFF,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xFF,0x00,0x 00,0x00,0x00,/*-- 文字: 一--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x 80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x 00,0x00,0x00,/*-- 文字: 二--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x 00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x 10,0x10,0x00,/*-- 文字: 三--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x00,0x04,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x 04,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x 20,0x20,0x00,/*-- 文字: 四--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x00,0xFC,0x04,0x04,0x04,0xFC,0x04,0x04,0x04,0xFC,0x04,0x04,0x04,0x FC,0x00,0x00,0x00,0x7F,0x28,0x24,0x23,0x20,0x20,0x20,0x20,0x21,0x22,0x22,0x22,0x 7F,0x00,0x00,/*-- 文字: 五--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x00,0x02,0x42,0x42,0x42,0xC2,0x7E,0x42,0x42,0x42,0x42,0xC2,0x02,0x 02,0x00,0x00,0x40,0x40,0x40,0x40,0x78,0x47,0x40,0x40,0x40,0x40,0x40,0x7F,0x40,0x 40,0x40,0x00,/*-- 文字: 六--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x20,0x20,0x20,0x20,0x20,0x20,0x21,0x22,0x2C,0x20,0x20,0x20,0x20,0x 20,0x20,0x00,0x00,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x00,0x01,0x02,0x04,0x18,0x 60,0x00,0x00,};//半角数字点阵(8*16)---------------------------------------------------- uchar code DIGITS[]={/*-- 文字: 0 --*//*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,/*-- 文字: 1 --*//*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x 20,0x00,0x00,/*-- 文字: 2 --*//*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x 21,0x30,0x00,/*-- 文字: 3 --*//*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x 11,0x0E,0x00,/*-- 文字: 4 --*//*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x 3F,0x24,0x00,/*-- 文字: 5 --*//*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x 11,0x0E,0x00,/*-- 文字: 6 --*//*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x 11,0x0E,0x00,/*-- 文字: 7 --*//*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x 00,0x00,0x00,/*-- 文字: 8 --*//*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x 22,0x1C,0x00,/*-- 文字: 9 --*//*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x 11,0x0F,0x00,};//向DS1302写入一字节void Write_A_Byte_TO_DS1302(uchar x){ uchar i;for(i=0;i<8;i++){ SDA=x&1; CLK=1; CLK=0; x>>=1;}}//从DS1302读取一字节uchar Get_A_Byte_FROM_DS1302(void) { uchar i,b,t;for(i=0;i<8;i++){ b>>=1; t=SDA; b|=t<<7; CLK=1; CLK=0;}//BCD码转换return(b/16*10+b%16);}//从DS1302指定位置读数据uchar Read_Data(uchar addr){ uchar dat;RST=0; CLK=0; RST=1;Write_A_Byte_TO_DS1302(addr);dat=Get_A_Byte_FROM_DS1302();CLK=1; RST=0;return(dat);}//向DS1302某地址写入数据void Write_DS1302(uchar addr,uchar dat){ CLK=0; RST=1;Write_A_Byte_TO_DS1302(addr);Write_A_Byte_TO_DS1302(dat);CLK=0; RST=0;}//设置时间void SET_DS1302(void){ uchar i;Write_DS1302(0x8e,0x00);//秒分时日月年依次写入for(i=0;i<7;i++){ //秒的起始地址1000 0000(0x80)//后续依次是分,时,月,周,年,写入地址每次递增2Write_DS1302(0x80+2*i,(DateTime[i]/10<<4)|(DateTime[i]%10));}Write_DS1302(0x8e,0x80);}//读取当前日期时间void GetTime(void){ uchar i;for(i=0;i<7;i++){ DateTime[i]=Read_Data(0x81+2*i);}}//半断是否为闰年uchar isLeapYear(uint y){ return((y%4==0&&y%100!=0)||(y%400==0)); }//--------------------------------------------//求自2000.1.1开始的任何一天是星期几//函数没有通过,求出总天数后在求出星期几//因为求总天数可能会月出uint的范围//--------------------------------------------void RefreshWeekDay(void){ uint i,d,w=5; //已知1999.12.31是周五for(i=2000;i<2000+DateTime[6];i++){ d=isLeapYear(i)?366:365;w=(w+d)%7;}d=0;for(i=1;i<DateTime[4];i++)d+=MonthsDays[i];d+=DateTime[3];//保存星期,0~6表示星期日,星期一,二,、、、六,为了与DS1302的星期格式匹配,返回值需要加1DateTime[5]=(w+d)%7+1;}//年月日时分秒++/--void DateTime_Adjust(char x){ switch(Adjust_Index){ case 6: //年00-99if(x==1&&DateTime[6]<99)DateTime[6]++;if(x==-1&&DateTime[6]>0)DateTime[6]--;//获取2月天数MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28;//如果年份变化后当前月份的天数大于上限则设为上限if(DateTime[3]>MonthsDays[DateTime[4]])DateTime[3]=MonthsDays [DateTime[4]];RefreshWeekDay(); //刷新星期break;case 4: //月01-12if(x==1&&DateTime[4]<12)DateTime[4]++;if(x==-1&&DateTime[4]>1)DateTime[4]--;//获取2月份天数MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28;//如果月份变化后当前月份的天数大于上限则设为上限if(DateTime[3]>MonthsDays[DateTime[4]])DateTime[3]=MonthsDays [DateTime[4]];RefreshWeekDay(); //刷新星期break;case 3: //日00-28/29/30/31;调节之前首先根据年份得出该年中2月的天数MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28;//根据当前月份决定调节日期的上限if(x==1&&DateTime[3]<MonthsDays[DateTime[4]])DateTime[3]++;if(x==-1&&DateTime[3]>1)DateTime[3]--;RefreshWeekDay(); //刷新星期break;case 2: //时if(x==1&&DateTime[2]<23)DateTime[2]++;if(x==-1&&DateTime[3]>1)DateTime[2]--;break;case 1: //分if(x==1&&DateTime[1]<59)DateTime[1]++;if(x==-1&&DateTime[1]>1)DateTime[1]--;break;case 0: //秒if(x==1&&DateTime[0]<59)DateTime[0]++;if(x==-1&&DateTime[0]>1)DateTime[0]--;}}//定时器0每秒刷新LCD显示void T0_INT(void) interrupt 1{ TH0=-50000/256;TL0=-50000%256;if(++tCount!=2)return;tCount=0;if(Adjust_Index==-1)GetTime(); //如果未执行调整操作则正常读取当前时间//年后两位Reverse_Display=Adjust_Index==6; /*等同于{ if(Adjust_Index==6)Reverse_Display=1;else Reverse_Display=0; } */Display_A_Char_8X16(V_Page_Offset,16+H_Offset,DIGITS+DateTime [6]/10*16);Display_A_Char_8X16(V_Page_Offset,24+H_Offset,DIGITS+DateTime [6]%10*16);//月Reverse_Display=Adjust_Index==4;Display_A_Char_8X16(V_Page_Offset,48+H_Offset,DIGITS+DateTime [4]/10*16);Display_A_Char_8X16(V_Page_Offset,56+H_Offset,DIGITS+DateTime [4]%10*16);//日Reverse_Display=Adjust_Index==3;Display_A_Char_8X16(V_Page_Offset,80+H_Offset,DIGITS+DateTime [3]/10*16);Display_A_Char_8X16(V_Page_Offset,88+H_Offset,DIGITS+DateTime [3]%10*16);//星期Reverse_Display=Adjust_Index==5;Display_A_WORD(V_Page_Offset+2,96+H_Offset,WEEDDAY_WORDS +(DateTime[5]-1)*32);//时Reverse_Display=Adjust_Index==2;Display_A_Char_8X16(V_Page_Offset+5,16+H_Offset,DIGITS+DateTi me[2]/10*16);Display_A_Char_8X16(V_Page_Offset+5,24+H_Offset,DIGITS+DateTi me[2]%10*16);//分Reverse_Display=Adjust_Index==1;Display_A_Char_8X16(V_Page_Offset+5,48+H_Offset,DIGITS+DateTi me[1]/10*16);Display_A_Char_8X16(V_Page_Offset+5,56+H_Offset,DIGITS+DateTi me[1]%10*16);//秒Reverse_Display=Adjust_Index==0;Display_A_Char_8X16(V_Page_Offset+5,80+H_Offset,DIGITS+DateTi me[0]/10*16);Display_A_Char_8X16(V_Page_Offset+5,88+H_Offset,DIGITS+DateTi me[0]%10*16);}//键盘中断(INT0)void EX_INT0(void) interrupt 0{ if(k1==0) //选择调整对象{ if(Adjust_Index==-1||Adjust_Index==0)Adjust_Index=7;Adjust_Index--;if(Adjust_Index==5)Adjust_Index=4; //跳过对星期的调整}else if(k2==0)DateTime_Adjust(1); //加else if(k3==0)DateTime_Adjust(-1); //减else if(k4==0) //确定{ SET_DS1302(); //将调整后的时间写入DS1302Adjust_Index=-1; //操作索引重设为-1,时间继续正常显示}}//主程序void main(){ //液晶初始化LCD_Initialize();//显示年的固定前两位Display_A_Char_8X16(V_Page_Offset,0+H_Offset,DIGITS+2*16);Display_A_Char_8X16(V_Page_Offset,8+H_Offset,DIGITS);//显示固定汉字:年月日,星期,时分秒Display_A_WORD(V_Page_Offset,32+H_Offset,DATE_TIME_WORDS+ 0*32);Display_A_WORD(V_Page_Offset,64+H_Offset,DATE_TIME_WORDS+ 1*32);Display_A_WORD(V_Page_Offset,96+H_Offset,DATE_TIME_WORDS+ 2*32);Display_A_WORD(V_Page_Offset+2,64+H_Offset,DATE_TIME_WORD S+3*32);Display_A_WORD(V_Page_Offset+2,80+H_Offset,DATE_TIME_WORD S+4*32);Display_A_WORD(V_Page_Offset+5,32+H_Offset,DATE_TIME_WORD S+5*32);Display_A_WORD(V_Page_Offset+5,64+H_Offset,DATE_TIME_WORD S+6*32);Display_A_WORD(V_Page_Offset+5,96+H_Offset,DATE_TIME_WORD S+7*32);//允许INT0,T0中断IE=0x83;IP=0x01;IT0=0x01;TH0=-50000/256;TL0=-50000%256;TR0=1;while(1);}。
*********************************#include<>#include<>#define LCD_Data P0#define uchar unsigned charunsigned charsec,min,hour,day,month,year,cen,week, next,aa,bb,cc,dd,mm,temp0,LunarMonth, LunarDay,LunarYear;int temp;uchar tt=1;bit c_moon;bit cenbit=1;bit w;sbit LCD_RS=P2^0;sbit LCD_RW=P2^1;sbit LCD_E=P2^2;sbit PSB=P2^3;sbit DS1302_CLK=P3^7;sbit DS1302_IO=P3^6;sbit DS1302_RST=P3^5;sbit DS18B20=P2^5;sbit speak=P2^7;sbit SetKey=P1^4; // 按键功能:设置sbit SureKey=P1^5; // 按键功能:确认sbit PlusKey=P1^6; // 按键功能:加sbit ReduceKey=P1^7; // 按键功能:减sbit scl=P1^1;sbit sda=P1^0;void DisplayShengXiao(void);void delay(unsigned int a)// 延时 1MS/ 次{unsigned char i;while(--a){for(i=0;i<125;i++) ;}}void delayb(unsigned int count){while(count--);}void delays(){ ; ;}void start(){sda=1;scl=1;delays();sda=0;delays();}void stop(){sda=0;scl=1;delays();sda=1;delays();}void response(){uchar i;while((sda==1)&&i<255)i++; //给应答信号 sda=0 ;错误( while (( sda==0 )|i<255 ) i++ ;)程序进入 while 死循环scl=1;delays();scl=0; // 没有这一步出错,如果没有 sda 将保持 0 状态,一直处于应答中。
西南科技大学电子专业综合设计报告设计名称:基于单片机的多功能电子万年历系统设计姓名:学号:班级:指导教师:起止日期:西南科技大学信息工程学院制综合设计任务书学生班级:学生姓名:学号:设计名称:基于单片机的多功能电子万年历系统设计起止日期:指导教师:设计要求:基本要求:1.查阅有关资料,掌握单总线的基本通信协议及C语言的编程方法;2.用STC89C52微控制器控制DS12CR887和DS18B20的工作方式,完成多功能电子万年历系统的设计,显示部分采用LCD12864。
要求日期可显示农历,并能提示农历节日和阳历节日;要求电子万年历具有闹钟功能并能实时显示当前环境温度;3.对系统的工作的可靠性进和稳定性行分析,得出结论;4.撰写设计报告。
综合设计学生日志时间设计内容2013.11.23 熟悉题目,对研究题目做分析,具体划分为几个模块2013.11.24 LCD12864显示屏的显示模块的实现2013.11.25 DS18B20温度传感器模块的研究2013.11.26 对DS18B20和LCD12864联合设计温度显示系统2013.11.27 阅读DS12CR887的数据手册,了解芯片的功能实现2013.11.28 根据DS12CR887数据手册完成基本的驱动程序2013.11.30 在C52单片机最小系统的的基础上搭建电子万年历硬件系统,完成芯片焊接及连线2013.12.1 上网查阅阳历转换阴历的相关算法2013.12.2 完成阳历转换阴历相关算法在单片机的程序设计以及节日的显示程序2013.12.3 设计程序实现在LCD12864上显示时间,日期,农历,节日,温度等功能2013.12.4 完成闹钟程序设计2013.12.5 调试硬件系统和软件系统解决系统BUG2013.12.6 完成课程设计报告1基于单片机的多功能电子万年历系统设计摘要:电子万年历是一种通过STC52C89RC单片机编程来对不同电子芯片件进行控制、执行、数据读取、和读取的数据结果的显示的电子产品。
毕业设计(论文)论文题目:12864显示电子万年历系别:专业:班级:学号:学生姓名:指导教师:前言目录前言 (II)1绪论 (1)1.1 课题研究的背景 (1)1.2课题的研究目的与意义 (1)1.3课题解决的主要内容 (1)2系统的方案设计与论证 (4)2.1单片机芯片设计与论证 (4)方案1:采用51系列单片机作为系统控制器 (4)方案2:采用凌阳系列单片机作为系统的控制器 (4)2.2按键控制模块设计与论证 (4)2.3时钟模块设计与论证 (5)方案二:采用DS1302为计时时钟芯片 (5)方案三:采用DS12C887为计时时钟芯片 (5)2.4温度采集模块设计与论证 (5)2.5显示模块模块设计与论证 (5)3系统硬件的设计 (1)3.1 STC89C52单片机 (1)3.1.1 最小系统设计 (4)3.1.2 时钟电路 (4)3.1.3 复位电路 (5)3.2时钟芯片DS1302接口设计与性能分析 (5)3.2.1 DS1302性能简介 (5)3.2.2 DS1302接口电路设计 (1)3.3温度芯片DS18B20接口设计与性能分析 (3)3.3.1 DS18B20性能简介 (3)1.DS18B20的主要特性 (3)3.3.3 DS18B20的工作时序 (4)3.4 LCD显示模块 (1)3.4.1 液晶显示控制驱动器的特点 (1)3.4.2 液晶显示控制驱动器的引脚功能 (1)3.4.3 液晶显示控制驱动器的指令系统 (2)3.4.4 液晶显示控制驱动器的软件设计 (3)3.4.5 LCD12864的电路结构特点 (5)3.4.6 LCD12864的应用 (5)4系统软件的设计 (7)4.1主程序流程图的设计 (8)4.2程序设计 (1)4.2.1 DS1302读写程序设计 (1)4.2.2温度程序设计 (1)5系统的机体设计及调试 (2)5.1系统的模块组成 (2)5.2系统软件调试与仿真 (3)5.3系统硬件调试 (4)总结 (5)参考文献: (6)绪论摘要:本文介绍了基于STC89C52单片机的多功能电子万年历的硬件结构和软硬件设计方法。
*********************************#include<>#include<>#define LCD_Data P0#define uchar unsigned charunsigned charsec,min,hour,day,month,year,cen,week, next,aa,bb,cc,dd,mm,temp0,LunarMonth, LunarDay,LunarYear;int temp;uchar tt=1;bit c_moon;bit cenbit=1;bit w;sbit LCD_RS=P2^0;sbit LCD_RW=P2^1;sbit LCD_E=P2^2;sbit PSB=P2^3;sbit DS1302_CLK=P3^7;sbit DS1302_IO=P3^6;sbit DS1302_RST=P3^5;sbit DS18B20=P2^5;sbit speak=P2^7;sbit SetKey=P1^4; // 按键功能:设置sbit SureKey=P1^5; // 按键功能:确认sbit PlusKey=P1^6; // 按键功能:加sbit ReduceKey=P1^7; // 按键功能:减sbit scl=P1^1;sbit sda=P1^0;void DisplayShengXiao(void);void delay(unsigned int a)// 延时 1MS/ 次{unsigned char i;while(--a){for(i=0;i<125;i++) ;}}void delayb(unsigned int count){while(count--);}void delays(){ ; ;}void start(){sda=1;scl=1;delays();sda=0;delays();}void stop(){sda=0;scl=1;delays();sda=1;delays();}void response(){uchar i;while((sda==1)&&i<255)i++; //给应答信号 sda=0 ;错误( while (( sda==0 )|i<255 ) i++ ;)程序进入 while 死循环scl=1;delays();scl=0; // 没有这一步出错,如果没有 sda 将保持 0 状态,一直处于应答中。
程序停止。
delays();}void write24c02(uchar date){uchar temp,i;temp=date;for(i=0;i<8;i++){scl=0;sda=temp&0x80;delays();scl=1;delays();temp=temp<<1;}scl=0;delays();sda=1;delays();}uchar read24c02(){uchar k,i;scl=0;delays();sda=1;// 仅仅是释放数据线,可有可无for(i=0;i<8;i++){scl=1;delays();k=k<<1;if(sda)k++;scl=0;delays();}return k;}void write_24c02add(uchar address,uchar date){start();write24c02(0xa0);response();write24c02(address);response();write24c02(date);response();stop();}uchar read_24c02add(uchar address) {uchar a;start();write24c02(0xa0);response();write24c02(address);response();start();write24c02(0xa1);response();a=read24c02();stop();return a;}unsigned char DS18B20Init(){ unsigned char x;DS18B20=1;delayb(2);DS18B20=0;delayb(80);DS18B20=1;delayb(5);x=DS18B20;delayb(20);return x;}unsigned char TempRead(void){unsigned char i,dat;DS18B20=1;delayb(1);for(i=0;i<8;i++){DS18B20=0;dat=dat>>1;DS18B20=1;if(DS18B20)dat=dat|0x80;delayb(4);}return dat;}void TempWriteByte(unsigned chardat){unsigned int i;DS18B20=1;delayb(2);for(i=0;i<8;i++){DS18B20=0;DS18B20=dat&0x01;delayb(8);DS18B20=1;dat=dat>>1;delayb(2);}}int GetTemp(){float tt;unsigned char a,b;DS18B20Init();TempWriteByte(0xcc); TempWriteByte(0x44);delayb(100);DS18B20Init();TempWriteByte(0xcc); TempWriteByte(0xbe);delayb(200);a=TempRead();b=TempRead();temp=b;temp<<=8;temp=temp|a;tt=temp*;temp=tt*10+;return temp;}void WriteDs1302Byte(unsigned char temp){unsigned char i;for (i=8;i>0;i--){DS1302_IO=temp&0x01;DS1302_CLK=0;DS1302_CLK=1;temp>>=1;}}void WriteDs1302( unsigned char address,unsigned char dat ){DS1302_RST=0;DS1302_CLK=0;DS1302_RST=1;delay(1);WriteDs1302Byte(address);WriteDs1302Byte(dat);DS1302_RST=0;}unsigned char read_byte(){ unsigned char i;for(i=8;i>0;i--){if(DS1302_IO)temp0=temp0|0x80;DS1302_CLK=1;DS1302_CLK=0;temp0=temp0>>1;}return temp0;}unsigned char ReadDs1302(unsignedchar address){unsigned char temp;DS1302_RST=0;DS1302_CLK=0;DS1302_RST=1;WriteDs1302Byte(address);temp=read_byte();DS1302_RST=0;DS1302_CLK=1;return temp;}void InitDS1302(){// unsigned charSecond=ReadDs1302(0x80);// if(Second&0x80){WriteDs1302(0x8e,0x00);delay(5);WriteDs1302(0x8c,0x10);// 写入年份 10 年delay(5);WriteDs1302(0x8a,0x06);// 写入星期 6delay(5);WriteDs1302(0x88,0x11);// 定入月分 11 月delay(5);WriteDs1302(0x86,0x6);// 写入日期 6 日delay(5);WriteDs1302(0x84,0x17);// 写入小时 17 点delay(5);WriteDs1302(0x82,0x43);delay(5);WriteDs1302(0x80,0x00);// 写入秒 30 秒delay(5);WriteDs1302(0x8e,0x80);// 控制命令, WP 为 1, 禁止写操作}}/* 阳历对应的阴历数据,每年三字节,格式第一字节 BIT7- 4 位表示闰月月份,为 0, 则无闰月, BIT3-0 对应阴历第 1-4 月的大小,第二字节 BIT7- 0 对应阴历第 5-1 2 月大小,第三字节 BIT7 表示阴历第 13 月大小月分对应的位为 1, 表示农历月大( 3 0天)为 0 表示小( 29 天)第三字节 BIT6- 5 表示春节的公历月份,BIT4-0 表示春节公历日期*/code unsigned char YearCode[597]={0x04,0xAe,0x53, //1901 00x0A,0x57,0x48, //1902 30x55,0x26,0xBd, //1903 60x0d,0x26,0x50, //1904 90x0d,0x95,0x44, //1905 120x46,0xAA,0xB9, //1906 150x05,0x6A,0x4d, //1907 180x09,0xAd,0x42, //1908 210x24,0xAe,0xB6, //19090x04,0xAe,0x4A, //19100x6A,0x4d,0xBe, //19110x0A,0x4d,0x52, //19120x5d,0x52,0xBA, //19140x0B,0x54,0x4e, //19150x0d,0x6A,0x43, //1916 0x29,0x6d,0x37, //19170x09,0x5B,0x4B, //19180x74,0x9B,0xC1, //19190x04,0x97,0x54, //19200x0A,0x4B,0x48, //19210x5B,0x25,0xBC, //19220x06,0xA5,0x50, //19230x06,0xd4,0x45, //19240x4A,0xdA,0xB8, //19250x02,0xB6,0x4d, //19260x09,0x57,0x42, //19270x24,0x97,0xB7, //19280x04,0x97,0x4A, //19290x66,0x4B,0x3e, //19300x0d,0x4A,0x51, //19310x0e,0xA5,0x46, //19320x56,0xd4,0xBA, //19330x05,0xAd,0x4e, //19340x02,0xB6,0x44, //19350x39,0x37,0x38, //19360x09,0x2e,0x4B, //19370x7C,0x96,0xBf, //19380x0C,0x95,0x53, //19390x0d,0x4A,0x48, //19400x6d,0xA5,0x3B, //19410x0B,0x55,0x4f, //19420x05,0x6A,0x45, //19430x4A,0xAd,0xB9, //19440x02,0x5d,0x4d, //19450x09,0x2d,0x42, //19460x2C,0x95,0xB6, //19470x0A,0x95,0x4A, //19480x7B,0x4A,0xBd, //19490x06,0xCA,0x51, //19500x0B,0x55,0x46, //19510x55,0x5A,0xBB, //19520x04,0xdA,0x4e, //19530x0A,0x5B,0x43, //19540x35,0x2B,0xB8, //19550x05,0x2B,0x4C, //19560x8A,0x95,0x3f, //19570x06,0xAA,0x48, //19590x7A,0xd5,0x3C, //1960 0x0A,0xB5,0x4f, //19610x04,0xB6,0x45, //19620x4A,0x57,0x39, //19630x0A,0x57,0x4d, //19640x05,0x26,0x42, //19650x3e,0x93,0x35, //19660x0d,0x95,0x49, //19670x75,0xAA,0xBe, //19680x05,0x6A,0x51, //19690x09,0x6d,0x46, //19700x54,0xAe,0xBB, //19710x04,0xAd,0x4f, //19720x0A,0x4d,0x43, //19730x4d,0x26,0xB7, //19740x0d,0x25,0x4B, //19750x8d,0x52,0xBf, //19760x0B,0x54,0x52, //19770x0B,0x6A,0x47, //19780x69,0x6d,0x3C, //19790x09,0x5B,0x50, //19800x04,0x9B,0x45, //19810x4A,0x4B,0xB9, //19820x0A,0x4B,0x4d, //19830xAB,0x25,0xC2, //19840x06,0xA5,0x54, //19850x06,0xd4,0x49, //19860x6A,0xdA,0x3d, //19870x0A,0xB6,0x51, //19880x09,0x37,0x46, //19890x54,0x97,0xBB, //19900x04,0x97,0x4f, //19910x06,0x4B,0x44, //19920x36,0xA5,0x37, //19930x0e,0xA5,0x4A, //19940x86,0xB2,0xBf, //19950x05,0xAC,0x53, //19960x0A,0xB6,0x47, //19970x59,0x36,0xBC, //19980x09,0x2e,0x50, //1999 2940x0C,0x96,0x45, //2000 2970x4d,0x4A,0xB8, //2001 3000x0d,0x4A,0x4C, //2002 3030x0d,0xA5,0x41, //2003 3060x25,0xAA,0xB6, //2004 309 0x05,0x6A,0x49, //2005 3120x7A,0xAd,0xBd, //2006 3150x02,0x5d,0x52, //2007 3180x09,0x2d,0x47, //2008 3210x5C,0x95,0xBA, //2009 3240x0A,0x95,0x4e, //2010 3270x0B,0x4A,0x43, //20110x4B,0x55,0x37, //20120x0A,0xd5,0x4A, //20130x95,0x5A,0xBf, //20140x04,0xBA,0x53, //20150x0A,0x5B,0x48, //20160x65,0x2B,0xBC, //20170x05,0x2B,0x50, //20180x0A,0x93,0x45, //20190x47,0x4A,0xB9, //20200x06,0xAA,0x4C, //20210x0A,0xd5,0x41, //20220x24,0xdA,0xB6, //20230x04,0xB6,0x4A, //20240x69,0x57,0x3d, //20250x0A,0x4e,0x51, //20260x0d,0x26,0x46, //20270x5e,0x93,0x3A, //20280x0d,0x53,0x4d, //20290x05,0xAA,0x43, //20300x36,0xB5,0x37, //20310x09,0x6d,0x4B, //20320xB4,0xAe,0xBf, //20330x04,0xAd,0x53, //20340x0A,0x4d,0x48, //20350x6d,0x25,0xBC, //20360x0d,0x25,0x4f, //20370x0d,0x52,0x44, //20380x5d,0xAA,0x38, //20390x0B,0x5A,0x4C, //20400x05,0x6d,0x41, //20410x24,0xAd,0xB6, //20420x04,0x9B,0x4A, //20430x7A,0x4B,0xBe, //20440x0A,0x4B,0x51, //20450x0A,0xA5,0x46, //20460x5B,0x52,0xBA, //20470x06,0xd2,0x4e, //20480x35,0x5B,0x37, //20500x09,0x37,0x4B, //20510x84,0x97,0xC1, //20520x04,0x97,0x53, //20530x06,0x4B,0x48, //20540x66,0xA5,0x3C, //20550x0e,0xA5,0x4f, //20560x06,0xB2,0x44, //20570x4A,0xB6,0x38, //20580x0A,0xAe,0x4C, //20590x09,0x2e,0x42, //20600x3C,0x97,0x35, //20610x0C,0x96,0x49, //20620x7d,0x4A,0xBd, //20630x0d,0x4A,0x51, //20640x0d,0xA5,0x45, //20650x55,0xAA,0xBA, //20660x05,0x6A,0x4e, //20670x0A,0x6d,0x43, //20680x45,0x2e,0xB7, //20690x05,0x2d,0x4B, //20700x8A,0x95,0xBf, //20710x0A,0x95,0x53, //20720x0B,0x4A,0x47, //20730x6B,0x55,0x3B, //20740x0A,0xd5,0x4f, //20750x05,0x5A,0x45, //20760x4A,0x5d,0x38, //20770x0A,0x5B,0x4C, //20780x05,0x2B,0x42, //20790x3A,0x93,0xB6, //20800x06,0x93,0x49, //20810x77,0x29,0xBd, //20820x06,0xAA,0x51, //20830x0A,0xd5,0x46, //20840x54,0xdA,0xBA, //20850x04,0xB6,0x4e, //20860x0A,0x57,0x43, //20870x45,0x27,0x38, //20880x0d,0x26,0x4A, //20890x8e,0x93,0x3e, //20900x0d,0x52,0x52, //20910x0d,0xAA,0x47, //2092 0x66,0xB5,0x3B, //20930x04,0xAe,0x45, //20950x4A,0x4e,0xB9, //20960x0A,0x4d,0x4C, //20970x0d,0x15,0x41, //20980x2d,0x92,0xB5, //2099};void WriteDataLCD(unsigned chardat){LCD_RS=1;LCD_RW=0;LCD_E=0;delay(2);LCD_Data=dat;delay(2);LCD_E=1;delay(5);LCD_E=0;delay(5);}void WriteCommandLCD(unsigned charudat){LCD_RS=0;LCD_RW=0;LCD_E=0;delay(2);LCD_Data=udat;delay(2);LCD_E=1;delay(5);LCD_E=0;delay(5);}void LCDInit(void){WriteCommandLCD(0x30);WriteCommandLCD(0x01); WriteCommandLCD(0x06);WriteCommandLCD(0x0C);}void LCDClear(void){WriteCommandLCD(0x01);WriteCommandLCD(0x34);WriteCommandLCD(0x30);}void LCDSendWord(unsigned char *p {while(*p>0){WriteDataLCD(*p);p++;}}void LCDTestWord(bit i,unsigned char word){if(i==0){WriteCommandLCD(word);}else{WriteDataLCD(word);}}void DisplayYear(void){year=ReadDs1302(0x8d); LCDTestWord(0,0x81); LCDTestWord(1,(year/16)+0x30); LCDTestWord(1,year%16+0x30); LCDTestWord(0,0x82); LCDSendWord(" 年 "); DisplayShengXiao();}void DisplayMonth(void){month=ReadDs1302(0x89); LCDTestWord(0,0x83);if(month/16!=0){LCDTestWord(1,(month/16)+0x30); }else{LCDTestWord(1,0x20);}LCDTestWord(1,month%16+0x30);LCDTestWord(0,0x84); LCDSendWord(" 月 "); DisplayShengXiao();}void DisplayDay(void){day=ReadDs1302(0x87); LCDTestWord(0,0x85);if(day/16!=0)LCDTestWord(1,(day/16)+0x30); } else{ LCDTestWord(1,0x20);} LCDTestWord(1,day%16+0x30); LCDTestWord(0,0x86); LCDSendWord(" 日 "); DisplayShengXiao();}void DisplayHour(void){hour=ReadDs1302(0x85); LCDTestWord(0,0x88); LCDTestWord(1,(hour/16)+0x30); LCDTestWord(1,hour%16+0x30);}void DisplayMin(void){min=ReadDs1302(0x83); LCDTestWord(0,0x89);// LCDTestWord(1,0x3a); LCDSendWord(" 点 "); LCDTestWord(1,(min/16)+0x30); LCDTestWord(1,min%16+0x30); LCDSendWord(" 分 ");}void DisplaySec(void){unsigned char i=0;unsigned int a=0,b=0,c=0;sec=ReadDs1302(0x81); LCDTestWord(0,0x8c); LCDTestWord(1,(sec/16)+0x30); LCDTestWord(1,sec%16+0x30);}void DisplayTemp(void){unsigned int i;unsigned char a,b,c; WriteCommandLCD(0x8c);LCDTestWord(0,0x8d);LCDSendWord(" ");i=GetTemp();a=i/100;LCDTestWord(1,a+0x30);b=i%100/10;LCDTestWord(1,b+0x30);LCDTestWord(1,0x2e);c=i-a*100-b*10;LCDTestWord(1,c+0x30);LCDSendWord("C");}code unsigned charDayCode1[9]={0x00,0x1f,0x3b,0x5a,0x780x97,0xb5,0xd4,0xf3};code unsigned intDayCode2[3]={0x111,0x130,0x14e};// 计算公历日离当年元旦的天数 , 为了减少运算 , 用了两个表DayCode1[9],DayCode2[3]// 如果公历月在九月或前 , 天数会少于0xff, 用表 DayCode1[9], 在九月后 , 天数大于 0xff, 用表 DayCode2[3]// 如输入公历日为 8 月 1 0 日 , 则公历日离元旦天数为 DayCode1[8-1]+10-1, 如输入公历日为 11 月 10 日 , 则公历日离元旦天数为 DayCode2[11-10]+10-1/* 读取数据表中农历月的大月或小月 ,如果该月为大返回 1, 为小返回 0*/bit GetMoonDay(unsigned char LunarMonth,unsigned int TableAddr){unsigned char temp;switch (LunarMonth)//LunarMonth 指向农历月份{case 1:{temp=YearCode[TableAddr]&0x08//1 月,对应年份表里第一字节的 BIT3 位,如果是 1, 则月大,如果是 0, 则月小if (temp==0) return(0);// 为 0, 月小// 为 1, 月大}case 2:{temp=YearCode[TableAddr]&0x04; // 2月,对应年份表里第一字节的 BIT2 位,如果是 1, 则月大,如果是 0, 则月小if (temp==0) return(0);// 为 0, 月小else return(1);// 为 1, 月大}case 3:{temp=YearCode[TableAddr]&0x02; // 3月,对应第一字节的 BIT1 位,如果是 1, 则月大,如果是 0, 则月小if (temp==0) return(0);// 为 0, 月小else return(1);// 为 1, 月大}case 4:{temp=YearCode[TableAddr]&0x01; // 1月,对应第一字节的 BIT0 位,如果是 1, 则月大,如果是 0, 则月小if (temp==0) return(0);else return(1);}case 5:{temp=YearCode[TableAddr+1]&0x80; // 5月,对应第二字节的 BIT7 位,如果是 1, 则月大,如果是 0, 则月小if (temp==0) return(0);else return(1);}case 6:{temp=YearCode[TableAddr+1]&0x40; // 6月,对应第二字节的 BIT6 位,如果是 1, 则月大,如果是 0, 则月小if (temp==0) return(0);}case 7:{temp=YearCode[TableAddr+1]&0x20; // 7月,对应第二字节的 BIT5 位,如果是 1, 则月大,如果是 0, 则月小if (temp==0) return(0);else return(1);}case 8:{temp=YearCode[TableAddr+1]&0x10; // 8月,对应第二字节的 BIT4 位,如果是 1, 则月大,如果是 0, 则月小if (temp==0) return(0);else return(1);}case 9:{temp=YearCode[TableAddr+1]&0x08; // 9月,对应第二字节的 BIT3 位,如果是 1, 则月大,如果是 0, 则月小if (temp==0) return(0);else return(1);}case 10:{temp=YearCode[TableAddr+1]&0x04;//10 月,对应第二字节的 BIT2 位,如果是1, 则月大,如果是 0, 则月小if (temp==0) return(0);else return(1);}case 11:{temp=YearCode[TableAddr+1]&0x02;//11 月,对应第二字节的 BIT1 位,如果是1, 则月大,如果是 0, 则月小if (temp==0) return(0);else return(1);}case 12:{temp=YearCode[TableAddr+1]&0x01;//12 月,对应第二字节的 BIT0 位,如果是1, 则月大,如果是 0, 则月小if (temp==0) return(0);else return(1);}case 13:{temp=YearCode[TableAddr+2]&0x80;//13 月,对应第三字节的 BIT7 位,如果是1, 则月大,如果是 0, 则月小if (temp==0) return(0);else return(1);}}}void Conversion(bitcenbit,unsigned char year,unsigned charmonth,unsigned char day){unsigned chartemp1,temp2,temp3,MonthP;//temp3,temp4 分别表示春节距元旦的天数,公历日离元旦的天数unsigned int temp4,TableAddr;bit flag2,flag_y;temp1=year/16;//BCD->hex 先把数据转换为十六进制高位temp2=year%16; // 低位year=temp1*10+temp2; // 把年数据转换成 10 进制temp1=month/16; // 月份高位temp2=month%16; // 月份低位month=temp1*10+temp2; // 把月数据转换成 10 进制temp1=day/16; // 日期高位temp2=day%16; // 日期低位day=temp1*10+temp2; // 把日数据转换成 16 进制// 如果是 21 世纪TableAddr=(year+0x64-1)*0x0// 定位数据表地址 year 对应的年份表中的地址是 (year+99)*3 如 201 0 年其地址是327LCDTestWord(0,0x80);LCDSendWord("20");temp1=YearCode[TableAddr+2]&0x60;// 取当年春节所在的公历月份年份表中第三字节 BIT6-5 表示春节的公历月份temp1=_cror_(temp1,5);// 循环右移 5 位,得到春节所在的公历月份temp2=YearCode[TableAddr+2]&0x1f;// 取当年春节所在的公历日年份表中第三字节 BIT4-0 表示当年春节所在的公历日if(temp1==0x01)// 计算当年春年离当年元旦的天数 , 春节只会在公历 1 月或 2 月temp3=temp2-1;// 假如春节在公历 1 月,则元旦离春节的天数为 temp2-1 天elsetemp3=temp2+0x1f-1;// 假如春节在公历 2 月,则无理离春节的天数为 temp2+0x1f-1 天if (month<10)temp4=DayCode1[month-1]+day-1;//0 到 8 月某日距元旦的天数elsetemp4=DayCode2[month-10]+day-1;//9 月开始的某一天距元旦的天数if((month>0x02)&&(year%0x04==0))// 如果公历月大于 2 月并且该年的 2 月为闰月 , 天数加 1temp4+=1;// 计算机出公历日距元旦的天数和春节距元旦的天数,则是为了比较公历日是在春节前还是春节后// 如果 temp3>temp4 则公历日在春节之前if (temp4>=temp3)// 公历日在春节后或就是春节当日使用下面代码进行运算{temp4-=temp3;// 公历日离春节的天数因为公历日在春节后所以为 temp4-temp3month=0x01;MonthP=0x01;//LunarMonth 为月份指向 , 公历日在春节前或就是春节当日 LunarMonth 指向首月flag2=GetMoonDay(MonthP,TableAddr); //检查该农历月为大小还是小月 , 大月返回 1,小月返回 0flag_y=0;if(flag2==0)//GetMoonDay() 函数返回的是 0{temp1=0x1d;}// 小月 29 天else//GetMoonDay() 函数返回的是 1{temp1=0x1e;}// 大月 30 天temp2=YearCode[TableAddr]&0xf0;// 年份数据表中第 1 字节 BIT7-4 为闰月,为 0 则这年无闰月,如为 1, 表示有闰月temp2=_cror_(temp2,4);// 从数据表中取该年的闰月月份 , 如为 0 ,则该年无闰月 BIT3- 0 表示阴历 1 到 4 月的大小 1 为大 0 为小while(temp4>=temp1){temp4-=temp1;MonthP+=1;if(month==temp2){flag_y=~flag_y;if(flag_y==0){month+=1;}}else{month+=1;}flag2=GetMoonDay(MonthP,TableAddr);if(flag2==0){temp1=0x1d;}else{temp1=0x1e;}}day=temp4+1;}else{ // 公历日在春节前使用下面代码进行运算temp3-=temp4;// 公历日离春节的天数因为公历日在春节前所以为 temp3-temp4 if(year==0x00){year=0x63;cenbit=1;}else year-=1;TableAddr-=0x03;month=0x0c;temp2=YearCode[TableAddr]&0xf0;格式第一字节 BIT7-4 位表示闰月月份,则无闰月, BIT3-0 对应阴历第 1-4 月的小,temp2=_cror_(temp2,4);if (temp2==0)MonthP=0xelse MonthP=0x0d; ///* MonthP 为月份指向 , 如当年有闰月 , 一年有十三个月 , 月指向 1闰月指向 12*/flag_y=0;flag2=GetMoonDay(MonthP,TableAddr)if(flag2==0)temp1=0x1delse temp1=0x1e;while(temp3>temp1){temp3-=temp1;MonthP-=1;if(flag_y==0)month-=1;if(month==temp2)flag_y=~flag_y;flag2=GetMoonDay(MonthP,TableAddr)if(flag2==0)temp1=0x1d;else temp1=0x1e;}day=temp1-temp3+1;}c_moon=cenbit;temp1=year/10;temp1=_crol_(temp1,4);temp2=year%10;LunarYear=temp1|temp2;temp1=month/10;temp1=_crol_(temp1,4); temp2=month%10;LunarMonth=temp1|temp2;temp1=day/10;temp1=_crol_(temp1,4);temp2=day%10;LunarDay=temp1|temp2;}void DisplayShengXiao(void){unsigned char LunarYearD,ReYear;// 农历年份的十进制数和取模后的余数if(cen==0x19) {cenbit=1;}if(cen==0x20) {cenbit=0;}Conversion(cenbit,year,month,day);// 将公历日期转换成农历LCDTestWord(0,0x94);// 显示在 LCD 的 0X94 位置上LCDTestWord(1,LunarYear/16+0x30);// 农历年十位LCDTestWord(1,LunarYear%16+0x30);// 农历年个位LCDTestWord(1,'-');// 用 - 隔开LCDTestWord(1,LunarMonth/16+0x30);// 农历月十位LCDTestWord(1,LunarMonth%16+0x30);// 农历月个位LCDTestWord(1,'-');LCDTestWord(1,LunarDay/16+0x30);// 农历日十位LCDTestWord(1,LunarDay%16+0x30);// 农历日个位LunarYearD=(LunarYear/16)*10+LunarYea r%16; // 农历年转换成 10 进制数ReYear=LunarYearD%12;// 农历年模 12, 取余运算switch(ReYear) {case 0:LCDTestWord(0,0x93);LCDSendWord(" 龙");break; // 余 0 即整除农历龙年case 1:LCDTestWord(0,0x93);LCDSendWord(" 蛇");break; // 蛇年case 2:LCDTestWord(0,0x93);LCDSendWord(" 马");break;case 3:LCDTestWord(0,0x93);LCDSendWord(" 羊");break;case 4:LCDTestWord(0,0x93);LCDSendWord(" 猴");break;case 5:LCDTestWord(0,0x93);LCDSendWord(" 鸡");break;case 6:LCDTestWord(0,0x93);LCDSendWord(" 狗");break;case 7:LCDTestWord(0,0x93);LCDSendWord(" 猪");break;case 8:LCDTestWord(0,0x93);LCDSendWord(" 鼠");break;case 9:LCDTestWord(0,0x93);LCDSendWord(" 牛");break;case10:LCDTestWord(0,0x93);LCDSendWord("虎 ");break;case11:LCDTestWord(0,0x93);LCDSendWord("兔 ");break;}}void UpDate(void){DisplayYear();DisplayMonth();DisplayDay();DisplayWeek();DisplayHour();DisplayMin();DisplaySec();DisplayShengXiao();}void SetTime(unsigned char count) {char address,item;unsigned char max,mini;if(count<8){LCDTestWord(0,0x98); LCDSendWord(" 调整 ");if(count==7) {LCDSendWord(" 秒钟请按 + - "); address=0x81;max=59;mini=0;}if(count==2) {LCDSendWord(" 分钟请按 + - "); address=0x83;max=59;mini=0;}if(count==1) {LCDSendWord(" 小时请按 + - ");address=0x85;max=23;mini=0;}if(count==5) {LCDSendWord(" 星期请按 + - "); address=0x8b;max=7;mini=1;}if(count==3) {LCDSendWord(" 日期请按 + - ");address=0x87; max=31; mini=1;}if(count==4) {LCDSendWord(" 月份请按 + - "); address=0x89;max=12;mini=1;}if(count==6) {LCDSendWord(" 年份请按 + - "); address=0x8d;max=99;mini=0;}item=ReadDs1302(address);// 读取DS1302 某地址上的数值赋给 item item=(item/16)*10+item%16;if(PlusKey==0) //PlusKey-加{ item++; } // 数加 1if(ReduceKey==0) //ReduceKey- 减{item--; } // 数减 1if(item>max)item=mini; // 查看数值有效范围if(item<mini)item=max;WriteDs1302(0x8e,0x00);item=(item/10)*16+item%10;WriteDs1302(address-1,item); // 将调整好的 item 值写入 DS1302UpDate(); }else{if(count==8){LCDTestWord(0,0x01); WriteCommandLCD(0x0c);aa=read_24c02add(30);if(PlusKey==0) //PlusKey-加aa++; // 数加 1if(ReduceKey==0)//ReduceKey- 减aa--;write_24c02add(30,aa);LCDTestWord(0,0x80);LCDSendWord(" 请输入温度报警上");LCDTestWord(0,0x90);LCDSendWord(" 限 :");LCDTestWord(0,0x92);LCDTestWord(1,aa/10+0x30); LCDTestWord(1,aa%10+0x30); LCDSendWord(" 度 ");}if(count==9){bb=read_24c02add(31); WriteCommandLCD(0x0c);if(PlusKey==0) //PlusKey-加bb++; // 数加 1if(ReduceKey==0)//ReduceKey- 减bb--;write_24c02add(31,bb); LCDTestWord(0,0x88);LCDSendWord(" 请输入温度报警下限 :");LCDTestWord(0,0x98);LCDSendWord(" 限 :");LCDTestWord(0,0x9a);LCDTestWord(1,bb/10+0x30); LCDTestWord(1,bb%10+0x30); LCDSendWord(" 度 ");}if(count==10){cc=read_24c02add(32);LCDTestWord(0,0x01); WriteCommandLCD(0x0c); LCDTestWord(0,0x92);if(PlusKey==0) //PlusKey-加cc++; // 数加 1if(ReduceKey==0)//ReduceKey- 减cc--;write_24c02add(32,cc); LCDTestWord(0,0x80);LCDSendWord(" 请设置闹钟 1"); LCDTestWord(0,0x93);LCDSendWord(" 点 ");LCDTestWord(0,0x95);LCDSendWord(" 分 ");LCDTestWord(0,0x92);LCDTestWord(1,cc/10+0x30); LCDTestWord(1,cc%10+0x30); LCDTestWord(0,0x94);LCDTestWord(1,dd/10+0x30); LCDTestWord(1,dd%10+0x30); LCDTestWord(0,0x88);LCDSendWord(" 闹钟: "); LCDTestWord(0,0x98);LCDSendWord(" 设置闹钟小时位 ");}if(count==11){ dd=read_24c02add(33); if(PlusKey==0) //PlusKey-加dd++; // 数加 1if(ReduceKey==0)//ReduceKey- 减dd--;write_24c02add(33,dd);LCDTestWord(0,0x94);LCDTestWord(1,dd/10+0x30);LCDTestWord(1,dd%10+0x30);LCDTestWord(0,0x98);LCDSendWord(" 设置闹钟分钟位 ");}if(count==12){LCDTestWord(0,0x98);LCDSendWord(" 设置闹钟状态 ");if(PlusKey==0) //PlusKey-加mm=1;if(ReduceKey==0)//ReduceKey- 减mm=0;write_24c02add(34,mm);if(mm==1){LCDTestWord(0,0x8b);LCDSendWord(" 开");}if(mm==0){LCDTestWord(0,0x8b);LCDSendWord(" 关");}}}}void Key(void){if (SetKey==0) // 设置时间{delay(10); // 按键消抖if(SetKey==0&&w==0) // 当是正常状态时就进入调时状态{w=1; // 进入调时SetTime(next); // 调整}if(SetKey==0&&w==1) // 当是调时状态本键用于调整下一项{next++;if(next==15) {next=0;WriteCommandLCD(0x0c);}SetTime(next); // 调整}while(SetKey==0); // 等待键松开}switch(next){case 1: WriteCommandLCD(0x0f);LCDTestWord(0,0x88);break;case 2: WriteCommandLCD(0x0f);LCDTestWord(0,0x8a);break;case 3: WriteCommandLCD(0x0f);LCDTestWord(0,0x85);break;case 4: WriteCommandLCD(0x0f);LCDTestWord(0,0x83);break;case 5: WriteCommandLCD(0x0f);LCDTestWord(0,0x92);break;case 6: WriteCommandLCD(0x0f);LCDTestWord(0,0x81);break;case 7: WriteCommandLCD(0x0f);LCDTestWord(0,0x8c);break;case 8: WriteCommandLCD(0x0f);LCDTestWord(0,0x92);break;case 9: WriteCommandLCD(0x0f);LCDTestWord(0,0x9a);break;case 10: WriteCommandLCD(0x0f);LCDTestWord(0,0x92);break;case 11: WriteCommandLCD(0x0f);LCDTestWord(0,0x94);break;case 12: WriteCommandLCD(0x0f);LCDTestWord(0,0x8b);break;}if(SureKey==0) // 当在调时状态时就退出调时{delay(10); // 按键消抖if(SureKey==0&&w==1){w=0;next=0;Holidays();}while(SureKey==0); // 等待键松开}if (PlusKey==0) // 加调整{delay(10); // 按键消抖if(PlusKey==0&&w==1){SetTime(next); // 调整}while(PlusKey==0); // 等待键松开}if (ReduceKey==0) // 减调整{delay(10); // 按键消抖if(ReduceKey==0&&w==1){SetTime(next); // 调整}while(ReduceKey==0); // 等待键松开}}void beep(){ int i;uchar hour1,min1,high,low;hour1=read_24c02add(32);min1=read_24c02add(33);high=read_24c02add(30);low=read_24c02add(31);mm=read_24c02add(34);hour=ReadDs1302(0x85)/16*10+ReadDs1302(0x85)%16;min=ReadDs1302(0x83)/16*10+ReadDs1302(0x83)%16;i=GetTemp()/;//tt=1;if(mm==1){LCDTestWord(0,0x87);WriteDataLCD(0x0e);WriteDataLCD(0x0e);}if(mm==0){LCDTestWord(0,0x87);WriteDataLCD(0x01);WriteDataLCD(0x01);}if(((hour>6&&hour<23)&&sec==0&&min==0) &&mm==1){speak=0;delay(20);speak=1;delay(10);}if((hour==hour1&&min==min1)&&mm==1){speak=0;delay(20);speak=1;delay(10);}if((i+1>high||i<low)&&mm==1){speak=0;delay(150);speak=1;delay(50);}}void main(){SetKey=1;SureKey=1;PlusKey=1;ReduceKey=1;PSB=1;next=0;delayb(100);LCDInit();LCDClear();InitDS1302();while(1){ while(!next){Key();WriteCommandLCD(0x0c);DisplayYear(); // 显示年DisplayMonth(); // 显示月DisplayDay(); // 显示日DisplayWeek(); // 显示星期DisplayHour(); // 显示时DisplayMin(); // 显示分DisplaySec(); // 显示秒beep();}Key();}}31。