51单片机c语言知识电子万年历完整编辑程序
51单片机12864万年历(图片+主要程序C语言)
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("简洁界面");}。
单片机万年历C语言程序完整
sbit DQ = P3^0;
char done,count,temp,flag,up_flag,down_flag,t_value;
uchar TempBuffer[5],week_value[2];
void show_time(); //液晶显示程序
unsigned char Day;
unsigned char Month;
unsigned char Year;
unsigned char DateString[11];
unsigned char TimeString[9];
}SYSTEMTIME;//定义的时间类型
#define AM(X)X
#define PM(X)(X+12)//转成24小时制
{
unsigned char ucData;
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(ucAddr|0x01); //地址,命令
ucData = DS1302OutputByte(); //读1Byte数据
DS1302_CLK = 1;
#define DS1302_SECOND0x80 //时钟芯片的寄存器位置,存放时间
#define DS1302_MINUTE0x82
#define DS1302_HOUR0x84
#define DS1302_WEEK0x8A
#define DS1302_DAY0x86
#define DS1302_MONTH0x88
#define uchar unsigned char
基于51单片机的12864万年历
#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总线。
#51单片机12864万年历C语言
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>。
51单片机实现万年历程序文件
51单片机实现万年历利用AT89S52单片机的P0口来和另外几个口来控制1602液晶的显示和P1口还有其它口来控制ds12887时钟芯片。
设置四个按键,1个定义为时间设置功能键,一个定义为闹钟设置功能键,另外两个用来调节时间的增减。
原理图:pcb图:源程序:#include<reg52.h>#define uint unsigned int#define uchar unsigned charsbit beep=P2^0;//蜂鸣器控制口sbit timeadd=P2^1;//调节时间加sbit timesub=P2^2;//调节时间减sbit timeclk=P2^3;//闹钟设定键sbit timefun=P2^4;//时间设定键sbit lcdrs=P2^5;//液晶的命令和数据控制口sbit ledrw=P2^6;//液晶的写数据口sbit lcden=P2^7;//液晶显示模块的使能端sbit timeds=P3^3;//时钟芯片地址闸sbit timerw=P3^4;//时钟芯片读写sbit timeas=P3^5;//时钟芯片地址闸sbit timeen=P3^6;//时钟芯片片选uchar code table[]="20 - - week ";uchar code table1[]=" : : ";//要显示的字符串char num,shi,fen,miao,nian=2000,yue,ri,week,numfun,anumfun,flag,flag1; uchar leap;void delay(uint x){uchar i,j;for(i=x;i>0;i--)for(j=110;j>0;j--);}void didi(){beep=0;delay(1000);beep=1;delay(1000);}void write_(uchar ){lcdrs=0;P0=;delay(5);lcden=1;delay(20);lcden=0;}void write_date(uchar date){lcdrs=1;P0=date;delay(5);lcden=1;delay(20);lcden=0;}void write_sfm(uchar add,uchar date){ uchar shi,ge;shi=date/10;ge=date%10;write_(0x80+0x40+add);write_date(0x30+shi);write_date(0x30+ge);}void write_nyr(uchar add,uchar date){ uchar shi,ge;shi=date/10;ge=date%10;write_(0x80+add);write_date(0x30+shi);write_date(0x30+ge);}void write_zhou(uchar add,uchar date) {write_(0x80+add);write_date(0x30+date);}void write_ds(uchar add,uchar date){ timeen=0;timeas=1;timeds=1;timerw=1;P1=add;timeas=0;timerw=0;P1=date;timerw=1;timeas=1;timeen=1;}uchar read_ds(uchar add){uchar ds_date;timeas=1;timeds=1;timerw=1;timeen=0;P1=add;timeas=0;timeds=0;P1=0xff;ds_date=P1;timeds=1;timeas=1;timeen=1;return ds_date;}void keyscan(){if(flag1==1)//用来关闭闹钟铃声{if(timeadd==0){delay(5);if(timeadd==0){while(!timeadd==0);flag1=0;}}if(timesub==0){delay(5);if(timesub==0){while(!timesub==0);flag1=0;}}}if(timefun==0){delay(5);if(timefun==0){while(!timefun);flag=1;numfun++;if(numfun==1){write_(0x80+0x40+0x0a);write_(0x0f);}if(numfun==2){write_(0x80+0x40+0x07);write_(0x0f);}if(numfun==3){write_(0x80+0x40+0x04);write_(0x0f);}if(numfun==4){write_(0x80+0x0f);write_(0x0f);}if(numfun==5){write_(0x80+0x09);write_(0x0f);}if(numfun==6){write_(0x80+0x06);write_(0x0f);}if(numfun==7){write_(0x80+0x03);write_(0x0f);}if(numfun==8){numfun=0;flag=0;}}}if(numfun!=0){if(timeadd==0){delay(5);while(!timeadd);if(numfun==1){miao++;if(miao==60)miao=0;write_sfm(9,miao);write_(0x80+0x40+9);write_ds(0,miao);}if(numfun==2){fen++;if(fen==60)fen=0;write_sfm(6,fen);write_(0x80+0x40+6);write_ds(2,fen);}if(numfun==3){shi++;if(shi==24)shi=0;write_sfm(3,shi);write_(0x80+0x40+3);write_ds(4,shi);}if(numfun==4){week++;if(week==8)week=1;write_zhou(0x0f,week);write_(0x80+0x0f);write_ds(6,week);}if(numfun==5){if(nian==0){switch(yue){case 1:ri++;if(ri==32) ri=1;break;case 2:ri++;if(ri==30) ri=1;break;case 3:ri++;if(ri==32) ri=1;break;case 4:ri++;if(ri==31) ri=1;break;case 5:ri++;if(ri==32) ri=1;break;case 6:ri++;if(ri==31) ri=1;break;case 7:ri++;if(ri==32) ri=1;break;case 8:ri++;if(ri==32) ri=1;break;case 9:ri++;if(ri==31)ri=1;break;case 10:ri++;if(ri==32)ri=1;break;case 11:ri++;if(ri==31)ri=1;break;case 12:ri++;if(ri==32)ri=1;break;}}else if(leap&&yue==2){ri++;if(ri==30)ri=1;}else if(yue==2&&leap==0){ri++;if(ri==29)ri=1;}elseswitch(yue){case 1:ri++;if(ri==32) ri=1;break;case 3:ri++;if(ri==32) ri=1;break;case 4:ri++;if(ri==31) ri=1;break;case 5:ri++;if(ri==32) ri=1;break;case 6:ri++;if(ri==31) ri=1;break;case 7:ri++;if(ri==32) ri=1;break;case 8:ri++;if(ri==32) ri=1;break;case 9:ri++;if(ri==31) ri=1;break;case 10:ri++;if(ri==32) ri=1;break;case 11:ri++;if(ri==31) ri=1;break;case 12:ri++;if(ri==32) ri=1;break;}write_nyr(8,ri);write_(0x80+0x08);write_ds(7,ri);}if(numfun==6){yue++;if(yue==13)yue=0;write_nyr(5,yue);write_(0x80+0x05);write_ds(8,yue);}if(numfun==7){nian++;if(nian==100)nian=0;leap=nian%4==0&&nian%100!=0;write_nyr(2,nian);write_(0x80+2);write_ds(9,nian);}}if(timesub==0){delay(5);while(!timesub);if(numfun==1){miao--;if(miao==-1)miao=59;write_sfm(9,miao);write_(0x80+0x40+9);write_ds(0,miao);}if(numfun==2){fen--;if(fen==-1)fen=59;write_sfm(6,fen);write_(0x80+0x40+6);write_ds(2,fen);}if(numfun==3){shi--;if(shi==-1)shi=23;write_sfm(3,shi);write_(0x80+0x40+3);write_ds(4,shi);}if(numfun==4){week--;if(week==0)week=7;write_zhou(0x0f,week);write_(0x80+0x0f);write_ds(6,week);}if(numfun==5){if(nian==0){switch(yue){case 1:ri--;if(ri==0) ri=31;break;case 2:ri--;if(ri==0) ri=29;break;case 3:ri--;if(ri==0) ri=31;break;case 4:ri--;if(ri==0) ri=30;break;case 5:ri--;if(ri==0) ri=31;break;case 6:ri--;if(ri==0) ri=30;break;case 7:ri--;if(ri==0) ri=31;break;case 8:ri--;if(ri==0) ri=31;break;case 9:ri--;if(ri==0) ri=30;break;case 10:ri--;if(ri==0) ri=31;break;case 11:ri--;if(ri==0) ri=30;break;case 12:ri--;if(ri==0) ri=31;break;}}else if(leap&&yue==2){ri--;if(ri==0)ri=29;}else if(yue==2&&leap==0){ri--;if(ri==0)ri=28;}elseswitch(yue){case 1:ri--;if(ri==0) ri=31;break;case 3:ri--;if(ri==0) ri=31;break;case 4:ri--;if(ri==0) ri=30;break;case 5:ri--;if(ri==0) ri=31;break;case 6:ri--;if(ri==0) ri=30;break;case 7:ri--;if(ri==0) ri=31;break;case 8:ri--;if(ri==0) ri=31;break;case 9:ri--;if(ri==0) ri=30;break;case 10:ri--;if(ri==0) ri=31;break;case 11:ri--;if(ri==0) ri=30;break;case 12:ri--;if(ri==0) ri=31;break;}write_nyr(8,ri);write_(0x80+0x08);write_ds(7,ri);}if(numfun==6){yue--;if(yue==-1)yue=12;write_nyr(5,yue);write_(0x80+0x05);write_ds(8,yue);}if(numfun==7){nian--;if(nian==-1)nian=99;leap=nian%4==0&&nian%100!=0;write_nyr(2,nian);write_(0x80+2);write_ds(9,nian);}}}}void set_alarm(){uchar ashi,afen,amiao;if(timeclk==0)//判断是否按下闹钟设定键{delay(5);//延时消抖if(timeclk==0){while(!timeclk);anumfun++;//按键次数加1if(anumfun==1){flag=1;write_(0x80+0x40+0x0a);write_(0x0f);}if(anumfun==2){flag=1;write_(0x80+0x40+0x07);write_(0x0f);}if(anumfun==3){flag=1;write_(0x80+0x40+0x04);write_(0x0f);}if(anumfun==4){flag=0;anumfun=0;}}}if(anumfun!=0){if(timeadd==0)//如果加功能键按下{delay(5);while(!timeadd);if(anumfun==1) //设定秒{amiao++;if(amiao==60)amiao=0;write_sfm(9,amiao);write_(0x80+0x40+9);write_ds(1,amiao);}if(anumfun==2){afen++;if(afen==60)afen=0;write_sfm(6,afen);write_(0x80+0x40+6);write_ds(3,afen);}if(anumfun==3){ashi++;if(ashi==24)ashi=0;write_sfm(3,ashi);write_(0x80+0x40+3);write_ds(5,ashi);}}}if(anumfun!=0){if(timesub==0){delay(5);while(!timesub);if(anumfun==1){amiao--;if(amiao==-1)amiao=59;write_sfm(9,amiao);write_(0x80+0x40+9);write_ds(1,amiao);}if(anumfun==2){afen--;if(afen==-1)afen=59;write_sfm(6,afen);write_(0x80+0x40+6);write_ds(3,afen);}if(anumfun==3){ashi--;if(ashi==-1)ashi=23;write_sfm(3,ashi);write_(0x80+0x40+3);write_ds(5,ashi);}}}}void init(){EA=1;//开总中断EX0=1;//开外部中断0IT0=1;//设定触发方式为负跳变沿有效lcden=0;//选通液晶显示屏ledrw=0;//设定液晶显示屏的读写方式为读write_(0x38);//设置液晶显示模式为16*2显示,5*7点阵,8位数据接口 write_(0x0c);//打开显示,并使光标不显示也不闪烁write_(0x06);//光标指针每次自动加1write_(1);//清屏write_(0x80);//送地址指针for(num=0;num<16;num++){write_date(table[num]);delay(5);}write_(0x80+0x40);//写到第二行for(num=0;num<11;num++){write_date(table1[num]);delay(5);}write_ds(0x0a,0x20);//开启时钟芯片振荡器write_ds(0x0b,0x26);//开启闹钟read_ds(0x0c);//读取时钟芯片c寄存器}void main(){init();while(1){keyscan();set_alarm();if(flag1==1)didi();if(flag==0){//读取时间miao=read_ds(0x00);fen=read_ds(0x02);shi=read_ds(0x04);yue=read_ds(0x08);ri=read_ds(0x07);nian=read_ds(0x09);week=read_ds(0x06);//写入液晶显示屏write_sfm(9,miao);write_sfm(6,fen);write_sfm(3,shi);write_nyr(2,nian);write_nyr(5,yue);write_nyr(8,ri);write_zhou(0x0f,week);}}}void exter() interrupt 0{flag1=1;read_ds(0x0c);//读时钟芯片c寄存器。
单片机万年历c语言程序
}
}
void time_1() interrupt 1
{
TH0 = (65536 - 1000) / 256;
TL0 = (65536 - 1000) % 256;
time++;
if(time == 2000)
{
time = 0;
/******************************************************************/
unsigned char code str[] = {
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff
};
unsigned char su[] = {
10,10,10,10,10,10,10,10
};
void delay_SMG(unsigned char t)
}
IN_key();
if(SURE == 1) //按下确认键 确认日期
{
if(flag_led > 0)
{
strl_led[flag_led] = day_add;
flag_led = 0;
SURE = 0;
day_add = 0;
lei = P3 & 0xf0;
zong = hang | lei;
switch (zong)
{
case 0x7e: key = 1; //模式选择按键
flag_led ++;
if(flag_led > 6) flag_led = 0;
51电子日历C程序
#define SYS_CLOCK_EN 1#if SYS_CLOCK_EN#include "typedef.h"#include "reg52.h"#include "string.h"#include "stdlib.h"#include "Stdio.h"#define FOSC 22118400L#define MACHINE_NUM 12 /*根据需要调整,如:W777E58=4*/#define TICKS_PER_SEC 10 /* # of clock ticks to obtain 1 second */#define CLK_DATE_EN 1 /* Enable DATE (when 1) */#define ENTER_CRITICAL() EA=1#define EXIT_CRITICAL() EA=0#if CLK_DATE_ENtypedef struct clk_month{UCHAR MonthDays; /* Number of days in each month */char *MonthName; /* Name of the month */UCHAR MonthVal; /* Value used to compute day of the week */} CLK_MONTH;#endifstatic UCHAR ClkTickCtr; /* Counter used to keep track of system clock ticks */static UCHAR ClkHr;static UCHAR ClkMin;static UCHAR ClkSec; /* Counters for local TIME*/#if CLK_DATE_ENstatic UCHAR ClkDay; /* Counters for local DATE */static UCHAR ClkDOW; /* Day of week (0 is Sunday)*/static UCHAR ClkMonth;static UINT ClkYear;#endif/****************************************************************************** ***************************** FUNCTION PROTOTYPES******************************************************************************* ***************************/static BOOL ClkUpdateTime(void);#if CLK_DATE_ENstatic BOOL ClkIsLeapYear(UINT year);static void ClkUpdateDate(void);static void ClkUpdateDOW(void);#endifvoid Init_sys_timer(void);void Sys_clk_init(void);void Sys_clk_task(void);void Clk_format_time(UCHAR mode, char *s);void Clk_set_time(UCHAR hr, UCHAR min, UCHAR sec);int Cmp_now_time(UCHAR hr, UCHAR min, UCHAR sec);#if CLK_DATE_ENvoid Clk_format_date(UCHAR mode, char *s);void Clk_set_date(UCHAR month, UCHAR day, UINT year);void Clk_set_date_time(UCHAR month, UCHAR day, UINT year, UCHAR hr, UCHAR min, UCHAR sec);int Cmp_now_date_time(UCHAR month, UCHAR day, UINT year, UCHAR hr, UCHAR min, UCHAR sec);#endif/****************************************************************************** ***************************/#if CLK_DATE_ENstatic char code *ClkDOWTbl[] = { /* NAME FOR EACH DAY OF THE WEEK */"Sunday ","Monday ","Tuesday ","Wednesday ","Thursday ","Friday ","Saturday "};static CLK_MONTH code ClkMonthTbl[] = { /* MONTHS TABLE */{0, "", 0}, /* Invalid month */{31, "January ", 6}, /* January */{28, "February ", 2}, /* February (note leap years are handled by code) */{31, "March ", 2}, /* March */{30, "April ", 5}, /* April */{31, "May ", 0}, /* May */{30, "June ", 3}, /* June */{31, "July ", 5}, /* July */{31, "August ", 1}, /* August */{30, "September ", 4}, /* September */{31, "October ", 6}, /* October */{30, "November ", 2}, /* November */{31, "December ", 4} /* December */};#endif/******************************************************************************** *************************** TIME-OF-DAY CLOCK TASK** Description : This task is created by Sys_clk_init() and is responsible for updating the time and date.* Sys_clk_task() executes every second.* Arguments : None.* Returns : None.* Notes : CLK_DL Y_TICKS must be set to produce 1 second delays.******************************************************************************* ***************************/void Sys_clk_task (void){if(++ClkTickCtr==TICKS_PER_SEC){ClkTickCtr=0;if (ClkUpdateTime() == TRUE){#if CLK_DATE_ENClkUpdateDate(); /* And date if a new day (i.e. MM-DD-YY) */#endif}}}void Sys_tick_isr(void) interrupt 5 using 3{TF2=0;Sys_clk_task();}void Init_sys_timer(void){BYTE_WORD Init_value;Sys_clk_init();T2CON=0x00;Init_value.word=FOSC/(TICKS_PER_SEC*MACHINE_NUM);TH2=RCAP2H=-Init_value.bytes.high;TL2=RCAP2L=-Init_value.bytes.low;ET2=1;TR2=1;//TMOD&=0xF0; //使用定时器0,但在中断中需要重新赋初值,因而我更倾向用Timer2//TMOD|=0x01;// Init_value.word=FOSC/(TICKS_PER_SEC*MACHINE_NUM);//TH0=-Init_value.bytes.high;//TL0=-Init_value.bytes.low;//ET0=1;//TR0=1;}/******************************************************************************** *************************** TIME MODULE INITIALIZATION* TIME-OF-DAY CLOCK INITIALIZATION** Description : This function initializes the time module. The time of day clock task will be created* by this function.* Arguments : None* Returns : None.******************************************************************************* ***************************/void Sys_clk_init (void){ClkTickCtr = 0;Clk_set_time(11,32,0);#if CLK_DATE_ENClk_set_date(5,28,2002);#endif}/******************************************************************************** *************************** FORMAT CURRENT DATE INTO STRING** Description : Formats the current date into an ASCII string.* Arguments : mode is the format type:* 1 will format the time as "MM-DD-YY" (needs at least 9 characters)* 2 will format the time as "Day Month DD, YYYY" (needs at least30 characters)* 3 will format the time as "YYYY-MM-DD" (needs at least 11 characters)* s is a pointer to the destination string. The destination string must be large* enough to hold the formatted date.* contain* Returns : None.* Notes : - A 'switch' statement has been used to allow you to add your own date formats. For* example, you could display the date in French, Spanish, German etc. by assigning* numbers for those types of conversions.* - This function assumes that strcpy(), strcat() and itoa() are reentrant.******************************************************************************* ***************************/#if CLK_DATE_ENvoid Clk_format_date (UCHAR mode, char *s){UINT year;char str[5];switch (mode){case 1:strcpy(s, "MM-DD-YY"); /* Create the template for the selected format */s[0] = ClkMonth / 10 + '0'; /* Convert DATE to ASCII */s[1] = ClkMonth % 10 + '0';s[3] = ClkDay / 10 + '0';s[4] = ClkDay % 10 + '0';year = ClkYear % 100;s[6] = year / 10 + '0';s[7] = year % 10 + '0';break;case 2:strcpy(s, ClkDOWTbl[ClkDOW]); /* Get the day of the week */strcat(s, ClkMonthTbl[ClkMonth].MonthName); /* Get name of month */if (ClkDay < 10){str[0] = ClkDay + '0';str[1] = 0;}else{str[0] = ClkDay / 10 + '0';str[1] = ClkDay % 10 + '0';str[2] = 0;}strcat(s, str);strcat(s, ", ");sprintf(str,"%d",ClkYear);strcat(s, str);break;case 3:strcpy(s, "YYYY-MM-DD"); /* Create the template for the selected format */s[0] = year / 1000 + '0';year = year % 1000;s[1] = year / 100 + '0';year = year % 100;s[2] = year / 10 + '0';s[3] = year % 10 + '0';s[5] = ClkMonth / 10 + '0'; /* Convert DATE to ASCII */s[6] = ClkMonth % 10 + '0';s[8] = ClkDay / 10 + '0';s[9] = ClkDay % 10 + '0';break;default:strcpy(s, "?");break;}}#endif/******************************************************************************** *************************** FORMAT CURRENT TIME INTO STRING** Description : Formats the current time into an ASCII string.* Arguments : mode is the format type:* 1 will format the time as "HH:MM:SS" (24 Hour format)* (needs at least 9 characters)* 2 will format the time as "HH:MM:SS AM" (With AM/PM indication)* (needs at least 13 characters)* s is a pointer to the destination string. The destination string must be large* enough to hold the formatted time.* contain* Returns : None.* Notes : - A 'switch' statement has been used to allow you to add your own time formats. * - This function assumes that strcpy() is reentrant.******************************************************************************* ***************************/void Clk_format_time (UCHAR mode, char *s){UCHAR hr;switch (mode){case 1:strcpy(s, "HH:MM:SS"); /* Create the template for the selected format */s[0] = ClkHr / 10 + '0'; /* Convert TIME to ASCII */s[1] = ClkHr % 10 + '0';s[3] = ClkMin / 10 + '0';s[4] = ClkMin % 10 + '0';s[6] = ClkSec / 10 + '0';s[7] = ClkSec % 10 + '0';break;case 2:strcpy(s, "HH:MM:SS AM"); /* Create the template for the selected format */s[9] = (ClkHr >= 12) ? 'P' : 'A'; /* Set AM or PM indicator */if (ClkHr > 12){ /* Adjust time to be displayed */hr = ClkHr - 12;}else{hr = ClkHr;}s[0] = hr / 10 + '0'; /* Convert TIME to ASCII */s[1] = hr % 10 + '0';s[3] = ClkMin / 10 + '0';s[4] = ClkMin % 10 + '0';s[6] = ClkSec / 10 + '0';s[7] = ClkSec % 10 + '0';break;default:strcpy(s, "?");break;}}/******************************************************************************** *************************** UPDATE THE TIME** Description : This function is called to update the time (i.e. hours, minutes and seconds)* Arguments : None.* Returns : TRUE if we have completed one day.* FALSE otherwise* Notes : This function updates ClkSec, ClkMin and ClkHr.******************************************************************************* ***************************/static BOOL ClkUpdateTime (void){BOOL newday;newday = FALSE; /* Assume that we haven't completed one whole day yet */if (ClkSec >= 59){ /* See if we have completed one minute yet */ClkSec = 0; /* Yes, clear seconds */if (ClkMin >= 59){ /* See if we have completed one hour yet */ClkMin = 0; /* Yes, clear minutes */if (ClkHr >= 23){ /* See if we have completed one day yet */ClkHr = 0; /* Yes, clear hours ... */newday = TRUE; /* ... change flag to indicate we have a new day */}else{ClkHr++; /* No, increment hours */}}else{ClkMin++; /* No, increment minutes */}}else{ClkSec++; /* No, increment seconds */}return (newday);}/******************************************************************************** *************************** SET TIME ONL Y** Description : Set the time-of-day clock* Arguments : hr is the desired hour (0..23)* min is the desired minutes (0..59)* sec is the desired seconds (0..59)* Returns : None.* Notes : It is assumed that you are specifying a correct time (i.e. there is no range checking* done by this function).******************************************************************************* ***************************/void Clk_set_time (UCHAR hr, UCHAR min, UCHAR sec){ENTER_CRITICAL(); /* Gain exclusive access to time-of-day clock */ClkHr = hr;ClkMin = min;ClkSec = sec;EXIT_CRITICAL(); /* Release access to time-of-day clock */}/******************************************************************************** *************************** DETERMINE IF WE HA VE A LEAP YEAR** Description : This function determines whether the 'year' passed as an argument is a leap year.* Arguments : year is the year to check for leap year.* Returns : TRUE if 'year' is a leap year.* FALSE if 'year' is NOT a leap year.******************************************************************************* ***************************/#if CLK_DATE_ENstatic BOOL ClkIsLeapYear(UINT year){if (!(year % 4) && (year % 100) || !(year % 400)){return TRUE;}else{return (FALSE);}}#endif/******************************************************************************** *************************** SET DA TE ONL Y** Description : Set the date of the time-of-day clock* Arguments : month is the desired month (1..12)* day is the desired day (1..31)* year is the desired year (CLK_TS_BASE_YEAR .. CLK_TS_BASE_YEAR+63)* Returns : None.* Notes : It is assumed that you are specifying a correct date (i.e. there is no range checking* done by this function).******************************************************************************* ***************************/#if CLK_DATE_ENvoid Clk_set_date (UCHAR month, UCHAR day, UINT year){ENTER_CRITICAL();ClkMonth = month;ClkDay = day;ClkYear = year;ClkUpdateDOW();EXIT_CRITICAL();}#endif/******************************************************************************** *************************** SET DATE AND TIME** Description : Set the date and time of the time-of-day clock* Arguments : month is the desired month (1..12)* day is the desired day (1..31)* year is the desired year (2xxx)* hr is the desired hour (0..23)* min is the desired minutes (0..59)* sec is the desired seconds (0..59)* Returns : None.* Notes : It is assumed that you are specifying a correct date and time (i.e. there is no range* checking done by this function).******************************************************************************* ***************************/#if CLK_DATE_ENvoid Clk_set_date_time (UCHAR month, UCHAR day, UINT year, UCHAR hr, UCHAR min,UCHAR sec){ENTER_CRITICAL(); /* Gain exclusive access to time-of-day clock */ClkMonth = month;ClkDay = day;ClkYear = year;ClkHr = hr;ClkMin = min;ClkSec = sec;ClkUpdateDOW(); /* Compute the day of the week (i.e. Sunday ...) */EXIT_CRITICAL(); /* Release access to time-of-day clock */}#endif/******************************************************************************** *************************** UPDATE THE DATE** Description : This function is called to update the date (i.e. month, day and year)* Arguments : None.* Returns : None.* Notes : This function updates ClkDay, ClkMonth, ClkYear and ClkDOW.******************************************************************************* ***************************/#if CLK_DATE_ENstatic void ClkUpdateDate (void){BOOL newmonth;newmonth = TRUE;if (ClkDay >= ClkMonthTbl[ClkMonth].MonthDays) { /* Last day of the month? */if (ClkMonth == 2) { /* Is this February? */if (ClkIsLeapYear(ClkYear) == TRUE) { /* Yes, Is this a leap year? */if (ClkDay >= 29) { /* Yes, Last day in february? */ClkDay = 1; /* Yes, Set to 1st day in March */} else {ClkDay++;newmonth = FALSE;}} else {ClkDay = 1;}} else {ClkDay = 1;}} else {ClkDay++;newmonth = FALSE;}if (newmonth == TRUE) { /* See if we have completed a month */if (ClkMonth >= 12) { /* Yes, Is this december ? */ClkMonth = 1; /* Yes, set month to january... */ClkYear++; /* ...we have a new year! */} else {ClkMonth++; /* No, increment the month */}}ClkUpdateDOW(); /* Compute the day of the week (i.e. Sunday ...) */}#endif/******************************************************************************** *************************** COMPUTE DAY-OF-WEEK** Description : This function computes the day of the week (0 == Sunday) based on the current month,* day and year.* Arguments : None.* Returns : None.* Notes : - This function updates ClkDOW.* - This function is called by ClkUpdateDate().**********************************************************************************************************/#if CLK_DATE_ENstatic void ClkUpdateDOW (void){UINT dow;dow = ClkDay + ClkMonthTbl[ClkMonth].MonthVal;if (ClkMonth < 3){if (ClkIsLeapYear(ClkYear)){dow--;}}dow += ClkYear + (ClkYear / 4);dow += (ClkYear / 400) - (ClkYear / 100);dow %= 7;ClkDOW = dow;}#endifint Cmp_now_time(UCHAR hr, UCHAR min, UCHAR sec){if(ClkHr!=hr)return(hr-ClkHr);else if(ClkMin!= min)return(min-ClkMin);elsereturn(sec-ClkSec);}#if CLK_DATE_ENint Cmp_now_date_time(UCHAR month, UCHAR day, UINT year, UCHAR hr, UCHAR min, UCHAR sec){if(ClkYear!=year)return(year-ClkYear);else if(ClkMonth!=month)return(month-ClkMonth);else if(ClkDay!=day)return(day-ClkDay);else if(ClkHr!=hr)return(hr-ClkHr);else if(ClkMin!= min)return(min-ClkMin);elsereturn(sec-ClkSec); }#endif#endif。
51单片机万年历毕设程序各种功能
#include<reg52.h>//#include"DS18B20_3.H"#include <string.h>#include <intrins.h>#define uint unsigned int#define uchar unsigned char#define wd 1 //定义是否有温度功能=0时无温度,=1时有温度#define yh 0x80 //LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1(100000000=80)#define er 0x80+0x40 //LCD第二行初始位置(因为第二行第一个字符位置地址是0x40)//液晶屏的与C51之间的引脚连接定义(显示数据线接C51的P0口)sbit en=P2^7;sbit rw=P2^6; //如果硬件上rw接地,就不用写这句和后面的rw=0了sbit rs=P2^5; //校时按键与C51的引脚连接定义sbit menu=P3^0; //菜单键sbit set=P3^1; //设置键sbit add=P3^2; //加键sbit dec=P3^3; //减键sbit ensure=P3^4; //确认键sbit DQ=P2^0; //sbit buzzer=P1^4; //蜂鸣器,通过三极管8550驱动,端口低电平响sbit led=P2^4; //LCD背光开关bit led1=1;unsigned char temp_miao;unsigned char bltime; //背光亮的时间//DS1302时钟芯片与C51之间的引脚连接定义sbit IO=P1^1;sbit SCLK=P1^0;sbit RST=P1^2;uchar a,miao,shi,fen,ri,yue,nian,week,setn,temp;uint flag;//flag用于读取头文件中的温度值,和显示温度值bit c_moon;uchar nz_shi=12,nz_fen=0,nz_miao=0,setNZn; //定义闹钟变量uchar shangyimiao,bsn,temp_hour; //记录上一秒时间uchar T_NL_NZ; //计数器bit timerOn=0; //闹钟启用标志位bit baoshi=0; //整点报时标志位bit p_r=0; //平年/润年=0表示平年,=1表示润年data uchar year_moon,month_moon,day_moon,week;sbit ACC0=ACC^0;sbit ACC7=ACC^7;ACC累加器=AACC.0=E0H//********阳历转换阴历表************************************code uchar year_code[597]={ 0x04,0xAe,0x53, 0x0A,0x57,0x48, 0x55,0x26,0xBd, 0x0d,0x26,0x50, 0x0d,0x95,0x44, 0x46,0xAA,0xB9, 0x05,0x6A,0x4d, 0x09,0xAd,0x42, 0x24,0xAe,0xB6, 0x04,0xAe,0x4A, 0x6A,0x4d,0xBe, 0x0A,0x4d,0x52,0x0d,0x25,0x46, 0x5d,0x52,0xBA, 0x0B,0x54,0x4e, 0x0d,0x6A,0x43, 0x29,0x6d,0x37, 0x09,0x5B,0x4B, 0x74,0x9B,0xC1, 0x04,0x97,0x54, 0x0A,0x4B,0x48,0x5B,0x25,0xBC, 0x06,0xA5,0x50, 0x06,0xd4,0x45, 0x4A,0xdA,0xB8, 0x02,0xB6,0x4d, 0x09,0x57,0x42, 0x24,0x97,0xB7, 0x04,0x97,0x4A,0x66,0x4B,0x3e, 0x0d,0x4A,0x51, 0x0e,0xA5,0x46, 0x56,0xd4,0xBA, 0x05,0xAd,0x4e, 0x02,0xB6,0x44, 0x39,0x37,0x38, 0x09,0x2e,0x4B,0x7C,0x96,0xBf, 0x0C,0x95,0x53, 0x0d,0x4A,0x48, 0x6d,0xA5,0x3B,0x0B,0x55,0x4f, 0x05,0x6A,0x45, 0x4A,0xAd,0xB9, 0x02,0x5d,0x4d,0x09,0x2d,0x42, 0x2C,0x95,0xB6, 0x0A,0x95,0x4A, 0x7B,0x4A,0xBd,0x06,0xCA,0x51, 0x0B,0x55,0x46, 0x55,0x5A,0xBB, 0x04,0xdA,0x4e,0x0A,0x5B,0x43, 0x35,0x2B,0xB8, 0x05,0x2B,0x4C, 0x8A,0x95,0x3f,0x0e,0x95,0x52, 0x06,0xAA,0x48, 0x7A,0xd5,0x3C, 0x0A,0xB5,0x4f,0x04,0xB6,0x45, 0x4A,0x57,0x39, 0x0A,0x57,0x4d, 0x05,0x26,0x42,0x3e,0x93,0x35, 0x0d,0x95,0x49, 0x75,0xAA,0xBe, 0x05,0x6A,0x51,0x09,0x6d,0x46, 0x54,0xAe,0xBB, 0x04,0xAd,0x4f, 0x0A,0x4d,0x43,0x4d,0x26,0xB7, 0x0d,0x25,0x4B, 0x8d,0x52,0xBf, 0x0B,0x54,0x52, 0x0B,0x6A,0x47,0x69,0x6d,0x3C, 0x09,0x5B,0x50, 0x04,0x9B,0x45, 0x4A,0x4B,0xB9,0x0A,0x4B,0x4d, 0xAB,0x25,0xC2, 0x06,0xA5,0x54, 0x06,0xd4,0x49,0x6A,0xdA,0x3d, 0x0A,0xB6,0x51, 0x09,0x37,0x46, 0x54,0x97,0xBB,0x04,0x97,0x4f, 0x06,0x4B,0x44, 0x36,0xA5,0x37, 0x0e,0xA5,0x4A,0x86,0xB2,0xBf, 0x05,0xAC,0x53, 0x0A,0xB6,0x47, 0x59,0x36,0xBC,0x09,0x2e,0x50, 0x0C,0x96,0x45, 0x4d,0x4A,0xB8, 0x0d,0x4A,0x4C,0x0d,0xA5,0x41, 0x25,0xAA,0xB6, 0x05,0x6A,0x49, 0x7A,0xAd,0xBd,0x02,0x5d,0x52, 0x09,0x2d,0x47, 0x5C,0x95,0xBA, 0x0A,0x95,0x4e, 0x0B,0x4A,0x43, 0x4B,0x55,0x37, 0x0A,0xd5,0x4A, 0x95,0x5A,0xBf, 0x04,0xBA,0x53, 0x0A,0x5B,0x48, 0x65,0x2B,0xBC, 0x05,0x2B,0x50, 0x0A,0x93,0x45, 0x47,0x4A,0xB9, 0x06,0xAA,0x4C, 0x0A,0xd5,0x41,0x24,0xdA,0xB6, 0x04,0xB6,0x4A, 0x69,0x57,0x3d, 0x0A,0x4e,0x51,0x0d,0x26,0x46, 0x5e,0x93,0x3A, 0x0d,0x53,0x4d, 0x05,0xAA,0x43, 0x36,0xB5,0x37, 0x09,0x6d,0x4B, 0xB4,0xAe,0xBf, 0x04,0xAd,0x53,0x0A,0x4d,0x48, 0x6d,0x25,0xBC, 0x0d,0x25,0x4f, 0x0d,0x52,0x44, 0x5d,0xAA,0x38, 0x0B,0x5A,0x4C, 0x05,0x6d,0x41, 0x24,0xAd,0xB6,0x04,0x9B,0x4A, 0x7A,0x4B,0xBe, 0x0A,0x4B,0x51, 0x0A,0xA5,0x46,0x5B,0x52,0xBA, 0x06,0xd2,0x4e, 0x0A,0xdA,0x42, 0x35,0x5B,0x37,0x09,0x37,0x4B, 0x84,0x97,0xC1, 0x04,0x97,0x53, 0x06,0x4B,0x48,0x66,0xA5,0x3C, 0x0e,0xA5,0x4f, 0x06,0xB2,0x44, 0x4A,0xB6,0x38, 0x0A,0xAe,0x4C, 0x09,0x2e,0x42, 0x3C,0x97,0x35, 0x0C,0x96,0x49,0x7d,0x4A,0xBd, 0x0d,0x4A,0x51, 0x0d,0xA5,0x45, 0x55,0xAA,0xBA,0x05,0x6A,0x4e, 0x0A,0x6d,0x43, 0x45,0x2e,0xB7, 0x05,0x2d,0x4B,0x8A,0x95,0xBf, 0x0A,0x95,0x53, 0x0B,0x4A,0x47, 0x6B,0x55,0x3B,0x0A,0xd5,0x4f, 0x05,0x5A,0x45, 0x4A,0x5d,0x38, 0x0A,0x5B,0x4C, 0x05,0x2B,0x42, 0x3A,0x93,0xB6, 0x06,0x93,0x49, 0x77,0x29,0xBd, 0x06,0xAA,0x51,0x0A,0xd5,0x46, 0x54,0xdA,0xBA, 0x04,0xB6,0x4e, 0x0A,0x57,0x43,0x45,0x27,0x38, 0x0d,0x26,0x4A, 0x8e,0x93,0x3e, 0x0d,0x52,0x52,0x0d,0xAA,0x47, 0x66,0xB5,0x3B, 0x05,0x6d,0x4f, 0x04,0xAe,0x45, 0x4A,0x4e,0xB9, 0x0A,0x4d,0x4C, 0x0d,0x15,0x41, 0x2d,0x92,0xB5, };///月份数据表code uchar day_code1[9]={0x0,0x1f,0x3b,0x5a,0x78,0x97,0xb5,0xd4,0xf3};code uint day_code2[3]={0x111,0x130,0x14e}bit c_moon;data uchar year_moon,month_moon,day_moon,week;//子函数,用于读取数据表中农历月的大月或小月,如果该月为大返回1,为小返回0bit get_moon_day(uchar month_p,uint table_addr){uchar temp;switch (month_p){case 1:{temp=year_code[table_addr]&0x08;if (temp==0)return(0);else return(1);}case 2:{temp=year_code[table_addr]&0x04;if (temp==0)return(0);else return(1);}case 3:{temp=year_code[table_addr]&0x02;if (temp==0)return(0);else return(1);}case 4:{temp=year_code[table_addr]&0x01;if (temp==0)return(0);else return(1);}case 5:{temp=year_code[table_addr+1]&0x80;if (temp==0) return(0);else return(1);}case 6:{temp=year_code[table_addr+1]&0x40;if (temp==0)return(0);else return(1);}case 7:{temp=year_code[table_addr+1]&0x20;if (temp==0)return(0);else return(1);}case 8:{temp=year_code[table_addr+1]&0x10;if (temp==0)return(0);else return(1);}case 9:{temp=year_code[table_addr+1]&0x08;if (temp==0)return(0);else return(1);}case 10:{temp=year_code[table_addr+1]&0x04;if (temp==0)return(0);else return(1);}case 11:{temp=year_code[table_addr+1]&0x02;if (temp==0)return(0);else return(1);}case 12:{temp=year_code[table_addr+1]&0x01;if (temp==0)return(0);else return(1);}case 13:{temp=year_code[table_addr+2]&0x80;if (temp==0)return(0);else return(1);}}}/*函数功能:输入BCD阳历数据,输出BCD阴历数据(只允许1901-2099年)调用函数示例:Conversion(c_sun,year_sun,month_sun,day_sun)如:计算2004年10月16日Conversion(0,0x4,0x10,0x16);c_sun,year_sun,month_sun,day_sun均为BCD数据,c_sun为世纪标志位,c_sun=0为21世纪,c_sun=1为19世纪调用函数后,原有数据不变,读c_moon,year_moon,month_moon,day_moon得出阴历BCD数据*/void Conversion(bit c,uchar year,uchar month,uchar day){ //c=0 为21世纪,c=1 为19世纪输入输出数据均为BCD数据uchar temp1,temp2,temp3,month_p;uint temp4,table_addr;bit flag2,flag_y;temp1=year/16; //BCD->hex 先把数据转换为十六进制temp2=year%16;// year=temp1*10+temp2;year=temp1*16+temp2;temp1=month/16;temp2=month%16;//month=temp1*10+temp2;month=temp1*16+temp2;temp1=day/16;temp2=day%16;//day=temp1*10+temp2;day=temp1*16+temp2;//定位数据表地址if(c==0){table_addr=(year+0x64-1)*0x3;}else {table_addr=(year-1)*0x3;}//定位数据表地址完成//取当年春节所在的公历月份temp1=year_code[table_addr+2]&0x60;temp1=_cror_(temp1,5);//取当年春节所在的公历月份完成//取当年春节所在的公历日temp2=year_code[table_addr+2]&0x1f;//取当年春节所在的公历日完成// 计算当年春年离当年元旦的天数,春节只会在公历1月或2月if(temp1==0x1){temp3=temp2-1;}else{temp3=temp2+0x1f-1;}// 计算当年春年离当年元旦的天数完成//计算公历日离当年元旦的天数,为了减少运算,用了两个表//day_code1[9],day_code2[3]//如果公历月在九月或前,天数会少于0xff,用表day_code1[9],//在九月后,天数大于0xff,用表day_code2[3]//如输入公历日为8月10日,则公历日离元旦天数为day_code1[8-1]+10-1//如输入公历日为11月10日,则公历日离元旦天数为day_code2[11-10]+10-1if (month<10){temp4=day_code1[month-1]+day-1;}else{temp4=day_code2[month-10]+day-1;}if ((month>0x2)&&(year%0x4==0)){ //如果公历月大于2月并且该年的2月为闰月,天数加1temp4+=1;}//计算公历日离当年元旦的天数完成//判断公历日在春节前还是春节后if (temp4>=temp3){ //公历日在春节后或就是春节当日使用下面代码进行运算temp4-=temp3;month=0x1;month_p=0x1; //month_p为月份指向,公历日在春节前或就是春节当日month_p指向首月flag2=get_moon_day(month_p,table_addr); //检查该农历月为大小还是小月,大月返回1,小月返回0flag_y=0;if(flag2==0)temp1=0x1d; //小月29天else temp1=0x1e; //大小30天temp2=year_code[table_addr]&0xf0;temp2=_cror_(temp2,4); //从数据表中取该年的闰月月份,如为0则该年无闰月while(temp4>=temp1){temp4-=temp1;month_p+=1;if(month==temp2){flag_y=~flag_y;if(flag_y==0)month+=1;}else month+=1;flag2=get_moon_day(month_p,table_addr);if(flag2==0)temp1=0x1d;else temp1=0x1e;}day=temp4+1;}else{ //公历日在春节前使用下面代码进行运算temp3-=temp4;if (year==0x0){year=0x63;c=1;}else year-=1;table_addr-=0x3;month=0xc;temp2=year_code[table_addr]&0xf0;temp2=_cror_(temp2,4);if (temp2==0)month_p=0xc;elsemonth_p=0xd; ////month_p为月份指向,如果当年有闰月,一年有十三个月,月指向13,无闰月指向12flag_y=0;flag2=get_moon_day(month_p,table_addr);if(flag2==0)temp1=0x1d;else temp1=0x1e;while(temp3>temp1){temp3-=temp1;month_p-=1;if(flag_y==0)month-=1;if(month==temp2)flag_y=~flag_y;flag2=get_moon_day(month_p,table_addr);if(flag2==0)temp1=0x1d;else temp1=0x1e;}day=temp1-temp3+1;}c_moon=c; //HEX->BCD ,运算结束后,把数据转换为BCD数据temp1=year/10;temp1=_crol_(temp1,4);temp2=year%10;year_moon=temp1|temp2;temp1=month/10;temp1=_crol_(temp1,4);temp2=month%10;month_moon=temp1|temp2;temp1=day/10;temp1=_crol_(temp1,4);temp2=day%10;day_moon=temp1|temp2;}/*函数功能:输入BCD阳历数据,输出BCD星期数据(只允许1901-2099年)调用函数示例:Conver_week(c_sun,year_sun,month_sun,day_sun)如:计算2004年10月16日Conversion(0,0x4,0x10,0x16);c_sun,year_sun,month_sun,day_sun均为BCD数据,c_sun为世纪标志位,c_sun=0为21世纪,c_sun=1为19世纪调用函数后,原有数据不变,读week得出阴历BCD数据*/code uchar table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表/*算法:日期+年份+所过闰年数+月较正数之和除7 的余数就是星期但如果是在闰年又不到3 月份上述之和要减一天再除7星期数为0*/void Conver_week(uchar year,uchar month,uchar day){//c=0 为21世纪,c=1 为19世纪输入输出数据均为BCD数据uchar p1,p2;year+=0x64; //如果为21世纪,年份数加100p1=year/0x4; //所过闰年数只算1900年之后的p2=year+p1;p2=p2%0x7; //为节省资源,先进行一次取余,避免数大于0xff,避免使用整型数据p2=p2+day+table_week[month-1];if (year%0x4==0&&month<3)p2-=1;week=p2%0x7;}/**************************************************************/uchar code tab1[]={"20 - - "}; //年显示的固定字符uchar code tab2[]={" : : "}; //时间显示的固定字符uchar code nlp[]={"NL: - - PING"}; //农历平年显示uchar code nlr[]={"NL: - - RUN "}; //农历润年显示uchar code NZd[]={"timer: - - "}; //显示闹钟固定点uchar code qk[]= {" "}; //清空显示uchar code tm[]= {"time"};//=====================DS18B20========================================= ====//***************************************************************************** *void Delayns(int num)//延时函数{while(num--);}//***************************************************************************** *void Init_DS18B20(void)//初始化ds1820{unsigned char x=0;DQ = 1; //DQ复位Delayns(8); //稍做延时DQ = 0; //单片机将DQ拉低Delayns(80); //精确延时大于480usDQ = 1; //拉高总线Delayns(14);x=DQ; //稍做延时后如果x=0则初始化成功x=1则初始化失败Delayns(20);}//***************************************************************************** *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;Delayns(4);}return(dat);}//***************************************************************************** *void WriteOneChar(unsigned char dat)//写一个字节{unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;Delayns(5);DQ = 1;dat>>=1;}}//***************************************************************************** *unsigned int ReadTemperature(void)//读取温度{unsigned char a=0;unsigned char b=0;unsigned int t=0;float tt=0;Init_DS18B20();WriteOneChar(0xCC); // 跳过读序号列号的操作WriteOneChar(0x44); // 启动温度转换Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器a=ReadOneChar(); //读低8位b=ReadOneChar(); //读高8位t=b;t<<=8;t=t|a;tt=t*0.0625;t= tt*10+0.5; //放大10倍输出并四舍五入return(t);}//*****************************************************************************//延时函数,后面经常调用void delay(uint xms)//延时函数,有参函数uint x,y;for(x=xms;x>0;x--)for(y=110;y>0;y--);}/********液晶写入指令函数与写入数据函数,以后可调用**************//*在这个程序中,液晶写入有关函数会在DS1302的函数中调用,所以液晶程序要放在前面*/write_1602com(uchar com)//****液晶写入指令函数****{rs=0;//数据/指令选择置为指令rw=0; //读写选择置为写P0=com;//送入数据delay(1);en=1;//拉高使能端,为制造有效的下降沿做准备delay(1);en=0;//en由高变低,产生下降沿,液晶执行命令}write_1602dat(uchar dat)//***液晶写入数据函数****{rs=1;//数据/指令选择置为数据rw=0; //读写选择置为写P0=dat;//送入数据delay(1);en=1; //en置高电平,为制造下降沿做准备delay(1);en=0; //en由高变低,产生下降沿,液晶执行命令}lcd_init()//***液晶初始化函数****{write_1602com(0x38);//设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据write_1602com(0x0c);//开显示不显示光标write_1602com(0x06);//整屏不移动,光标自动右移write_1602com(0x01);//清显示write_1602com(yh+1);//日历显示固定符号从第一行第1个位置之后开始显示for(a=0;a<14;a++){write_1602dat(tab1[a]);//向液晶屏写日历显示的固定符号部分//delay(3);}write_1602com(er);//时间显示固定符号写入位置,从第2个位置后开始显示for(a=0;a<8;a++){write_1602dat(tab2[a]);//写显示时间固定符号,两个冒号//delay(3);}}/*********************over***********************//***************DS1302有关子函数********************/void write_byte(uchar dat)//写一个字节{ACC=dat;RST=1;for(a=8;a>0;a--){IO=ACC0;SCLK=0;SCLK=1;ACC=ACC>>1;}}uchar read_byte()//读一个字节{RST=1;for(a=8;a>0;a--){ACC7=IO;SCLK=1;SCLK=0;ACC=ACC>>1;}return (ACC);}//----------------------------------------void write_1302(uchar add,uchar dat)//向1302芯片写函数,指定写入地址,数据RST=0;SCLK=0;RST=1;write_byte(add);write_byte(dat);SCLK=1;RST=0;}uchar read_1302(uchar add)//从1302读数据函数,指定读取数据来源地址{uchar temp;RST=0;SCLK=0;RST=1;write_byte(add);temp=read_byte();SCLK=1;RST=0;return(temp);}uchar BCD_Decimal(uchar bcd)//BCD码转十进制函数,输入BCD,返回十进制{uchar Decimal;Decimal=bcd>>4;return(Decimal=Decimal*10+(bcd&=0x0F));}//--------------------------------------void ds1302_init() //1302芯片初始化子函数(2010-01-07,12:00:00,week4){RST=0;SCLK=0;write_1302(0x8e,0x00); //允许写,禁止写保护//write_1302(0x80,0x00); //向DS1302内写秒寄存器80H写入初始秒数据00//write_1302(0x82,0x00);//向DS1302内写分寄存器82H写入初始分数据00//write_1302(0x84,0x12);//向DS1302内写小时寄存器84H写入初始小时数据12 //write_1302(0x8a,0x04);//向DS1302内写周寄存器8aH写入初始周数据4//write_1302(0x86,0x07);//向DS1302内写日期寄存器86H写入初始日期数据07 //write_1302(0x88,0x01);//向DS1302内写月份寄存器88H写入初始月份数据01 //write_1302(0x8c,0x10);//向DS1302内写年份寄存器8cH写入初始年份数据10 write_1302(0x8e,0x80); //打开写保护//------------------------------------//温度显示子函数void write_temp(uchar add,uint dat)//向LCD写温度数据,并指定显示位置{uint gw,sw,bw;bw=dat/100;//取得百位sw=dat%100/10;//取得十位数字gw=dat%10;//取得个位数字write_1602com(er+add);//er是头文件规定的值0x80+0x40write_1602dat(0x30+bw);write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码write_1602dat('.');write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码write_1602dat(0xdf);//显示温度的小圆圈符号,0xdf是液晶屏字符库的该符号地址码write_1602dat(0x43); //显示"C"符号,0x43是液晶屏字符库里大写C的地址码}//------------------------------------//时分秒显示子函数void write_sfm(uchar add,uchar dat)//向LCD写时分秒,有显示位置加、现示数据,两个参数{uchar gw,sw;gw=dat%10;//取得个位数字sw=dat/10;//取得十位数字write_1602com(er+add);//er是头文件规定的值0x80+0x40write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码}//-------------------------------------//年月日显示子函数void write_nyr(uchar add,uchar dat)//向LCD写年月日,有显示位置加数、显示数据,两个参数{uchar gw,sw;gw=dat%10;//取得个位数字sw=dat/10;//取得十位数字write_1602com(yh+add);//设定显示位置为第一个位置+addwrite_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码//------------------------------------//农历显示子函数void write_nl(uchar add,uchar dat)//向LCD写时分秒,有显示位置加、现示数据,两个参数{uchar gw,sw;//gw=dat%10;//取得个位数字//sw=dat/10;//取得十位数字gw=dat%16;//取得个位数字sw=dat/16;//取得十位数字write_1602com(er+add);//er是头文件规定的值0x80+0x40// write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码// write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码write_1602dat('0'+sw);//数字+30得到该数字的LCD1602显示码write_1602dat('0'+gw);//数字+30得到该数字的LCD1602显示码}//-------------------------------------------void write_week(uchar week)//写星期函数{write_1602com(yh+0x0c);//星期字符的显示位置switch(week){case 1:write_1602dat('M');//星期数为1时,显示write_1602dat('O');write_1602dat('N');break;case 2:write_1602dat('T');//星期数据为2时显示write_1602dat('U');write_1602dat('E');break;case 3:write_1602dat('W');//星期数据为3时显示write_1602dat('E');write_1602dat('D');break;case 4:write_1602dat('T');//星期数据为4是显示write_1602dat('H');write_1602dat('U');break;case 5:write_1602dat('F');//星期数据为5时显示write_1602dat('R');write_1602dat('I');break;case 6:write_1602dat('S');//星期数据为6时显示write_1602dat('T');write_1602dat('A');break;case 0:write_1602dat('S');//星期数据为7时显示write_1602dat('U');write_1602dat('N');break;}write_1602dat(' ');}//****************键盘扫描有关函数********************** void keyscan(){if(ensure==0){delay(9);if(ensure==0){buzzer=0;//蜂鸣器短响一次delay(20);buzzer=1;led1=1; //背光灭setn=0; //退出任何当前的设置setNZn=0;T_NL_NZ=0;write_1602com(0x0c); //设置光标不闪烁TR0=1; //打开定时器temp=(miao)/10*16+(miao)%10;write_1302(0x8e,0x00);write_1302(0x80,0x00|temp); //miao数据写入DS1302write_1302(0x8e,0x80);}}if(menu==0){delay(9);if(menu==0){led1=0;bltime=0;if((setn==0)&&(setNZn==0)) //在没有进入调时模式时才可按动{buzzer=0;//蜂鸣器短响一次delay(20);buzzer=1;if(TR1==1){TR1=0;}else{T_NL_NZ++;if(T_NL_NZ==3){setn=0;setNZn=0;T_NL_NZ=0;}}}while(menu==0);}}if(set==0)//---------------set为功能键(设置键)--------------------{delay(9);//延时,用于消抖动if(set==0)//延时后再次确认按键按下{led1=0;bltime=0;buzzer=0;//蜂鸣器短响一次delay(20);buzzer=1;while(!set);if(T_NL_NZ==0x02) //证明是对闹钟进行设置{setNZn++;if(setNZn==4) //闹钟设定成功,退回到正常显示并开启闹钟{setNZn=0;setn=0;timerOn=1;}switch(setNZn){case 0: //正常显示日期时间write_1602com(0x0c); //置光标不闪?write_1602com(er); //时间显示固定符号写入位置?for(a=0;a<16;a++)write_1602dat(NZd[a]); //写显示时间固定符号,两个冒号write_sfm(8,nz_shi); //闹钟时write_sfm(11,nz_fen); //闹钟分write_sfm(14,nz_miao); //闹钟秒break;case 1: //闹钟秒光标闪烁write_1602com(er+15); //设置按键按动一次,秒位置显示光标//er+0x09;write_1602com(0x0f); //设置光标为闪烁break;case 2: //闹钟分光标闪烁write_1602com(er+12); //设置按键按动一次,秒位置显示光标//er+0x09;write_1602com(0x0f); //设置光标为闪烁break;case 3: //闹钟时光标闪烁write_1602com(er+9); //设置按键按动一次,秒位置显示光标//er+0x09;write_1602com(0x0f); //设置光标为闪烁break;}}else //证明是对时间及日期进行设置{if(T_NL_NZ==0){setn++;if(setn==7)setn=0; //设置按键共有秒、分、时、星期、日、月、年、返回,8个功能循环switch(setn){case 1: TR0=0;//关闭定时器//TR1=0;write_1602com(er+7);//设置按键按动一次,秒位置显示光标//er+0x09;write_1602com(0x0f);//设置光标为闪烁temp=(miao)/10*16+(miao)%10;//秒数据写入DS1302write_1302(0x8e,0x00);write_1302(0x80,0x80|temp);//miaowrite_1302(0x8e,0x80);break;case 2:write_1602com(er+4); //按2次fen位置显示光标//er+0x06//write_1602com(0x0f);break;case 3:write_1602com(er+1); //按动3次,shi//write_1602com(0x0f);break;// case 4: write_1602com(yh+0x0e);//按动4次,week//write_1602com(0x0f);// break;case 4: write_1602com(yh+0x0a);//按动4次,ri//write_1602com(0x0f);break;case 5: write_1602com(yh+0x07);//按动5次,yue//write_1602com(0x0f);break;case 6: write_1602com(yh+0x04);//按动6次,nian//write_1602com(0x0f);break;case 0:write_1602com(0x0c);//按动到第7次,设置光标不闪烁TR0=1;//打开定时器temp=(miao)/10*16+(miao)%10;write_1302(0x8e,0x00);write_1302(0x80,0x00|temp);//miao数据写入DS1302write_1302(0x8e,0x80);break;}}}}}//------------------------------加键add----------------------------if((setn!=0)&&(setNZn==0))//当set按下以下。
51单片机c语言电子万年历完整程序
该程序为51单片机c语言电子万年历#include"reg52.h"//#include<stdio.h>#define uchar unsigned char#define uint unsigned intsbit lcden=P3^4;sbit lcdrs=P3^5;sbit DATA=P0^7;sbit RST=P0^5;sbit SCLK=P0^6;sbit menu=P3^0; //菜单sbit add=P3^1; //加一sbit dec=P3^7; //减一sbit led0=P1^0;sbit led1=P1^1;sbit led2=P1^2;sbit led3=P1^3;sbit ds=P3^2;//sbit beep=P3^3;uint temp;float f_temp;uint warn_l1=270;uint warn_l2=250;uint warn_h1=300;uint warn_h2=320;uint get_temp();void delayms(uint x);void write_com(uchar com);void write_data(uchar date);void init();void dis_temp(uint t);void Write1302(uchar dat);void WriteSet1302(uchar Cmd,uchar dat);uchar Read1302(void);uchar ReadSet1302(uchar Cmd);void Init_DS1302(void);void DisplaySecond(uchar x);void DisplayMinute(uchar x);void DisplayHour(uchar x);void DisplayDay(uchar x);void DisplayMonth(uchar x);void DisplayYear(uchar x);void DisplayWeek(uchar x);void dis_temp(uint t);void read_date(void);void turn_val(char newval,uchar flag,uchar newaddr,uchar s1num);void key_scan(void);char code table[]="0123456789" ;uchar code table2[]= "TUEWESTHUFRISATSUNMON"; uchar second,minute,hour,day,month,year,week,count=0; uchar ReadValue,num,time;void delayms(uint x){uint i,j;for(i=x;i>0;i--)for(j=110;j>0;j--);}////////////////////////////////////////////////////////////void write_com(uchar com){lcdrs=0;P2=com;delayms(5);lcden=1;delayms(5);lcden=0;}void write_data(uchar date){lcdrs=1;P2=date;delayms(5);lcden=1;delayms(5);lcden=0;}void init(){lcden=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);}/////////////////////////////////////////////////////////////////void Write1302(uchar dat){uchar i;SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备 delayms(2); //稍微等待,使硬件做好准备for(i=0;i<8;i++) //连续写8个二进制位数据DATA=dat&0x01; //取出dat的第0位数据写入1302delayms(2); //稍微等待,使硬件做好准备SCLK=1; //上升沿写入数据delayms(2); //稍微等待,使硬件做好准备SCLK=0; //重新拉低SCLK,形成脉冲dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位 }}void WriteSet1302(uchar Cmd,uchar dat){RST=0; //禁止数据传递SCLK=0; //确保写数居前SCLK被拉低RST=1; //启动数据传输delayms(2); //稍微等待,使硬件做好准备Write1302(Cmd); //写入命令字Write1302(dat); //写数据SCLK=1; //将时钟电平置于已知状态RST=0; //禁止数据传递}uchar Read1302(void){uchar i,dat;delayms(2); //稍微等待,使硬件做好准备for(i=0;i<8;i++) //连续读8个二进制位数据dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位if(DATA==1) //如果读出的数据是1dat|=0x80; //将1取出,写在dat的最高位SCLK=1; //将SCLK置于高电平,为下降沿读出delayms(2); //稍微等待SCLK=0; //拉低SCLK,形成脉冲下降沿delayms(2); //稍微等待}return dat; //将读出的数据返回}uchar ReadSet1302(uchar Cmd){uchar dat;RST=0; //拉低RSTSCLK=0; //确保写数居前SCLK被拉低RST=1; //启动数据传输Write1302(Cmd); //写入命令字dat=Read1302(); //读出数据SCLK=1; //将时钟电平置于已知状态RST=0; //禁止数据传递return dat; //将读出的数据返回}void Init_DS1302(void){WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令WriteSet1302(0x80,((0/10)<<4|(0%10))); //根据写秒寄存器命令字,写入秒的初始值WriteSet1302(0x82,((59/10)<<4|(59%10))); //根据写分寄存器命令字,写入分的初始值WriteSet1302(0x84,((23/10)<<4|(23%10))); //根据写小时寄存器命令字,写入小时的初始值WriteSet1302(0x86,((28/10)<<4|(28%10))); //根据写日寄存器命令字,写入日的初始值 WriteSet1302(0x88,((2/10)<<4|(2%10))); //根据写月寄存器命令字,写入月的初始值WriteSet1302(0x8c,((14/10)<<4|(14%10))); //nian//WriteSet1302(0x8a,((4/10)<<4|(4%10)));}/////////////////////////////////////////////////////////////////void DisplaySecond(uchar x){uchar i,j;i=x/10;j=x%10;write_com(0x80+0x46);write_data(i+0x30);write_com(0x80+0x47);write_data(j+0x30);write_com(0x80+0x48);write_data(' ');dis_temp(get_temp());}void DisSecond(uchar x){uchar i,j;ReadValue = ReadSet1302(0x81);second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);i=x/10;j=x%10;write_com(0x80+0x46);write_data(i+0x30);write_com(0x80+0x47);write_data(j+0x30);}void DisplayMinute(uchar x) {uchar i,j;i=x/10;j=x%10;write_com(0x80+0x43);write_data(i+0x30);write_com(0x80+0x44);write_data(j+0x30);write_com(0x80+0x45);write_data(':');}void DisplayHour(uchar x){uchar i,j;i=x/10;j=x%10;write_com(0x80+0x40);write_data(i+0x30);write_com(0x80+0x41);write_data(j+0x30);write_com(0x80+0x42);write_data(':');}void DisplayDay(uchar x) {uchar i,j;i=x/10;j=x%10;write_com(0x89);write_data(i+0x30);write_com(0x8a);write_data(j+0x30); }void DisplayMonth(uchar x) {uchar i,j;i=x/10;j=x%10;write_com(0x86);write_data(i+0x30); write_com(0x87);write_data(j+0x30);write_com(0x88);write_data('/');}void DisplayYear(uchar x) {uchar i,j;i=x/10;j=x%10;write_com(0x81);write_data(2+0x30);write_com(0x82);write_data(0+0x30);write_com(0x83);write_data(i+0x30);write_com(0x84);write_data(j+0x30);write_com(0x85);write_data('/');}void DisplayWeek(uchar x){ uchar i;x=x*3;// write_com(0x8c);write_data(table2[x]);// write_com(0x8d);write_data(table2[x+1]);// write_com(0x8e);write_data(table2[x+2]);write_com(0x8c);for(i=0;i<3;i++){write_data(table2[x]);x++;}}void read_date(void){ReadValue = ReadSet1302(0x81);second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = ReadSet1302(0x83);minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = ReadSet1302(0x85);hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = ReadSet1302(0x87);day=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = ReadSet1302(0x89);month=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = ReadSet1302(0x8d);year=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue=ReadSet1302(0x8b); //读星期week=ReadValue&0x07;DisplayYear(year);DisplayMonth(month);DisplayDay(day);DisplayWeek(week);DisplayHour(hour);DisplayMinute(minute);DisplaySecond(second);dis_temp(get_temp()); ///温度显示key_scan(); ///按键检测}void turn_val(char newval,uchar flag,uchar newaddr,uchar s1num){newval=ReadSet1302(newaddr); //读取当前时间newval=((newval&0x70)>>4)*10+(newval&0x0f); //将bcd码转换成十进制 if(flag) //判断是加一还是减一{newval++;switch(s1num){ case 1: if(newval>99) newval=0;DisplayYear(newval);break;case 2: if(newval>12) newval=1;DisplayMonth(newval);break;case 3: if(newval>31) newval=1;DisplayDay(newval);break;case 4: if(newval>6) newval=0;DisplayWeek(newval);break;case 5: if(newval>23) newval=0;DisplayHour(newval);break;case 6: if(newval>59) newval=0;DisplayMinute(newval);break;case 7: if(newval>59) newval=0;DisplaySecond(newval);break;default:break;}}else{newval--;switch(s1num){ case 1: if(newval==0) newval=99;DisplayYear(newval);break;case 2: if(newval==0) newval=12;DisplayMonth(newval);break;case 3: if(newval==0) newval=31;DisplayDay(newval);break;case 4: if(newval<0) newval=6;DisplayWeek(newval);break;case 5: if(newval<0) newval=23;DisplayHour(newval);break;case 6: if(newval<0) newval=59;DisplayMinute(newval);break;case 7: if(newval<0) newval=59;DisplaySecond(newval);break;default:break;}}WriteSet1302((newaddr-1),((newval/10)<<4)|(newval%10)); //将新数据写入寄存器}//////////////////////////////////////void dsreset(void){uint i;ds=0;i=103;while(i>0)i=4;while(i>0)i--;}bit tempreadbit(void){uint i;bit dat;ds=0;i++;ds=1;i++;i++;dat=ds;i=8;while(i>0)i--;return(dat);}uchar tempread(void){uchar i,j,dat;dat=0;for(i=1;i<=8;i++){j=tempreadbit();dat=(j<<7)|(dat>>1); }return(dat);}void tempwritebyte(uchar dat) {bit testb;for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb){ds=0;i++;i++;ds=1;i=8;while(i>0)i--;}else{ds=0;i=8;while(i>0)i--;ds=1;i++;i++;}}}void tempchange(void) {dsreset();delayms(1);tempwritebyte(0xcc);tempwritebyte(0x44);key_scan(); //////按键函数}uint get_temp(){uchar a,b;tempchange(); //////温度函数dsreset();delayms(1);tempwritebyte(0xcc);tempwritebyte(0xbe);a=tempread();b=tempread();temp=b;temp<<=8;temp=temp|a;f_temp=temp*0.0625;temp=f_temp*10+0.5;f_temp=f_temp+0.05;return temp;}//////void dis_temp(uint t){uchar n1,n2,n3;n1=t/100;n2=t%100/10;n3=t%100%10;DisSecond(second); ///秒显示 write_com(0x80+0x49);write_data(table[n1]);//delayms(5);write_com(0x80+0x4a);write_data(table[n2]);//delayms(5);write_com(0x80+0x4b);write_data('.');// delayms(5);write_com(0x80+0x4c);write_data(table[n3]);//delayms(5);write_com(0x80+0x4d);write_data('^');//delayms(5);write_com(0x80+0x4e);write_data('C');//delayms(5);DisSecond(second); ////秒显示}/*********************液晶显示*****************/ void warn(uint s,uchar led){uchar i;i=s;// beep=0;P1=~(led);while(i--){dis_temp(get_temp());}// beep=1;P1=0xff;i=s;while(i--){dis_temp(get_temp());}}void deal(uint t){uchar i;if((t>warn_l2)&&(t<=warn_l1)){warn(40,0x01);}else if(t<=warn_l2){warn(10,0x03);}else if((t<warn_h2)&&(t>=warn_h1)) {warn(40,0x04);}else if(t>=warn_h2){warn(10,0x0c);}else{i=40;while(i--){dis_temp(get_temp());DisSecond(second);}}}///////////////////////////////////////void main(){init();Init_DS1302();while(1){tempchange();read_date();deal(temp);key_scan();}}////******************************************* void key_scan(void){// uchar miao,s1num=0;uchar s1num=0;if(menu==0){delayms(5);if(menu==0){while(!menu);s1num++;while(1){if(menu==0){delayms(5);if(menu==0){while(!menu);s1num++;}}// miao=ReadSet1302(0x81);// second=miao;// WriteSet1302(0x80,miao|0x80);write_com(0x0f);//光标闪射if(s1num==1){ //year=ReadSet1302(0x8d);write_com(0x80+4); //年光标if(add==0){delayms(3);if(add==0){ while(!add);turn_val(year,1,0x8d,1);}}if(dec==0){delayms(3);if(dec==0){ while(!dec);turn_val(year,0,0x8d,1);}}}if(s1num==2){//month=ReadSet1302(0x89);write_com(0x80+7); //月光标if(add==0){delayms(3);if(add==0){ while(!add);turn_val(month,1,0x89,2);}}if(dec==0){delayms(3);if(dec==0){ while(!dec);turn_val(month,0,0x89,2);}}}if(s1num==3){ //day=ReadSet1302(0x87);write_com(0x80+10);//日光标{delayms(3);if(add==0){ while(!add);turn_val(day,1,0x87,3);}}if(dec==0){delayms(3);if(dec==0){ while(!dec);turn_val(day,0,0x87,3); //写入日寄存器 }}}if(s1num==4){ //week=ReadSet1302(0x8b);write_com(0x80+14); //星期光标if(add==0){delayms(3);if(add==0){ while(!add);turn_val(week,1,0x8b,4);}}if(dec==0){delayms(3);{ while(!dec);turn_val(week,0,0x8b,4);}}}if(s1num==5){// hour=ReadSet1302(0x85)write_com(0x80+0x40+1); //时光标if(add==0){delayms(3);if(add==0){ while(!add);turn_val(hour,1,0x85,5);}}if(dec==0){delayms(3);if(dec==0){ while(!dec);turn_val(hour,0,0x85,5);}}}if(s1num==6)//调时间分{ // minute=ReadSet1302(0x83);write_com(0x80+0x40+4);if(add==0){delayms(5);if(add==0){ while(!add);turn_val(minute,1,0x83,6); //写入分寄存器}}if(dec==0){delayms(3);if(dec==0){ while(!dec);turn_val(minute,0,0x83,6); //写入分寄存器}}}if(s1num==7)//调时间秒{// second=ReadSet1302(0x81);write_com(0x80+0x40+7);//秒光标if(add==0){delayms(3);if(add==0){ while(!add);if(second==0x60)second=0x00;turn_val(second,1,0x81,7);}}if(dec==0){delayms(3);if(dec==0){ while(!dec);turn_val(second,0,0x81,7);}}}if(s1num==8){// miao=ReadSet1302(0x81);// second=miao;// WriteSet1302(0x80,second&0x7f);s1num=0;//s1num清零//write_com(0x0c);//光标不闪烁//break;}}}}}。
51单片机电子万年历设计电路图及程序
51单片机电子万年历设计电路图及程序(总37页)本页仅作为文档封面,使用时可以删除This document is for reference only-rar21year.March摘要:电子万年历是一种非常广泛日常计时工具,对现代社会越来越流行。
它可以对年、月、日、周日、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS1302的使用寿命长,误差小。
对于数字电子万年历采用直观的数字显示,可以同时显示年、月、日、周日、时、分、秒和温度等信息,还具有时间校准等功能。
该电路采用AT89S52单片机作为核心,功耗小,能在3V的低压工作,电压可选用3~5V电压供电。
本设计是基于51系列的单片机进行的电子万年历设计,可以显示年月日时分秒及周信息,具有可调整日期和时间功能。
在设计的同时对单片机的理论基础和外围扩展知识进行了比较全面准备。
在硬件与软件设计时,没有良好的基础知识和实践经验会受到很大限制,每项功能实现时需要那种硬件,程序该如何编写,算法如何实现等,没有一定的基础就不可能很好的实现。
在编写程序过程中发现以现有的相关知识要独自完成编写任务困难重重,在老师和同学的帮助下才完成了程序部分的编写。
万年历的设计过程在硬件与软件方面进行同步设计。
硬件部分主要由AT89C52单片机,LED显示电路,以及调时按键电路等组成。
在单片机的选择上本人使用了AT89C52单片机,该单片机适合于许多较为复杂控制应用场合。
显示器使用2片7SEG-MPX8-CA和一片7SEG-MPX4-CA。
7SEG-MPX8-CA是一种八个共阳二极管显示器,7SEG-MPX4-CA是一种四个共阳二极管显示器。
为了能更轻松的控制这三片显示器,本人使用了3片74HC164来驱动。
74HC164 是 8 位边沿触发式移位寄存器,串行输入数据,然后并行输出。
软件方面主要包括日历程序、时间调整程序,公历转阴历程序,显示程序等。
程序采用汇编语言编写,以便更简单地实现调整时间及阴历显示功能。
51单片机实现万年历程序
51单片机实现万年历利用AT89S52单片机的P0口来和另外几个口来控制1602液晶的显示和P1口还有其它口来控制ds12887时钟芯片。
设置四个按键,1个定义为时间设置功能键,一个定义为闹钟设置功能键,另外两个用来调节时间的增减。
原理图:pcb图:源程序:#include<reg52.h>#define uint unsigned int#define uchar unsigned charsbit beep=P2^0;//蜂鸣器控制口sbit timeadd=P2^1;//调节时间加sbit timesub=P2^2;//调节时间减sbit timeclk=P2^3;//闹钟设定键sbit timefun=P2^4;//时间设定键sbit lcdrs=P2^5;//液晶的命令和数据控制口sbit ledrw=P2^6;//液晶的写数据口sbit lcden=P2^7;//液晶显示模块的使能端sbit timeds=P3^3;//时钟芯片地址闸sbit timerw=P3^4;//时钟芯片读写sbit timeas=P3^5;//时钟芯片地址闸sbit timeen=P3^6;//时钟芯片片选uchar code table[]="20 - - week ";uchar code table1[]=" : : ";//要显示的字符串char num,shi,fen,miao,nian=2000,yue,ri,week,numfun,anumfun,flag,flag1; uchar leap;void delay(uint x){uchar i,j;for(i=x;i>0;i--)for(j=110;j>0;j--);}void didi(){beep=0;delay(1000);beep=1;delay(1000);}void write_com(uchar com){lcdrs=0;P0=com;delay(5);lcden=1;delay(20);lcden=0;}void write_date(uchar date){lcdrs=1;P0=date;delay(5);lcden=1;delay(20);lcden=0;}void write_sfm(uchar add,uchar date){ uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+0x40+add);write_date(0x30+shi);write_date(0x30+ge);}void write_nyr(uchar add,uchar date){ uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+add);write_date(0x30+shi);write_date(0x30+ge);}void write_zhou(uchar add,uchar date) {write_com(0x80+add);write_date(0x30+date);}void write_ds(uchar add,uchar date){ timeen=0;timeas=1;timeds=1;timerw=1;P1=add;timeas=0;timerw=0;P1=date;timerw=1;timeas=1;timeen=1;}uchar read_ds(uchar add){uchar ds_date;timeas=1;timeds=1;timerw=1;timeen=0;P1=add;timeas=0;timeds=0;P1=0xff;ds_date=P1;timeds=1;timeas=1;timeen=1;return ds_date;}void keyscan(){if(flag1==1)//用来关闭闹钟铃声{if(timeadd==0){delay(5);if(timeadd==0){while(!timeadd==0);flag1=0;}}if(timesub==0){delay(5);if(timesub==0){while(!timesub==0);flag1=0;}}}if(timefun==0){delay(5);if(timefun==0){while(!timefun);flag=1;numfun++;if(numfun==1){write_com(0x80+0x40+0x0a);write_com(0x0f);}if(numfun==2){write_com(0x80+0x40+0x07);write_com(0x0f);}if(numfun==3){write_com(0x80+0x40+0x04);write_com(0x0f);}if(numfun==4){write_com(0x80+0x0f);write_com(0x0f);}if(numfun==5){write_com(0x80+0x09);write_com(0x0f);}if(numfun==6){write_com(0x80+0x06);write_com(0x0f);}if(numfun==7){write_com(0x80+0x03);write_com(0x0f);}if(numfun==8){numfun=0;flag=0;}}}if(numfun!=0){if(timeadd==0){delay(5);while(!timeadd);if(numfun==1){miao++;if(miao==60)miao=0;write_sfm(9,miao);write_com(0x80+0x40+9);write_ds(0,miao);}if(numfun==2){fen++;if(fen==60)fen=0;write_sfm(6,fen);write_com(0x80+0x40+6);write_ds(2,fen);}if(numfun==3){shi++;if(shi==24)shi=0;write_sfm(3,shi);write_com(0x80+0x40+3);write_ds(4,shi);}if(numfun==4){week++;if(week==8)week=1;write_zhou(0x0f,week);write_com(0x80+0x0f);write_ds(6,week);}if(numfun==5){if(nian==0){switch(yue){case 1:ri++;if(ri==32) ri=1;break;case 2:ri++;if(ri==30) ri=1;break;case 3:ri++;if(ri==32) ri=1;break;case 4:ri++;if(ri==31) ri=1;break;case 5:ri++;if(ri==32) ri=1;break;case 6:ri++;if(ri==31) ri=1;break;case 7:ri++;if(ri==32) ri=1;break;case 8:ri++;if(ri==32) ri=1;break;case 9:ri++;if(ri==31)ri=1;break;case 10:ri++;if(ri==32)ri=1;break;case 11:ri++;if(ri==31)ri=1;break;case 12:ri++;if(ri==32)ri=1;break;}}else if(leap&&yue==2){ri++;if(ri==30)ri=1;}else if(yue==2&&leap==0){ri++;if(ri==29)ri=1;}elseswitch(yue){case 1:ri++;if(ri==32) ri=1;break;case 3:ri++;if(ri==32) ri=1;break;case 4:ri++;if(ri==31) ri=1;break;case 5:ri++;if(ri==32) ri=1;break;case 6:ri++;if(ri==31) ri=1;break;case 7:ri++;if(ri==32) ri=1;break;case 8:ri++;if(ri==32) ri=1;break;case 9:ri++;if(ri==31) ri=1;break;case 10:ri++;if(ri==32) ri=1;break;case 11:ri++;if(ri==31) ri=1;break;case 12:ri++;if(ri==32) ri=1;break;}write_nyr(8,ri);write_com(0x80+0x08);write_ds(7,ri);}if(numfun==6){yue++;if(yue==13)yue=0;write_nyr(5,yue);write_com(0x80+0x05);write_ds(8,yue);}if(numfun==7){nian++;if(nian==100)nian=0;leap=nian%4==0&&nian%100!=0;write_nyr(2,nian);write_com(0x80+2);write_ds(9,nian);}}if(timesub==0){delay(5);while(!timesub);if(numfun==1){miao--;if(miao==-1)miao=59;write_sfm(9,miao);write_com(0x80+0x40+9);write_ds(0,miao);}if(numfun==2){fen--;if(fen==-1)fen=59;write_sfm(6,fen);write_com(0x80+0x40+6);write_ds(2,fen);}if(numfun==3){shi--;if(shi==-1)shi=23;write_sfm(3,shi);write_com(0x80+0x40+3);write_ds(4,shi);}if(numfun==4){week--;if(week==0)week=7;write_zhou(0x0f,week);write_com(0x80+0x0f);write_ds(6,week);}if(numfun==5){if(nian==0){switch(yue){case 1:ri--;if(ri==0) ri=31;break;case 2:ri--;if(ri==0) ri=29;break;case 3:ri--;if(ri==0) ri=31;break;case 4:ri--;if(ri==0) ri=30;break;case 5:ri--;if(ri==0) ri=31;break;case 6:ri--;if(ri==0) ri=30;break;case 7:ri--;if(ri==0) ri=31;break;case 8:ri--;if(ri==0) ri=31;break;case 9:ri--;if(ri==0) ri=30;break;case 10:ri--;if(ri==0) ri=31;break;case 11:ri--;if(ri==0) ri=30;break;case 12:ri--;if(ri==0) ri=31;break;}}else if(leap&&yue==2){ri--;if(ri==0)ri=29;}else if(yue==2&&leap==0){ri--;if(ri==0)ri=28;}elseswitch(yue){case 1:ri--;if(ri==0) ri=31;break;case 3:ri--;if(ri==0) ri=31;break;case 4:ri--;if(ri==0) ri=30;break;case 5:ri--;if(ri==0) ri=31;break;case 6:ri--;if(ri==0) ri=30;break;case 7:ri--;if(ri==0) ri=31;break;case 8:ri--;if(ri==0) ri=31;break;case 9:ri--;if(ri==0) ri=30;break;case 10:ri--;if(ri==0) ri=31;break;case 11:ri--;if(ri==0) ri=30;break;case 12:ri--;if(ri==0) ri=31;break;}write_nyr(8,ri);write_com(0x80+0x08);write_ds(7,ri);}if(numfun==6){yue--;if(yue==-1)yue=12;write_nyr(5,yue);write_com(0x80+0x05);write_ds(8,yue);}if(numfun==7){nian--;if(nian==-1)nian=99;leap=nian%4==0&&nian%100!=0;write_nyr(2,nian);write_com(0x80+2);write_ds(9,nian);}}}}void set_alarm(){uchar ashi,afen,amiao;if(timeclk==0)//判断是否按下闹钟设定键{delay(5);//延时消抖if(timeclk==0){while(!timeclk);anumfun++;//按键次数加1if(anumfun==1){flag=1;write_com(0x80+0x40+0x0a);write_com(0x0f);}if(anumfun==2){flag=1;write_com(0x80+0x40+0x07);write_com(0x0f);}if(anumfun==3){flag=1;write_com(0x80+0x40+0x04);write_com(0x0f);}if(anumfun==4){flag=0;anumfun=0;}}}if(anumfun!=0){if(timeadd==0)//如果加功能键按下{delay(5);while(!timeadd);if(anumfun==1) //设定秒{amiao++;if(amiao==60)amiao=0;write_sfm(9,amiao);write_com(0x80+0x40+9);write_ds(1,amiao);}if(anumfun==2){afen++;if(afen==60)afen=0;write_sfm(6,afen);write_com(0x80+0x40+6);write_ds(3,afen);}if(anumfun==3){ashi++;if(ashi==24)ashi=0;write_sfm(3,ashi);write_com(0x80+0x40+3);write_ds(5,ashi);}}}if(anumfun!=0){if(timesub==0){delay(5);while(!timesub);if(anumfun==1){amiao--;if(amiao==-1)amiao=59;write_sfm(9,amiao);write_com(0x80+0x40+9);write_ds(1,amiao);}if(anumfun==2){afen--;if(afen==-1)afen=59;write_sfm(6,afen);write_com(0x80+0x40+6);write_ds(3,afen);}if(anumfun==3){ashi--;if(ashi==-1)ashi=23;write_sfm(3,ashi);write_com(0x80+0x40+3);write_ds(5,ashi);}}}}void init(){EA=1;//开总中断EX0=1;//开外部中断0IT0=1;//设定触发方式为负跳变沿有效lcden=0;//选通液晶显示屏ledrw=0;//设定液晶显示屏的读写方式为读write_com(0x38);//设置液晶显示模式为16*2显示,5*7点阵,8位数据接口 write_com(0x0c);//打开显示,并使光标不显示也不闪烁write_com(0x06);//光标指针每次自动加1write_com(1);//清屏write_com(0x80);//送地址指针for(num=0;num<16;num++){write_date(table[num]);delay(5);}write_com(0x80+0x40);//写到第二行for(num=0;num<11;num++){write_date(table1[num]);delay(5);}write_ds(0x0a,0x20);//开启时钟芯片振荡器write_ds(0x0b,0x26);//开启闹钟read_ds(0x0c);//读取时钟芯片c寄存器}void main(){init();while(1){keyscan();set_alarm();if(flag1==1)didi();if(flag==0){//读取时间miao=read_ds(0x00);fen=read_ds(0x02);shi=read_ds(0x04);yue=read_ds(0x08);ri=read_ds(0x07);nian=read_ds(0x09);week=read_ds(0x06);//写入液晶显示屏write_sfm(9,miao);write_sfm(6,fen);write_sfm(3,shi);write_nyr(2,nian);write_nyr(5,yue);write_nyr(8,ri);write_zhou(0x0f,week);}}}void exter() interrupt 0{flag1=1;read_ds(0x0c);//读时钟芯片c寄存器。
C51单片机模块化编程万年历设计
C51单片机模块化编程万年历设计程序如下:main.h#ifndef __MAIN_H__#define __MAIN_H__#include<regx52.h>#include<intrins.h>#include<absacc.h>#define uchar unsigned char #define uint unsigned int#define DQ P3_7#endifds18b20.h#include "main.h"uint sec;uint min=41;uint hour=18;uint day=20;uint month=4;uint yearl=11;uint yearh=20;uint tcnt;uint cursor=0;uchar a=0xff;uchar code Seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};void delay(uint t){uint i;while(t--){for (i=0;i<125;i++);}}void Tdelay(unsigned int i){while(i--);}void Kdelay(unsigned int z){uchar i,j;for(i=0;i<z;i++)for(j=248;j>0;j--);}Init_DS18B20(void){unsigned char x = 0;DQ = 1;Tdelay(200);DQ=0;Tdelay(80);DQ=1;Tdelay(200);Tdelay(200);}//读一个字节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;Tdelay(4);}return(dat);}//写一个字节WriteOneChar(unsigned char dat) {unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;Tdelay(5);DQ = 1;dat>>=1;}}//读取温度ReadTemperature(void){unsigned char a=0;unsigned char b=0;unsigned int t=0;float tt=0;Init_DS18B20();WriteOneChar(0xCC); WriteOneChar(0x44);Init_DS18B20();WriteOneChar(0xCC); WriteOneChar(0xBE);a=ReadOneChar();b=ReadOneChar();t=b;t<<=8;t=t|a;tt=t*0.0625;t= tt*10+0.5;return(t);}void display(uchar L1,uchar L2,uchar L3,uchar L4,uchar L5,uchar L6,uchar L7,ucharL8,uchar L9,uchar L10,uchar L11,uchar L12,uchar L13,uchar L14,uchar L15,uchar L16) {P2=0x7F;P0=L1;delay(1); //yearhP2=0xBF;P0=L2;delay(1); //yearhif(cursor==6){P2=0xDF;P0=L3;delay(1);}else{P2=0xDF;P0=L3;delay(1);} //yearl if(cursor==6){P2=0xEF;P0=L4;delay(1);}else{P2=0xEF;P0=L4;delay(1);} //yearl if(cursor==5){P2=0xF7;P0=L5;delay(1);}else{P2=0xF7;P0=L5;delay(1);} //month if(cursor==5){P2=0xFB;P0=L6;delay(1);}else{P2=0xFB;P0=L6;delay(1);} //month if(cursor==4){P2=0xFD;P0=L7;delay(1);}else{P2=0xFD;P0=L7;delay(1);} //dayif(cursor==4){P2=0xFE;P0=L8;delay(1);}else{P2=0xFE;P0=L8;delay(1);} //dayP2=0xFF;if(cursor==3){P1=0x7F;P0=L9;delay(1);}else{P1=0x7F;P0=L9;delay(1);} //hourif(cursor==3){P1=0xBF;P0=L10;delay(1);}else{P1=0xBF;P0=L10;delay(1);} //hour if(cursor==2){P1=0xDF;P0=L11;delay(1);}else{P1=0xDF;P0=L11;delay(1);} //minif(cursor==2){P1=0xEF;P0=L12;delay(1);}else{P1=0xEF;P0=L12;delay(1);} //minif(cursor==1){P1=0xF7;P0=L13;delay(1);}else{P1=0xF7;P0=L13;delay(1);} //secif(cursor==1){P1=0xFB;P0=L14;delay(1);}else{P1=0xFB;P0=L14;delay(1);} //secP1=0xFD;P0=L15;delay(1); //tempP1=0xFE;P0=L16;delay(1); //tempP1=0xFF;}main.c#include "main.h"#include "ds18B20.h"void delay(uint t);void Tdelay(unsigned int i);void Kdelay(unsigned int z);Init_DS18B20(void);ReadOneChar(void);WriteOneChar(unsigned char dat);ReadTemperature(void);void display(uchar L1,uchar L2,uchar L3,uchar L4,uchar L5,uchar L6,uchar L7,ucharL8,uchar L9,uchar L10,uchar L11,uchar L12,uchar L13,uchar L14,uchar L15,uchar L16); main(){uint i;TMOD=0x02; //设置模式为定时器T0的模式2 (8位自动重装计数初值的计数TH0=0x06; //设置计数器初值,靠TH0存储重装的计数值X0=256-250=6 TL0=0x06;TR0=1; //启动T0ET0=1; //开启定时器T0中断允许EA=1; //开启中断总控制while(1){if(P3_0==0){Kdelay(200);if(P3_0==0){cursor++;if(cursor>=7){cursor=0;}}}if(P3_1==0){Kdelay(200);if(P3_1==0){if(cursor==1){sec++;if(sec==60)sec=0;}if(cursor==2){min++;if(min==60)min=0;}if(cursor==3){hour++;if(hour==24)hour=0;}if(cursor==4){day++;if(day==31)day=0;}if(cursor==5){month++;if(month==12)month=0;}if(cursor==6){yearl++;if(yearl==100)yearl=0;}if(cursor==7){yearh++;if(yearh==30)yearh=20;}}}if(P3_2==0){Kdelay(200);if(P3_2==0){if(cursor==1){sec--;}if(cursor==2){min--;}if(cursor==3){hour--;}if(cursor==4){day--;}if(cursor==5){month--;}if(cursor==6){yearl--;}if(cursor==7){yearh--;}}i=ReadTemperature();display(Seg[yearh/10],Seg[yearh],Seg[yearl/10],Seg[yearl],Seg[month/10],Seg [month],Seg[day/10],Seg[day],Seg[hour/10],Seg[hour],Seg[min/10],Seg[min],Seg[sec/10 ],Seg[sec],Seg[i/100],Seg[i/10]);}}void t0(void)interrupt 1 using 0 //t0的中断程序{tcnt++;if(tcnt==4000)//定时器的定时计数,4000次250us为1秒{tcnt=0;P3_3=~P3_3;a=~a;sec++;if(sec==60){sec=0;min++;if(min==60){min=0;hour++;if(hour==24){hour=0;day++;if(month==2&&((yearl==0&&yearh%4==0)||(yearl!=0&&yearl%4==0))&& day==30)day=1;else if(month==2&&day==29)day=1;elseif((month==4||month==6||month==9||month==11)&&day==31)day=1;else if(day==32)day=1;if(day==1){month++;if(month==13){month=1;yearl++;if(yearl==100){yearl=0;yearh++;if(yearh==100) {yearh=20; }}}}}}}}}。
c51单片机万年历的c程序
c51单片机万年历的c程序c51单片机万年历的c程序求一个单片机可以显示阳历的年、月、日、星期、小时.分.秒。
阴历也能显示,标明是否为闰年。
用LCD液晶显示,可以调整时间。
这有个数码管显示的程序以前做的,。
你可以在我这个程序上修改修改包括键盘扫描,还有动态显示。
【。
】#include <REG51.H>//常量参数#define TMODW 0x01;#define SCONW 0x00;#define xplay 0x04;//显示分频系数//显示位选unsigned char data stb;//键值缓存,0xFF无键命令unsigned char data keynum;//显示字型变量unsigned char data play[8];//工作参数unsigned char data l,m;//字型码unsigned char code BCDPC[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//字位码unsigned char code STBCODE[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 };//400Hz xplay分频计数unsigned char data cttime;//时钟参数unsigned char data hr,min,sec,sec100;//调整时钟参数(时钟“走”)void ct1(){sec100++;if (sec100==100){sec100=0;sec++;if (sec==60){sec=0;min++;if (min==60){min=0;hr++;if (hr==24) hr=0;}}}}//时钟参数→LED 显示缓存7段参数转换函数;void xcplay(){play[0]=BCDPC[hr/10];play[1]=BCDPC[hr%10];play[2]=BCDPC[min/10];play[3]=BCDPC[min%10];play[4]=BCDPC[sec/10];play[5]=BCDPC[sec%10];play[6]=BCDPC[sec100/10]; play[7]=BCDPC[sec100%10];}//显示扫描void cplay(){T0=1;//T0-高电平消隐T1=0;//T1-低电平准备发脉冲前沿TI=0;//?P1=0;//?SBUF=STBCODE[stb];while (TI==0){};TI=0;SBUF=play[stb];while (TI==0){};T1=1;T0=0;stb=++stb&0x07;}extern void cthl0();//定时器0中断处理程序void ct0(void) interrupt 1 using 1 {cthl0();cttime--;if (cttime==0){cttime=xplay;ct1();//调用时钟“走”函数xcplay();//调用时钟参数→Led显示缓存转换函数};cplay();}void w20ms(){for (l=0;l<41;l++){for (m=0;m<81;m++){}}}void tkey(){P1=0xF0;keynum=0xFF;if (P1!=0xF0){w20ms();P1=0xF0;if (P1!=0xF0){P1=0xFE;switch (P1){case 0xEE:keynum=0;break;case 0xDE:keynum=1;break;case 0xBE:keynum=2;break;case 0x7E:keynum=3;break;}P1=0xFD;switch (P1){case 0xED:keynum=4;break;case 0xDD:keynum=5;break;case 0xBD:keynum=6;break; case 0x7B:keynum=7;break; }P1=0xFB;switch (P1){case 0xEB:keynum=8;break; }};};P1=0x00;}void command(){switch (keynum){case 0:{hr=hr+1;if (hr==24)hr=0;}break;case 1:{min=min+1;if (min==60)min=0;}break;case 2:{sec=sec+1;if (sec==60)sec=0;}break;case 3:{sec100=0; }break;case 4:{while(!(P1=0xED)) {hr=0;min=0;sec=0;}}break;case 5:{hr=hr-1;if (hr==00)hr=24;}break;case 6:{min=min-1; if (min==00)min=59;}break;case 7:{sec=sec-1; if (sec==00)sec=0;}break;case 0xFF:break; }keynum=0xFF; }main (){ hr=8;min=5;sec=8;sec100=0; TMOD=TMODW; SCON=SCONW; ET0=1;TR0=1;EA=1;cttime=xplay; while (1){w20ms();tkey(); command();};}。
51单片机实现万年历程序文件
51单片机实现万年历利用AT89S52单片机的P0口来和另外几个口来控制1602液晶的显示和P1口还有其它口来控制ds12887时钟芯片。
设置四个按键,1个定义为时间设置功能键,一个定义为闹钟设置功能键,另外两个用来调节时间的增减。
原理图:pcb图:源程序:#include<reg52.h>#define uint unsigned int#define uchar unsigned charsbit beep=P2^0;//蜂鸣器控制口sbit timeadd=P2^1;//调节时间加sbit timesub=P2^2;//调节时间减sbit timeclk=P2^3;//闹钟设定键sbit timefun=P2^4;//时间设定键sbit lcdrs=P2^5;//液晶的命令和数据控制口sbit ledrw=P2^6;//液晶的写数据口sbit lcden=P2^7;//液晶显示模块的使能端sbit timeds=P3^3;//时钟芯片地址闸sbit timerw=P3^4;//时钟芯片读写sbit timeas=P3^5;//时钟芯片地址闸sbit timeen=P3^6;//时钟芯片片选uchar code table[]="20 - - week ";uchar code table1[]=" : : ";//要显示的字符串char num,shi,fen,miao,nian=2000,yue,ri,week,numfun,anumfun,flag,flag1; uchar leap;void delay(uint x){uchar i,j;for(i=x;i>0;i--)for(j=110;j>0;j--);}void didi(){beep=0;delay(1000);beep=1;delay(1000);}void write_com(uchar com){lcdrs=0;P0=com;delay(5);lcden=1;delay(20);lcden=0;}void write_date(uchar date){lcdrs=1;P0=date;delay(5);lcden=1;delay(20);lcden=0;}void write_sfm(uchar add,uchar date){ uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+0x40+add);write_date(0x30+shi);write_date(0x30+ge);}void write_nyr(uchar add,uchar date){ uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+add);write_date(0x30+shi);write_date(0x30+ge);}void write_zhou(uchar add,uchar date) {write_com(0x80+add);write_date(0x30+date);}void write_ds(uchar add,uchar date){timeas=1;timeds=1;timerw=1;P1=add;timeas=0;timerw=0;P1=date;timerw=1;timeas=1;timeen=1;}uchar read_ds(uchar add){ uchar ds_date;timeas=1;timeds=1;timerw=1;timeen=0;P1=add;timeas=0;timeds=0;ds_date=P1;timeds=1;timeas=1;timeen=1;return ds_date;}void keyscan(){if(flag1==1)//用来关闭闹钟铃声{if(timeadd==0){delay(5);if(timeadd==0){while(!timeadd==0); flag1=0;}}if(timesub==0){delay(5);if(timesub==0){while(!timesub==0);flag1=0;}}}if(timefun==0){delay(5);if(timefun==0){while(!timefun);flag=1;numfun++;if(numfun==1){write_com(0x80+0x40+0x0a); write_com(0x0f);}if(numfun==2){write_com(0x80+0x40+0x07); write_com(0x0f);}if(numfun==3){write_com(0x80+0x40+0x04); write_com(0x0f);}if(numfun==4){write_com(0x80+0x0f);write_com(0x0f);}if(numfun==5){write_com(0x80+0x09);write_com(0x0f);}if(numfun==6){write_com(0x80+0x06);write_com(0x0f);}if(numfun==7){write_com(0x80+0x03); write_com(0x0f);}if(numfun==8){numfun=0;flag=0;}}}if(numfun!=0){if(timeadd==0){delay(5);while(!timeadd);if(numfun==1){miao++;if(miao==60)miao=0;write_sfm(9,miao);write_com(0x80+0x40+9); write_ds(0,miao);}if(numfun==2){fen++;if(fen==60)fen=0;write_sfm(6,fen);write_com(0x80+0x40+6); write_ds(2,fen);}if(numfun==3){shi++;if(shi==24)shi=0;write_sfm(3,shi);write_com(0x80+0x40+3);write_ds(4,shi);}if(numfun==4){week++;if(week==8)week=1;write_zhou(0x0f,week);write_com(0x80+0x0f);write_ds(6,week);}if(numfun==5){if(nian==0){switch(yue){case 1:ri++;if(ri==32) ri=1;break; case 2:ri++;if(ri==30) ri=1;break; case 3:ri++;if(ri==32) ri=1;break; case 4:ri++;if(ri==31) ri=1;break; case 5:ri++;if(ri==32) ri=1;break;case 6:ri++;if(ri==31) ri=1;break; case 7:ri++;if(ri==32) ri=1;break; case 8:ri++;if(ri==32) ri=1;break; case 9:ri++;if(ri==31) ri=1;break; case 10:ri++;if(ri==32) ri=1;break; case 11:ri++;if(ri==31) ri=1;break; case 12:ri++;if(ri==32) ri=1;break; }}else if(leap&&yue==2){ri++;if(ri==30)ri=1;}else if(yue==2&&leap==0){ri++;if(ri==29)ri=1;}elseswitch(yue){case 1:ri++;if(ri==32) ri=1;break; case 3:ri++;if(ri==32) ri=1;break; case 4:ri++;if(ri==31) ri=1;break; case 5:ri++;if(ri==32) ri=1;break; case 6:ri++;if(ri==31) ri=1;break; case 7:ri++;if(ri==32) ri=1;break; case 8:ri++;if(ri==32) ri=1;break; case 9:ri++;if(ri==31) ri=1;break; case 10:ri++;if(ri==32) ri=1;break; case 11:ri++;if(ri==31) ri=1;break; case 12:ri++;if(ri==32) ri=1;break; }write_nyr(8,ri);write_com(0x80+0x08);write_ds(7,ri);}if(numfun==6){yue++;if(yue==13)yue=0;write_nyr(5,yue);write_com(0x80+0x05);write_ds(8,yue);}if(numfun==7){nian++;if(nian==100)nian=0;leap=nian%4==0&&nian%100!=0; write_nyr(2,nian);write_com(0x80+2);write_ds(9,nian);}}if(timesub==0){delay(5);while(!timesub);if(numfun==1){miao--;if(miao==-1)miao=59;write_sfm(9,miao);write_com(0x80+0x40+9); write_ds(0,miao);}if(numfun==2){fen--;if(fen==-1)fen=59;write_sfm(6,fen);write_com(0x80+0x40+6); write_ds(2,fen);}if(numfun==3){shi--;if(shi==-1)shi=23;write_sfm(3,shi);write_com(0x80+0x40+3);write_ds(4,shi);}if(numfun==4){week--;if(week==0)week=7;write_zhou(0x0f,week);write_com(0x80+0x0f);write_ds(6,week);}if(numfun==5){if(nian==0){switch(yue){case 1:ri--;if(ri==0) ri=31;break; case 2:ri--;if(ri==0) ri=29;break; case 3:ri--;if(ri==0) ri=31;break; case 4:ri--;if(ri==0) ri=30;break; case 5:ri--;if(ri==0) ri=31;break; case 6:ri--;if(ri==0) ri=30;break;case 7:ri--;if(ri==0) ri=31;break; case 8:ri--;if(ri==0) ri=31;break; case 9:ri--;if(ri==0) ri=30;break; case 10:ri--;if(ri==0) ri=31;break; case 11:ri--;if(ri==0) ri=30;break; case 12:ri--;if(ri==0) ri=31;break; }}else if(leap&&yue==2){ri--;if(ri==0)ri=29;}else if(yue==2&&leap==0){ri--;if(ri==0)ri=28;}elseswitch(yue){case 1:ri--;if(ri==0) ri=31;break; case 3:ri--;if(ri==0) ri=31;break; case 4:ri--;if(ri==0) ri=30;break; case 5:ri--;if(ri==0) ri=31;break; case 6:ri--;if(ri==0) ri=30;break; case 7:ri--;if(ri==0) ri=31;break; case 8:ri--;if(ri==0) ri=31;break; case 9:ri--;if(ri==0) ri=30;break; case 10:ri--;if(ri==0) ri=31;break; case 11:ri--;if(ri==0) ri=30;break; case 12:ri--;if(ri==0) ri=31;break; }write_nyr(8,ri);write_com(0x80+0x08);write_ds(7,ri);}if(numfun==6){yue--;if(yue==-1)yue=12;write_nyr(5,yue);write_com(0x80+0x05);write_ds(8,yue);}if(numfun==7){nian--;if(nian==-1)nian=99;leap=nian%4==0&&nian%100!=0; write_nyr(2,nian);write_com(0x80+2);write_ds(9,nian);}}}}void set_alarm(){uchar ashi,afen,amiao;if(timeclk==0)//判断是否按下闹钟设定键{delay(5);//延时消抖if(timeclk==0){while(!timeclk);anumfun++;//按键次数加1if(anumfun==1){flag=1;write_com(0x80+0x40+0x0a); write_com(0x0f);}if(anumfun==2){flag=1;write_com(0x80+0x40+0x07); write_com(0x0f);}if(anumfun==3){flag=1;write_com(0x80+0x40+0x04); write_com(0x0f);}{flag=0;anumfun=0;}}}if(anumfun!=0){if(timeadd==0)//如果加功能键按下{delay(5);while(!timeadd);if(anumfun==1) //设定秒{amiao++;if(amiao==60)amiao=0;write_sfm(9,amiao);write_com(0x80+0x40+9); write_ds(1,amiao);}{afen++;if(afen==60)afen=0;write_sfm(6,afen);write_com(0x80+0x40+6); write_ds(3,afen);}if(anumfun==3){ashi++;if(ashi==24)ashi=0;write_sfm(3,ashi);write_com(0x80+0x40+3); write_ds(5,ashi);}}}if(anumfun!=0){if(timesub==0){delay(5);while(!timesub);if(anumfun==1){amiao--;if(amiao==-1)amiao=59;write_sfm(9,amiao);write_com(0x80+0x40+9); write_ds(1,amiao);}if(anumfun==2){afen--;if(afen==-1)afen=59;write_sfm(6,afen);write_com(0x80+0x40+6); write_ds(3,afen);}if(anumfun==3){ashi--;if(ashi==-1)ashi=23;write_sfm(3,ashi);write_com(0x80+0x40+3);write_ds(5,ashi);}}}}void init(){EA=1;//开总中断EX0=1;//开外部中断0IT0=1;//设定触发方式为负跳变沿有效lcden=0;//选通液晶显示屏ledrw=0;//设定液晶显示屏的读写方式为读write_com(0x38);//设置液晶显示模式为16*2显示,5*7点阵,8位数据接口 write_com(0x0c);//打开显示,并使光标不显示也不闪烁write_com(0x06);//光标指针每次自动加1write_com(1);//清屏write_com(0x80);//送地址指针for(num=0;num<16;num++){write_date(table[num]);delay(5);}write_com(0x80+0x40);//写到第二行for(num=0;num<11;num++){write_date(table1[num]);delay(5);}write_ds(0x0a,0x20);//开启时钟芯片振荡器 write_ds(0x0b,0x26);//开启闹钟read_ds(0x0c);//读取时钟芯片c寄存器}void main(){init();while(1){keyscan();set_alarm();if(flag1==1)didi();if(flag==0){//读取时间miao=read_ds(0x00);fen=read_ds(0x02);shi=read_ds(0x04);yue=read_ds(0x08);ri=read_ds(0x07);nian=read_ds(0x09);week=read_ds(0x06);//写入液晶显示屏write_sfm(9,miao);write_sfm(6,fen);write_sfm(3,shi);write_nyr(2,nian);write_nyr(5,yue);write_nyr(8,ri);write_zhou(0x0f,week);}}}void exter() interrupt 0{flag1=1;read_ds(0x0c);//读时钟芯片c寄存器。
用51单片机做的万年历,显示用12864液晶
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);}。
基于51单片机的万年历-闹钟-秒表设计
基于51单片机的万年历,闹钟,秒表设计有关接线图完整的程序代码#include<reg52.h>#define uchar unsigned char#define uint unsigned intuchar code table[]={"20 年月日"};uchar code table1[]={" : : "};uchar code table5[]={" QI CHUANG LA"};void LCD_WRITE_COM(uchar com);void LCD_WRITE_DAT(uchar dat);void LCD_CSH();void LCD_GD();void LCD_CLR();void DELAYUS(uchar i);void DELAY(uint t);void DELAY_A(uint n);void DISP_TIME();void DISL1();void DISL3();void DS1302_CSH();void DS1302_WRITE(uchar addr,uchar dat); void WRITE_BTY(uchar dat);void DSweek(uchar num);void DS1820RST();void DS1820WR(uchar dat);void KEYSCAN();void KEYMOVE();void TIME_UP();void TIME_DOWN();uchar DS1820RD();uchar READ_T();uchar DS1302_READ(uchar addr);uchar READ_BTY();sbit IO=P3^5;sbit RST=P1^7;sbit SCLK=P1^6;sbit FMQ=P2^4;sbit DQ=P2^3; //DS18B20输出口sbit RS=P2^5; //寄存器选择信号sbit RW=P2^6; //读写控制信号线sbit LCDEN=P2^7; //使能信号线sbit S1=P1^0;sbit S2=P1^1;sbit S3=P1^2;sbit S4=P1^3;sbit S=P1^4;char BW,SW,GW;uchar t,tflag;uchar m,f,s,x,r,y,n;uchar A,A_m,A_f,A_s,A_x;uchar num1,num2;uchar flag,flag_A,flag_j;uchar shi,ge;uchar M_a,M_b,M_c,M_d,M_e,M_f,temp,ss; long int z=0,m1,m2;//*********延时*********void DELAY(uint t) //延时1MS{int x,y;for(x=t;x>0;x--)for(y=110;y>0;y--);}void DELAY_US(uint i) //延时1US {while(i--);}void DELAY_A(uint i){ uint j;char k;for(j=0;j<i;j++){ if(S4==0){DELAY(20);if(S4==0){break;}}for(k=110;k>0;k--){FMQ=1;DELAY(10);FMQ=0;DELAY(10);if(S4==0){DELAY(20); if(S4==0) {break;} }}}}//*********LCD模块*******void LCD_CSH(){ LCD_WRITE_COM(0x38); //设置液晶工作模式 16*2行显示,5*7点阵,8位数据DELAY(1);LCD_WRITE_COM(0x0c); //开显示DELAY(1);LCD_WRITE_COM(0x06); //光标移动DELAY(1);LCD_WRITE_COM(0x01); //清屏DELAY(1);}void LCD_WRITE_COM(uchar com){RW=0; //写RS=0; //寄存器模式选择,写命令P0=com; //写命令LCDEN=0;DELAY(1);LCDEN=1; //使能,0到1DELAY(1);LCDEN=0; //数据送入有效}void LCD_WRITE_DAT(uchar dat){RW=0;RS=1; //寄存器选择,写数据P0=dat; //写数据LCDEN=0;DELAY(1);LCDEN=1; //使能0到1DELAY(1);LCDEN=0; //数据送入有效}void LCD_WORD(unsigned char *p){while(*p>0){ LCD_WRITE_DAT(*p) ;p++;}}//固定显示void LCD_GD(){char i;LCD_WRITE_COM(0x80); //"20 年月日"for(i=0;i<15;i++){LCD_WRITE_DAT(table[i]);DELAY(1);}LCD_WRITE_COM(0x90); //" : : "for(i=0;i<11;i++){LCD_WRITE_DAT(table1[i]);}LCD_WRITE_COM(0x99);LCD_WRITE_DAT(0x03);LCD_WRITE_DAT(0x03);LCD_WRITE_COM(0x9A);LCD_WORD("萍水缘");LCD_WRITE_DAT(0x03);LCD_WRITE_DAT(0x03);}//清屏void LCD_CLR(){LCD_WRITE_COM(0x01);DELAY(2);}//上电欢迎界面void DISL1(){ LCD_WRITE_COM(0x80);LCD_WORD("基于51单片机的万年历,欢迎使用!"); }void DISL3() //闹钟时间到的显示界面{char i;LCD_WRITE_COM(0x80);for(i=0;i<15;i++){LCD_WRITE_DAT(table5[i]);DELAY(1);}LCD_WRITE_COM(0x90);for(i=0;i<15;i++){LCD_WRITE_DAT(table5[i]);DELAY(1);}}//********DS1302模块**********void DS1302_CSH()//(写程序要对照DS1302的各个写地址){RST=0;SCLK=0;DS1302_WRITE(0x8e,0x00);//允许写DS1302_WRITE(0x80,0x00);//初始秒0DS1302_WRITE(0x82,0x00);//初始分0DS1302_WRITE(0x84,0x15);//初始时0DS1302_WRITE(0x8a,0x01);//初始星期6DS1302_WRITE(0x86,0x04);//初始日1DS1302_WRITE(0x88,0x06);//初始月1DS1302_WRITE(0x8c,0x12);//初始年11DS1302_WRITE(0x8e,0x80);//写保护关}uchar DS1302_READ(uchar addr){uchar dat;RST=0; //初始CE为0SCLK=0; //初始时钟线为0RST=1; //传输开始WRITE_BTY(addr); //传送读取时间的地址dat=READ_BTY(); //读取时间SCLK=1; //时钟线拉高RST=0; //传输结束return dat; //返回时间}void DS1302_WRITE(uchar addr,uchar dat) {RST=0; //初始CE为0SCLK=0; //初始时钟线为0RST=1; //传输开始DELAY(1);WRITE_BTY(addr); //传送读取时间的地址WRITE_BTY(dat); //写入修改的时间SCLK=1; //时钟线拉高RST=0; //传输结束}uchar READ_BTY(){uchar i,dat=0;SCLK=0;DELAY(1);for(i=0;i<8;i++){dat=dat>>1;DELAY(1);if(IO==1) //如果读出数据是1(当前数据线为高时,证明该位数据为1)dat|=0x80; //要传输数据的当前位置为1,不是,则为0SCLK=1; //拉高时钟线DELAY(1);SCLK=0; //制造下降沿DELAY(1);}return dat;}void WRITE_BTY(uchar dat){uchar i;SCLK=0; //当前时钟线为0DELAY(1);for(i=0;i<8;i++) //开始传输8为数据{IO=dat&0x01; //取最低位DELAY(1);SCLK=0; //拉低时钟线DELAY(1);SCLK=1; //拉高时钟线dat=dat>>1; //数据右移一位,准备传输下一个数据}}//显示时间void DISP_TIME(){LCD_WRITE_COM(0x81);//显示年,DS1302的读地址8d为年位置,LCD显示在0x81位置shi=DS1302_READ(0x8d)/16;ge=DS1302_READ(0x8d)%16;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x83); //显示月,DS1302的读地址83为年位置shi=DS1302_READ(0x89)/16;ge=DS1302_READ(0x89)%16;LCD_WRITE_DAT(shi+0x30);LCD_WRITE_DAT(ge+0x30);LCD_WRITE_COM(0x85);//显示日shi=DS1302_READ(0x87)/16;ge=DS1302_READ(0x87)%16;LCD_WRITE_DAT(shi+0x30);LCD_WRITE_DAT(ge+0x30);LCD_WRITE_COM(0x90);//显示小时shi=DS1302_READ(0x85)/16;ge=DS1302_READ(0x85)%16;LCD_WRITE_DAT(shi+0x30);LCD_WRITE_DAT(ge+0x30);LCD_WRITE_COM(0x92);//显示分钟shi=DS1302_READ(0x83)/16;ge=DS1302_READ(0x83)%16;LCD_WRITE_DAT(shi+0x30);LCD_WRITE_DAT(ge+0x30);LCD_WRITE_COM(0x94);//显示秒shi=DS1302_READ(0x81)/16;ge=DS1302_READ(0x81)%16;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);DSweek(DS1302_READ(0x8b)); //显示星期if(A==1) //显示闹钟{LCD_WRITE_COM(0x87);LCD_WRITE_DAT(0x20);LCD_WRITE_DAT(0x0e);}if(A!=1){LCD_WRITE_COM(0x87);LCD_WRITE_DAT(' ');}}//显示时间的星期模块void DSweek(uchar num){LCD_WRITE_COM(0x95); //95位置清空,96.97显示周一,二,三,四,五,六,日LCD_WRITE_DAT(0x20);LCD_WRITE_DAT(0x20);LCD_WRITE_COM(0x96);switch(num){case 1:LCD_WRITE_DAT(0xD6);LCD_WRITE_DAT(0xDC);LCD_WRITE_DAT(0xD2);LCD_WRITE_DAT(0xBB);break;case 2:LCD_WRITE_DAT(0xD6);LCD_WRITE_DAT(0xDC);LCD_WRITE_DAT(0xB6);LCD_WRITE_DAT(0xFE);break;case 3:LCD_WRITE_DAT(0xD6); LCD_WRITE_DAT(0xDC);LCD_WRITE_DAT(0xC8);LCD_WRITE_DAT(0xFD);break;case 4:LCD_WRITE_DAT(0xD6); LCD_WRITE_DAT(0xDC);LCD_WRITE_DAT(0xCB);LCD_WRITE_DAT(0xC4);break;case 5:LCD_WRITE_DAT(0xD6); LCD_WRITE_DAT(0xDC);LCD_WRITE_DAT(0xCE);LCD_WRITE_DAT(0xE5);break;case 6:LCD_WRITE_DAT(0xD6); LCD_WRITE_DAT(0xDC);LCD_WRITE_DAT(0xC1);LCD_WRITE_DAT(0xF9);break;case 7:LCD_WRITE_DAT(0xD6); LCD_WRITE_DAT(0xDC);LCD_WRITE_DAT(0xC8);LCD_WRITE_DAT(0xD5);break;}}//**********温度模块*******void DS1820RST() //DS18b20的初始化函数{ uchar x=0;DQ=1; //DQ复位DELAY_US(4); //延时DQ=0; //DQ拉低DELAY_US(100); //精确延时大于480usDQ=1; //拉高DELAY_US(40);x=DQ;}uchar DS1820RD() //读一个字节{uchar i=0,dat=0;for (i=8;i>0;i--){DQ=0; //给脉冲信号 dat=dat>>1;DQ=1; //给脉冲信号if(DQ==1)dat|=0x80;DELAY_US(10);}return dat; //写一个字节}void DS1820WR(uchar dat){char i=0;for (i=8;i>0;i--){DQ=0;DQ=dat&0x01;DELAY_US(10);DQ=1;dat=dat>>1;}}uchar READ_T(){uchar a,b;DS1820RST();DS1820WR(0xcc);//跳过读序列号(固定)DS1820WR(0x44);//启动温度转换DS1820RST();DS1820WR(0xcc);//跳过读序列号DS1820WR(0xbe);//读取温度a=DS1820RD();b=DS1820RD();b<<=4;b+=(a&0xf0)>>4;t=b;return t;}//显示温度void DISP_T(){ uchar R1;R1=READ_T();LCD_WRITE_COM(0xc8);LCD_WRITE_DAT(0xCE);LCD_WRITE_DAT(0xC2);LCD_WRITE_DAT(0xB6);LCD_WRITE_DAT(0xC8);LCD_WRITE_DAT(':');if(R1<0x81){LCD_WRITE_DAT(0x30+R1/100);} else{R1=~(R1)+1;LCD_WRITE_DAT('-');}LCD_WRITE_DAT(0x30+R1%100/10);LCD_WRITE_DAT(0x30+R1%10);LCD_WRITE_DAT(0xA1);LCD_WRITE_DAT(0xE6);}//*******键盘******//读暂停时的时间void TIME(){if(flag==0){m=DS1302_READ(0x81); //分别读出秒,分,时,星期,日,月,年(DS1302的读地址应用)f=DS1302_READ(0x83);s=DS1302_READ(0x85);x=DS1302_READ(0x8b);r=DS1302_READ(0x87);y=DS1302_READ(0x89);n=DS1302_READ(0x8d);}}//时间更新void TIME_UPDATE(){DS1302_WRITE(0x8e,0x00); //写允许DS1302_WRITE(0x80,m); //分别写出秒,分,时,星期,日,月,年(DS1302的写地址应用)DS1302_WRITE(0x82,f);DS1302_WRITE(0x84,s);DS1302_WRITE(0x8a,x);DS1302_WRITE(0x86,r);DS1302_WRITE(0x88,y);DS1302_WRITE(0x8c,n);DS1302_WRITE(0x8e,0x80); //禁止写}//闹钟void ALARM_CLOCK(){LCD_CLR();DELAY(10);DISL3(); //显示起床DELAY_A(100);FMQ=0; //蜂鸣器响flag_A=0;LCD_CLR();LCD_GD(); //固定显示}//闹钟开关显示void ALARM_KG(){if(x!=1){A=0;LCD_WRITE_COM(0x85);LCD_WRITE_DAT(0xb9);LCD_WRITE_DAT(0xd8);x=0;}if(x==1){A=1;LCD_WRITE_COM(0x85);LCD_WRITE_DAT(0xbf);LCD_WRITE_DAT(0xaa);}}//*******秒表******void CSH(){EA=1;ET0=1;TMOD=0x01;TH0=(65535-4900)/256;TL0=(65535-4900)%256;TR0=0;ss=0;M_a=M_b=M_c=M_d=0;}//秒表的键盘扫描void KEYSCAN_M(){ S=0;if(S2==0){DELAY(100);if(S2==0){while(S2==0);ss=~ss;TR0=1;if(ss==0) //S2可以暂停或者继续TR0=0;}}if(S3==0){DELAY(100);if(S3==0){while(S3==0){M_a=M_b=M_c=M_d=0;}}}}void TIME_M() interrupt 1{TH0=(65535-4900)/256;TL0=(65535-4900)%256;temp++;if(temp==2){temp=0;M_c++;if(M_c==10){M_c=0;M_b++;if(M_b==10){M_b=0;M_a++;if(M_a==10){M_a=0;M_d++;if(M_d==6){M_d=0;M_e++;if(M_e==0){M_e=0;M_f++;}}}}}}}//显示秒表,fe:da:bcvoid DISP_M(){ LCD_WRITE_COM(0x83); //显示秒表LCD_WRITE_DAT(0xc3);LCD_WRITE_DAT(0xeb);LCD_WRITE_DAT(0xb1);LCD_WRITE_DAT(0xed);LCD_WRITE_COM(0x91); //显示00:00::00LCD_WRITE_DAT(0x30+M_f);LCD_WRITE_DAT(0x30+M_e);LCD_WRITE_DAT(':');LCD_WRITE_COM(0x93);LCD_WRITE_DAT(0x30+M_d);LCD_WRITE_DAT(0x30+M_a);LCD_WRITE_DAT(':');LCD_WRITE_COM(0x95);LCD_WRITE_DAT(0x30+M_b);LCD_WRITE_DAT(0x30+M_c);}//按键扫描,s1为功能显示,s2为光标移动/秒表暂停(开始),s3为加时间和秒表复位,s4为减时间和停止闹钟void KEYSCAN(){ S=0;if(S1==0){DELAY(100);if(S1==0)while(!S1);{num1++; // 界面切换switch(num1){case 1: num2=0;m=A_m;f=A_f;s=A_s;x=A_x;LCD_CLR();LCD_WRITE_COM(0x80); //显示闹钟设置LCD_WRITE_DAT(0xC4);LCD_WRITE_DAT(0xD6);LCD_WRITE_DAT(0xD6);LCD_WRITE_DAT(0xD3);LCD_WRITE_DAT(0xC9);LCD_WRITE_DAT(0xE8);LCD_WRITE_DAT(0xD6);LCD_WRITE_DAT(0xC3);LCD_WRITE_COM(0x94);LCD_WRITE_DAT(0x30+m/16); LCD_WRITE_DAT(0x30+m%16);LCD_WRITE_COM(0x92);LCD_WRITE_DAT(0x30+f/16); LCD_WRITE_DAT(0x30+f%16); LCD_WRITE_DAT(':');LCD_WRITE_COM(0x90);LCD_WRITE_DAT(0x30+s/16); LCD_WRITE_DAT(0x30+s%16); LCD_WRITE_DAT(':');LCD_WRITE_COM(0x8b);ALARM_KG();break;case 2: LCD_WRITE_COM(0x0c); //开显示LCD_CLR();break;case 3: num2=0;num1=0;A_m=m;A_f=f;A_s=s;A_x=x;LCD_WRITE_COM(0x0c);flag=0; //读暂停的时间标志位LCD_CLR();LCD_GD(); //固定显示break;}}}}//光标移动void KEYMOVE(){ S=0;if(S2==0){ DELAY(100);if(S2==0)while(!S2);{num2++;}}if(num1==0) //调整时间,日期{switch(num2){case 1: //S2按下一次TIME(); //读出暂停的时间flag=1;LCD_WRITE_COM(0x97); //光标在星期位置闪烁LCD_WRITE_COM(0x0f);TIME_UPDATE(); //时间更新,写入设置的时间break;case 2:LCD_WRITE_COM(0x94); //光标在秒位置闪烁TIME_UPDATE(); //时间更新,写入设置的时间break;case 3:LCD_WRITE_COM(0x92); //光标在分钟位置闪烁TIME_UPDATE(); //时间更新,写入设置的时间break;case 4:LCD_WRITE_COM(0x90); //光标在时位置闪烁TIME_UPDATE(); //时间更新,写入设置的时间break;case 5:LCD_WRITE_COM(0x85); //光标在日期位置闪烁TIME_UPDATE(); //时间更新,写入设置的时间break;case 6:LCD_WRITE_COM(0x83); //光标在月份位置闪烁TIME_UPDATE(); //时间更新,写入设置的时间break;case 7:LCD_WRITE_COM(0x81); //光标在年份位置闪烁TIME_UPDATE(); //时间更新,写入设置的时间break;case 8:LCD_WRITE_COM(0x0c); //开显示flag=0; // 读暂停的时间标志位TIME_UPDATE(); //时间更新,写入设置的时间num2=0; //复位 break;}}if(num1==1) //调整闹钟{switch(num2){case 1:LCD_WRITE_COM(0x85); //是够开闹钟LCD_WRITE_COM(0x0f);break;case 2:LCD_WRITE_COM(0x94); //光标在秒位置闪烁break;case 3:LCD_WRITE_COM(0x92); //光标在分钟位置闪烁break;case 4:LCD_WRITE_COM(0x90); //光标在小时位置闪烁break;case 5:LCD_WRITE_COM(0x0c); //开显示num2=0; //复位 break;}}if(S3==0) //加时间{ DELAY(100);if(S3==0)while(!S3);{TIME_UP();}}if(S4==0) //减时间{ DELAY(100);if(S4==0)while(!S4);{TIME_DOWN();}}}//加时间void TIME_UP(){switch(num2){case 1:x++; //星期加1if(x==0x08) x=1;if(num1==0){ DS1302_WRITE(0x8e,0x00);//写允许DS1302_WRITE(0x8a,x);DS1302_WRITE(0x8e,0x80); //写禁止DSweek(DS1302_READ(0x8b));//显示时间的星期模块}if(num1==1){ ALARM_KG();} //闹钟开关显示 break;case 2: m++; //秒加1if(m%16==10) m=(m&0xf0)+0x10;if(m==0x60) m=0;shi=m>>4;ge=m&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x94);break;case 3:f++; //分钟加1if(f%16==10) f=(f&0xf0)+0x10;if(f==0x60) f=0;shi=f>>4;ge=f&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x92);break;case 4:s++; //小时加1if(s%16==10) s=(s&0xf0)+0x10; if(s==0x24) s=0;shi=s>>4;ge=s&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x90);break;case 5:r++; //日期加1if(r%16==10) r=(r&0xf0)+0x10; if(r==0x32) r=1;shi=r>>4;ge=r&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x85);break;case 6:y++; //月份加1if(y%16==10) y=(y&0xf0)+0x10; if(y==0x13) y=1;shi=y>>4;ge=y&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x83);break;case 7:n++; //年份加1if(n%16==10) n=(n&0xf0)+0x10; if(n==0x99) n=1;shi=n>>4;ge=n&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x81);break;}}//减时间void TIME_DOWN(){switch(num2){case 1:x--; //星期减1if(x==0x00) x=7;if(num1==0){DS1302_WRITE(0x8e,0x00); DS1302_WRITE(0x8a,x);DS1302_WRITE(0x8e,0x80);DSweek(DS1302_READ(0x8b));}if(num1==1){ ALARM_KG();}break;case 2:m--; //秒减1if(m%16==15) m=(m&0xf0)+0x09; if(m==0xf9) m=0x59;shi=m>>4;ge=m&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x94);break;case 3:f--; //分钟减1if(f%16==15) f=(f&0xf0)+0x09; if(f==0xf9) f=0x59;shi=f>>4;ge=f&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x92);break;case 4:s--; //小时减1if(s%16==15) s=(s&0xf0)+0x09; if(s==0xf9) s=0x23;shi=s>>4;ge=s&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x90);break;case 5:r--; //日期减1if(r%16==15) r=(r&0xf0)+0x09; if(r==0xf9) r=0x31;shi=r>>4;ge=r&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x95);break;case 6:y--; //月份减1if(y%16==15) y=(y&0xf0)+0x09; if(y==0xf9) y=0x12;shi=y>>4;ge=y&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x93);break;case 7:n--; //年减1if(n%16==15) n=(n&0xf0)+0x09; if(n==0xf9) n=0x99;shi=n>>4;ge=n&0x0f;LCD_WRITE_DAT(0x30+shi);LCD_WRITE_DAT(0x30+ge);LCD_WRITE_COM(0x91);break;}}void main(){ CSH();LCD_CSH();DELAY(10);DS1302_CSH();DISL1(); //上电欢迎界面DELAY(10000);LCD_CLR(); //清屏LCD_GD(); //固定显示while(1){ KEYSCAN();if(num1==2){while(1){DISP_M();KEYSCAN_M();if(S1==0){DELAY(100);if(S1==0)break;}}}KEYMOVE();if(num1==0&&flag==0){DISP_TIME();DISP_T();if(DS1302_READ(0x83)==A_f&&DS1302_READ(0x85)==A_s&&DS1302_R EAD(0x81)==A_m&&A==1){ALARM_CLOCK();}}}}。
单片机万年历C程序
#include<reg52.h>#define N 4typedef unsigned char uchar ;typedef unsigned int uint ;sbit SCLK = P3^2; //实时时钟时钟线引脚sbit IO = P1^6; //实时时钟数据线引脚sbit RST = P3^7; //实时时钟复位线引脚sbit clk=P0^2;sbit Data=P0^3;sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;uchar cod[N],tab[]={0xb7,0x90,0x3d,0xb9,0x9a,0xab,0xaf,0xb0,0xbf,0xbb};uchar qq;/****************************************//函数群名称:cci函数群//函数功能:扫描4*4键盘并返回值//函数参数:无//函数返回值:键盘值//说明:值16为无输入******************************************/void Delay(uchar time){uchar i,j;for(i=time;i>0;i--)for(j=25;j>0;j--);}uchar Key(void){uchar ucTemp1,ucTemp2;P2 = 0xf0; //先将所有行线拉低Delay(1);if( (P2&0xf0)!= 0xf0 ) //如果列线有变化{Delay(1); //延迟10ms左右。
if( (P2&0xf0)!= 0xf0 ) //如果此时此刻列线还有变化,说明确实有按键按下{ucTemp1=P2;P2=0x0f;ucTemp2=P2;return ucTemp1|ucTemp2; //返回识别码,识别码是根据上一条语句的算法计算好的,//每个识别码对应一个按键,一共有16个识别码.}}return 0x00; //如果没有按键按下,返回0 }uchar cci(){uchar a=0;a=Key(); //键盘返回值switch(a){case 0x7e: return 3; break; //键盘各个返回值对应的键值case 0xbe: return 7; break;case 0xde: return 11; break;case 0xee: return 15; break;case 0x7d: return 2; break;case 0xbd: return 6; break;case 0xdd: return 10; break;case 0xed: return 14; break;case 0x7b: return 1; break;case 0xbb: return 5; break;case 0xdb: return 9; break;case 0xeb: return 13; break;case 0x77: return 0; break;case 0xb7: return 4; break;case 0xd7: return 8; break;case 0xe7: return 12; break;default: return 16; break; //无键按下返回16 }}/******************************************//函数群名称:xianshi(显示)函数//函数功能:显示一个字符串//函数参数:字符串头地址//函数返回值:无//说明:只能输入长度为四位的字符串********************************************/void xsq(void) //显示器函数{uchar a,b,c,d;for(d=20;d;d--){c=0xe0; //c赋初值for(a=0;a<4;a++){P0 = 0x00;qq = cod[a]; //送入寄存器的值for(b=8;b>0;b--) //将八个数送入寄存器{Data=(bit) ( qq&0x80 );clk=0; //制造一个脉冲,一共八个clk=1;qq=qq<<1; //qq移位}P0 = ~c; //控制数码管亮Delay(1); //延时c=(c<<1)|0x10; //移位控制数码管}}}void fz(uchar a[],uchar cod[],uchar b) //赋值函数将a的值给cod{uchar i,c=b-1;for(i=0;i<b;i++,c--) //将a前几位赋給cod{cod[3-i]=a[c];}for(;i<N;i++){cod[3-i]=0x00; //cod前几个值为不显示}xsq();}/******************************************//函数群名称:xszh(显示转换)函数//函数功能:将一个uchar字符转换为一个可以输出无符号数//函数参数:字符数//函数返回值:无符号字符数//说明:只能输入0到9的字符********************************************//*uchar xszh(uchar a) //显示转换函数,将一个uchar型数组转换为显示用的uchar型数组{switch (a){case 0: return 0xb7;break;case 1: return 0x90;break;case 2: return 0x3d;break;case 3: return 0xb9;break;case 4: return 0x9a;break;case 5: return 0xab;break;case 6: return 0xaf;break;case 7: return 0xb0;break;case 8: return 0xbf;break;case 9: return 0xbb;break;}}*//******************************************//函数群名称:xianshi(显示)函数//函数功能:将一个uchar字符串转换为一个可以输出无符号字符串//函数参数:字符串头地址,字符串有效位数//函数返回值:无//说明:只能输入长度为四位的字符串********************************************/void xianshi(uchar a[],uchar i) //将要显示的数转换赋予cod数组,需要输入赋予数组和数的个数{uchar b,c[N];for(b=0;b<i;b++){c[b]=tab[a[b]];/*xszh(a[b]);*/ //将a数组的值转换为可以输出的值给c函数}fz(c,cod,i);}void RTInputByte(uchar d) //向1302写入一数据{uchar i;ACC = d;for(i=8; i>0; i--){IO = ACC0; //相当于汇编中的RRCSCLK = 0;SCLK = 1;ACC = ACC >> 1;}}uchar RTOutputByte(void) //从1302中读出一数据{uchar i;for(i=0; i<8; i++){ //相当于汇编中的RRCACC7 = IO;SCLK = 1;SCLK = 0;ACC = ACC >>1;}SCLK = 1;return(ACC);}void W1302(uchar ucAddr, uchar ucDa) //前一字节为命令,后一字节为数据{RST = 0;SCLK = 0;RST = 1;RTInputByte(ucAddr); // 地址,命令RTInputByte(ucDa); //写1Byte数据SCLK = 1;RST = 0;}uchar R1302(uchar ucAddr){uchar ucData;RST = 0;SCLK = 0;RST = 1;RTInputByte(ucAddr); // 地址,命令ucData = RTOutputByte(); // 读1Byte数据SCLK = 1;RST = 0;return(ucData);}void main(void){uchar i,c=0,keys=17,da;uchar a[N];W1302( 0x8f, 0x00);W1302( 0x8e, 0x00); //打开写保护W1302( 0x80, 0x00);while (1) //进入循环{if(cci()!=keys) //要求每次输入与前一次不一样,防止不停输入{keys=cci(); //将键值记录if(keys==10) //按10显示年{while(1){W1302( 0x8e, 0x00);da=R1302(0x8d); //向年寄存器读出数据a[0]=2;a[1]=0;a[2]=(da&0xf0)/16;a[3]=(da&0x0f); //上四句将其十进制化并将键值记录i=4;xianshi(a,i); //显示keys=cci();if(keys==14){for(i=2;i<4;){if(cci()<10){keys=cci();a[i]=keys;i++;while(1){if(cci()==16)break;xianshi(a,i);}}xianshi(a,i);}W1302( 0x8e, 0x00);W1302(0x8c,(a[2]*16)|a[3]);}if(keys>10&&keys<14)break;} //将键值的有效位数记录}if(keys==11) //按11显示月日{while(1){W1302( 0x8e, 0x00);da=R1302(0x89); //向月寄存器读出数据a[0]=(da&0xf0)>>4;a[1]=(da&0x0f);W1302( 0x8e, 0x00);da=R1302(0x87); //向日寄存器读出数据a[2]=(da&0xf0)>>4;a[3]=(da&0x0f); //将键值记录i=4;xianshi(a,i);keys=cci();if(keys==14){for(i=0;i<4;){if(cci()<10){keys=cci();a[i]=keys;i++;while(1){if(cci()==16)break;xianshi(a,i);}}xianshi(a,i);}W1302( 0x8e, 0x00);W1302(0x88,(a[0]*16)|a[1]);W1302(0x86,(a[2]*16)|a[3]);}if(keys==10||keys==12||keys==13)break;} //将键值的有效位数记录}if(keys==12) //按12显示时分{while(1){W1302( 0x8e, 0x00);da=R1302(0x85); //向时寄存器读出数据a[0]=(da&0xf0)>>4;a[1]=(da&0x0f);W1302( 0x8e, 0x00);da=R1302(0x83); //向分寄存器读出数据a[2]=(da&0xf0)>>4;a[3]=(da&0x0f); //将键值记录i=4;xianshi(a,i);keys=cci();if(keys==14){for(i=0;i<4;){if(cci()<10){keys=cci();a[i]=keys;i++;while(1){if(cci()==16)break;xianshi(a,i);}}xianshi(a,i);}W1302( 0x8e, 0x00);W1302(0x84,(a[0]*16)|a[1]);W1302(0x82,(a[2]*16)|a[3]);}if(keys==10||keys==11||keys==13)break;} //将键值的有效位数记录}if(keys==13) //按13显示秒{while(1){W1302( 0x8e, 0x00);da=R1302(0x81); //向秒寄存器读出数据a[0]=0;a[1]=0;a[2]=(da&0xf0)>>4;a[3]=(da&0x0f); //将键值记录i=4;xianshi(a,i);keys=cci();if(keys==14){for(i=2;i<4;){if(cci()<10){keys=cci();a[i]=keys;i++;while(1){if(cci()==16)break;xianshi(a,i);}}xianshi(a,i);}W1302( 0x8e, 0x00);W1302(0x80,(a[2]*16)|a[3]);}if(keys>9&&keys<13)break;} //将键值的有效位数记录}}xianshi(a,i); //显示a数组}}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
uint temp;
float f_temp;
uint warn_l1=270;
uint warn_l2=250;
uint warn_h1=300;
uint warn_h2=320;
uint get_temp();
void delayms(uint x);
void write_com(uchar com);
该程序为51单片机c语言电子万年历
#include"reg52.h"
//#include<stdio.h>
#define uchar unsigned char
#define uint unsigned int
sbit lcden=P3^4;
sbit lcdrs=P3^5;
sbit DATA=P0^7;
void DisplayYear(uchar x);
void DisplayWeek(uchar x);
void dis_temp(uint t);
void read_date(void);
void turn_val(char newval,uchar flag,
uchar newaddr,uchar s1num);
minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = ReadSet1302(0x85);
hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = ReadSet1302(0x87);
write_data(' ');
dis_temp(get_temp());
}
void DisSecond(uchar x)
{
uchar i,j;
ReadValue = ReadSet1302(0x81);
second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
WriteSet1302(0x8c,((14/10)<<4|(14%10))); //nian
//WriteSet1302(0x8a,((4/10)<<4|(4%10)));
}
/////////////////////////////////////////////////////////////////
write_data(j+0x30);
write_com(0x88);
write_data('/');
}
void DisplayYear(uchax/10;
j=x%10;
write_com(0x81);
write_data(2+0x30);
write_com(0x82);
write_data(i+0x30);
write_com(0x8a);
write_data(j+0x30);
}
void DisplayMonth(uchar x)
{
uchar i,j;
i=x/10;
j=x%10;
write_com(0x86);
write_data(i+0x30);
write_com(0x87);
{
write_data(table2[x]);
x++;
}
}
void read_date(void)
{
ReadValue = ReadSet1302(0x81);
second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = ReadSet1302(0x83);
void Write1302(uchar dat)
{
uchar i;
SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备
delayms(2); //稍微等待,使硬件做好准备
for(i=0;i<8;i++) //连续写8个二进制位数据
{
DATA=dat&0x01; //取出dat的第0位数据写入1302
year=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
write_data(i+0x30);
write_com(0x80+0x44);
write_data(j+0x30);
write_com(0x80+0x45);
write_data(':');
}
void DisplayHour(uchar x)
{
uchar i,j;
i=x/10;
j=x%10;
write_com(0x80+0x40);
sbit RST=P0^5;
sbit SCLK=P0^6;
sbit menu=P3^0; //菜单
sbit add=P3^1; //加一
sbit dec=P3^7; //减一
sbit led0=P1^0;
sbit led1=P1^1;
sbit led2=P1^2;
sbit led3=P1^3;
sbit ds=P3^2;
void write_data(uchar date);
void init();
void dis_temp(uint t);
void Write1302(uchar dat);
void WriteSet1302(uchar Cmd,uchar dat);
uchar Read1302(void);
uchar ReadSet1302(uchar Cmd);
write_data(0+0x30);
write_com(0x83);
write_data(i+0x30);
write_com(0x84);
write_data(j+0x30);
write_com(0x85);
write_data('/');
}
void DisplayWeek(uchar x)
{ uchar i;
dat|=0x80; //将1取出,写在dat的最高位
SCLK=1; //将SCLK置于高电平,为下降沿读出
delayms(2); //稍微等待
SCLK=0; //拉低SCLK,形成脉冲下降沿
delayms(2); //稍微等待
}
return dat; //将读出的数据返回
}
uchar ReadSet1302(uchar Cmd)
uchar ReadValue,num,time;
void delayms(uint x)
{
uint i,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
////////////////////////////////////////////////////////////
{
RST=0; //禁止数据传递
SCLK=0; //确保写数居前SCLK被拉低
RST=1; //启动数据传输
delayms(2); //稍微等待,使硬件做好准备
Write1302(Cmd); //写入命令字
Write1302(dat); //写数据
SCLK=1; //将时钟电平置于已知状态
RST=0; //禁止数据传递
}
void Init_DS1302(void)
{
WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令
WriteSet1302(0x80,((0/10)<<4|(0%10))); //根据写秒寄存器命令字,写入秒的初始值
WriteSet1302(0x82,((59/10)<<4|(59%10))); //根据写分寄存器命令字,写入分的初始值
delayms(2); //稍微等待,使硬件做好准备
SCLK=1; //上升沿写入数据
delayms(2); //稍微等待,使硬件做好准备
SCLK=0; //重新拉低SCLK,形成脉冲
dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位
}
}
void WriteSet1302(uchar Cmd,uchar dat)
lcden=0;
}
void init()
{
lcden=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
}
/////////////////////////////////////////////////////////////////
void write_com(uchar com)
{
lcdrs=0;
P2=com;
delayms(5);
lcden=1;
delayms(5);
lcden=0;
}
void write_data(uchar date)
{
lcdrs=1;
P2=date;
delayms(5);