51单片机汇编语言万年历完美版
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单片机实现万年历程序文件
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寄存器。
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单片机控制的语音报时万年历-----20/11/2013 SDU(WH)一.实验要求运用单片机及相关外设实现以下功能:1)万年历及时钟显示2)时间日期可调3)可对时间进行整点报时和随机报时二.方案分析根据实验要求,选用STC公司的8051系列,STC12C5A16S2增强型51单片机。
此单片机功能强大,具有片内EEPROM、1T分频系数、片内ADC转换器等较为实用功能,故选用此款。
实验中,对日期和时间进行显示,显示的字符数较多,故选用12864LCD屏幕。
该屏幕操作较为便捷,外围电路相对简单,实用性较强。
为了实现要求中的时间日期可调,故按键是不可缺少的,所以使用了较多的按键。
一方面,单片机的I/O口较为充足;另一方面,按键较多,选择的余地较大,方便编程控制。
实验中,并未要求对时间和日期进行保存和掉电续运行,所以并未添加EEPROM和DS12C887-RTC芯片。
实际上,对万年历来说,这是较为重要的,但为了方便实现和编程的简单,此处并未添加,而是使用单片机的定时器控制时间,精度有差别。
且上电默认时间为2014-01-01 09:00:00 之后需要手动调整为正确时间。
要求中的语音报时功能,这里选用ISD1760芯片的模块来帮助实现。
此模块通过软件模拟SPI协议控制。
先将所需要的声音片段录入芯片的EEPROM区域,之后读出各段声音的地址段,然后在程序中定义出相应地址予以控制播放哪一声音片段。
三.电路硬件设计实际效果图四.程序代码部分Main.h#ifndef _MAIN_H#define _MAIN_H#include "reg52.h"#include "INTRINS.H"#include "math.h"#include "string.h"#include "key.h"#include "led.h"#include "12864.h"#include "main.h"#include "isd1700.h"#include "sound.h"extern unsigned int count;extern unsigned int key_time[8]; extern unsigned char key_new; extern unsigned char key_old; extern unsigned char stop_flag; extern unsigned char key_follow[8]; extern unsigned int key_num[8];sbit BEEP=P3^7;sbit ISD_SS=P0^7;sbit ISD_MISO=P0^4;sbit ISD_MOSI=P0^5;sbit ISD_SCLK=P0^6;extern unsigned char date_show[]; extern unsigned char time_show[]; extern unsigned char sec;extern unsigned char min;extern unsigned char hour;extern unsigned char day;extern unsigned char month;extern unsigned char year_f;extern unsigned char year_l;extern unsigned char leap_year_flag; extern unsigned char update_flag; extern unsigned char adjust_flag; extern unsigned char key;unsigned char report();#endifMain.c#include "main.h"unsigned int count=0;unsigned int key_num[8]=0;unsigned char key_new=0;unsigned char key_old=0;unsigned char stop_flag=0;unsigned char key_follow[8]=0; unsigned char sec=1;unsigned char min=0;unsigned char hour=9;unsigned char day=1;unsigned char month=1;unsigned char year_f=20;unsigned char year_l=14;unsigned char leap_year_flag=0; unsigned char date_show[]="2014-01-01"; unsigned char time_show[]="09:00:00"; unsigned char update_flag=1;unsigned char key=0;unsigned char adjust_flag=0;unsigned char adjust_pos=0;unsigned char report_flag=0;void main(){unsigned char i;P2=0XFF;BEEP=0;init();initinal(); //调用LCD字库初始化程序TMOD=0x01; //使用定时器T0TH0=(65536-1000)/256; //定时器高八位赋初值TL0=(65536-1000)%256; //定时器低八位赋初值 */ EA=1; //开中断总允许ET0=1; //允许T0中断TR0=1; //启动定时器T0while(1){if(update_flag){lcd_pos(1,0);for(i=0;i<10;i++)write_dat(date_show[i]);lcd_pos(2,4);for(i=0;i<8;i++)write_dat(time_show[i]);update_flag=0;}if(key!=keyscan_nor()){key=keyscan_nor();if(key==8&&!adjust_flag)adjust_flag=1;if(key&&adjust_flag){if(key==1){adjust_pos++;if(adjust_pos==14)adjust_pos=0;}else if(key==2){if(!adjust_pos)adjust_pos=13;elseadjust_pos--;}else if(key==6){if(!adjust_pos)sec++;else if(adjust_pos==1)sec=sec+10;else if(adjust_pos==2)min++;else if(adjust_pos==3)min=min+10;else if(adjust_pos==4)hour++;else if(adjust_pos==5)hour=hour+10;else if(adjust_pos==6)day++;else if(adjust_pos==7)day=day+10;else if(adjust_pos==8)month++;else if(adjust_pos==9)month=month+10;else if(adjust_pos==10)year_l++;else if(adjust_pos==11)year_l=year_l+10;else if(adjust_pos==12)year_f++;else if(adjust_pos==13)year_f=year_f+10; }else if(key==7){if(!adjust_pos)sec--;else if(adjust_pos==1)sec=sec-10;else if(adjust_pos==2)min--;else if(adjust_pos==3)min=min-10;else if(adjust_pos==4)hour--;else if(adjust_pos==5)hour=hour-10;else if(adjust_pos==6)day--;else if(adjust_pos==7)day=day-10;else if(adjust_pos==8)month--;else if(adjust_pos==9)month=month-10;else if(adjust_pos==10)year_l--;else if(adjust_pos==11)year_l=year_l-10;else if(adjust_pos==12)year_f--;else if(adjust_pos==13)year_f=year_f-10;}else if(key==3)adjust_flag=0;if(key==6||key==7){if(sec>=80)sec=0;if(min>=80)min=0;if(hour>=40)hour=0;if(month>30)month=1;if(day>50)day=0;if(year_f>=120)year_f=0;if(year_l>=120)year_l=0;}}}if(key==3)report_flag=1;if(report_flag){clrram();Dingwei(2,1);lcd_mesg("REPORTING!!!");report();clrram();}}}void time0() interrupt 1{static unsigned char timer=0;TH0=(65536-50000)/256; //定时器高八位赋初值TL0=(65536-50000)%256; //定时器低八位赋初值timer++;if(timer==20){sec++;time_show[6]=sec/10+48;time_show[7]=sec%10+48;if(sec>=60){sec=0;min++;time_show[6]=sec/10+48;time_show[7]=sec%10+48;time_show[3]=min/10+48;time_show[4]=min%10+48;}if(min>=60){min=0;hour++;time_show[3]=min/10+48;time_show[4]=min%10+48;time_show[0]=hour/10+48;time_show[1]=hour%10+48;}if(hour>=24){hour=0;day++;time_show[0]=hour/10+48;time_show[1]=hour%10+48;date_show[8]=day/10+48;date_show[9]=day%10+48;}if((day>=29&&!leap_year_flag&&month==2)||(day==30&&leap_year_flag&&month==2 )||(day==31&&(month==4||month==6||month==9||month==11))||(month==32)){day=1;month++;date_show[8]=day/10+48;date_show[9]=day%10+48;date_show[5]=month/10+48;date_show[6]=month%10+48;}if(month>=13){month=1;year_l++;date_show[5]=month/10+48;date_show[6]=month%10+48;date_show[0]=year_f/10+48;date_show[1]=year_f%10+48;date_show[2]=year_l/10+48;date_show[3]=year_l%10+48;}if(year_l>=100){year_l=0;year_f++;if(((!((year_f*100+year_l)%4))&&((year_f*100+year_l)%100))||(!((year_f*100+ year_l)%400)))leap_year_flag=1;elseleap_year_flag=0;date_show[0]=year_f/10+48;date_show[1]=year_f%10+48;date_show[2]=year_l/10+48;date_show[3]=year_l%10+48;}timer=0;update_flag=1;if(adjust_flag){time_show[7]=sec%10+48;time_show[6]=sec/10+48;time_show[4]=min%10+48;time_show[3]=min/10+48;time_show[1]=hour%10+48;time_show[0]=hour/10+48;date_show[9]=day%10+48;date_show[8]=day/10+48;date_show[6]=month%10+48;date_show[5]=month/10+48;date_show[3]=year_l%10+48;date_show[2]=year_l/10+48;date_show[1]=year_f%10+48;date_show[0]=year_f/10+48;}}if(adjust_flag&&timer==10){if(!adjust_pos)time_show[7]=' ';else if(adjust_pos==1)time_show[6]=' ';else if(adjust_pos==2)time_show[4]=' ';else if(adjust_pos==3)time_show[3]=' ';else if(adjust_pos==4)time_show[1]=' ';else if(adjust_pos==5)time_show[0]=' ';else if(adjust_pos==6)date_show[9]=' ';else if(adjust_pos==7)date_show[8]=' ';else if(adjust_pos==8)date_show[6]=' ';else if(adjust_pos==9)date_show[5]=' ';else if(adjust_pos==10)date_show[3]=' ';else if(adjust_pos==11)date_show[2]=' ';else if(adjust_pos==12)date_show[1]=' ';else if(adjust_pos==13)date_show[0]=' ';update_flag=1;}if(!min&&!sec&&!adjust_flag)report_flag=1;}unsigned char report(){PlaySoundTick(11);long_delay();if(!min){if(hour<=10){PlaySoundTick(hour);short_delay();PlaySoundTick(12);short_delay();PlaySoundTick(14);short_delay();}else if(hour>10&&hour<20){PlaySoundTick(10);short_delay();PlaySoundTick(hour-10);short_delay();PlaySoundTick(12);short_delay();PlaySoundTick(14);short_delay();}else if(hour==20){PlaySoundTick(2);short_delay();PlaySoundTick(10);short_delay();PlaySoundTick(12);short_delay();PlaySoundTick(14);short_delay();else{PlaySoundTick(2);short_delay();PlaySoundTick(10);short_delay();PlaySoundTick(hour-20);short_delay();PlaySoundTick(12);short_delay();PlaySoundTick(14);short_delay();}}else{if(hour<=10){PlaySoundTick(hour);short_delay();PlaySoundTick(12);short_delay();}else if(hour>10&&hour<20){PlaySoundTick(10);short_delay();PlaySoundTick(hour-10);short_delay();PlaySoundTick(12);short_delay();}else if(hour==20){PlaySoundTick(2);short_delay();PlaySoundTick(10);short_delay();PlaySoundTick(12);short_delay();}elsePlaySoundTick(2);short_delay();PlaySoundTick(10);short_delay();PlaySoundTick(hour-20);short_delay();PlaySoundTick(12);short_delay();}if(min<=10){PlaySoundTick(min);short_delay();PlaySoundTick(13);short_delay();}else if(min>10&&min%10){PlaySoundTick(min/10);short_delay();PlaySoundTick(10);short_delay();PlaySoundTick(min-10*(min/10));short_delay();PlaySoundTick(13);short_delay();}else{PlaySoundTick(min/10);short_delay();PlaySoundTick(10);short_delay();PlaySoundTick(13);short_delay();}}report_flag=0;time_show[7]=sec%10+48;time_show[6]=sec/10+48;time_show[4]=min%10+48;time_show[3]=min/10+48;time_show[1]=hour%10+48;time_show[0]=hour/10+48;date_show[9]=day%10+48;date_show[8]=day/10+48;date_show[6]=month%10+48;date_show[5]=month/10+48;date_show[3]=year_l%10+48;date_show[2]=year_l/10+48;date_show[1]=year_f%10+48;date_show[0]=year_f/10+48;return 0;}Isd1700.h#ifndef _ISD1760_H#define _ISD1760_H#include "main.h"#define ISD1700_PU 0x01 #define ISD1700_STOP 0X02 #define ISD1700_REST 0x03 #define ISD1700_CLR_INT 0x04 #define ISD1700_RD_STAUS 0x05 #define ISD1700_RD_PLAY_PTR 0x06 #define ISD1700_PD 0x07 #define ISD1700_RD_REC_PTR 0x08 #define ISD1700_DEVID 0x09#define ISD1700_PLAY 0x40 #define ISD1700_REC 0x41 #define ISD1700_ERASE 0x42 #define ISD1700_G_ERASE 0x43 #define ISD1700_RD_APC 0x44 #define ISD1700_WR_APC1 0x45 #define ISD1700_WR_APC2 0x65#define ISD1700_WR_NVCFG 0x46 #define ISD1700_LD_NVCFG 0x47 #define ISD1700_FWD 0x48 #define ISD1700_CHK_MEM 0x49 #define ISD1700_EXTCLK 0x4A #define ISD1700_SET_PLAY 0x80 #define ISD1700_SET_REC 0x81#define ISD1700_SET_ERASE 0x82#define NULL 0x00#define ISD_LED 0x10extern unsigned char data ISD_COMM_RAM_C[7];extern void init(void);extern void delay_isd(int x);extern void comm_sate(void);extern void rest_isd_comm_ptr(void);extern unsigned char T_R_comm_byte(unsigned char comm_data );extern void isd1700_par2_comm(unsigned char comm_par, unsigned int data_par); extern void isd1700_Npar_comm(unsigned char comm_par,comm_byte_count);extern void isd1700_7byte_comm(unsigned char comm_par, unsigned int star_addr, unsigned int end_addr);extern void spi_pu (void);extern void spi_stop (void);extern void spi_Rest ( void );extern void spi_CLR_INT(void);extern void spi_RD_STAUS(void);extern void spi_RD_play_ptr(void);extern void spi_pd(void);extern void spi_RD_rec_ptr(void);extern void spi_devid(void);extern void spi_play(void);extern void spi_rec (void);extern void spi_erase (void);extern void spi_G_ERASE (void);extern void spi_rd_apc(void);extern void spi_wr_apc1 (void);extern void spi_wr_apc2 (void);extern void spi_wr_nvcfg (void);extern void spi_ld_nvcfg (void);extern void spi_fwd (void);extern void spi_chk_mem(void);extern void spi_CurrRowAddr(void);extern void seril_back_sate(unsigned char byte_number);extern void spi_set_opt(unsigned char spi_set_comm);void init(void);#endifIsd1700.c//#pragma src#include "isd1700.h"#include "sound.h"#define uchar unsigned char#define uint unsigned intsbit DAC_sync=P2^0;sbit DAC_sclk=P2^1;sbit DAC_din =P2^2;bit re_fig;uchar data comm_temp;uchar data ISD_COMM_RAM[7];uchar data ISD_COMM_RAM_C[7];uchar data *isd_comm_ptr;uchar data *back_data_ptr;void init(void);void isd_delay(int x);void comm_sate(void);void rest_isd_comm_ptr(void);uchar T_R_comm_byte( uchar comm_data );void isd1700_par2_comm(uchar comm_par, uint data_par);void isd1700_Npar_comm(uchar comm_par,comm_byte_count); //no parameter comm void isd1700_7byte_comm(uchar comm_par, uint star_addr, uint end_addr);void spi_pu (void);void spi_stop (void);void spi_Rest ( void );void spi_CLR_INT(void);void spi_RD_STAUS(void);void spi_RD_play_ptr(void);void spi_pd(void);void spi_RD_rec_ptr(void);void spi_devid(void);void spi_play(void);void spi_rec (void);void spi_erase (void);void spi_G_ERASE (void);void spi_rd_apc(void);void spi_wr_apc1 (void);void spi_wr_apc2 (void);void spi_wr_nvcfg (void);void spi_ld_nvcfg (void);void spi_fwd (void);void spi_chk_mem(void);void spi_CurrRowAddr(void);void seril_back_sate(uchar byte_number); void spi_set_opt(uchar spi_set_comm);void comm_sate(void){uchar sate_temp;uint apc_temp;if(RI){ sate_temp=SBUF;if(sate_temp==0x09){ spi_devid();}if(sate_temp==0x44){spi_rd_apc();}if(sate_temp==0x40){spi_play();}if(sate_temp==0x04){spi_CLR_INT();}if(sate_temp==0x05){spi_RD_STAUS();}if(sate_temp==0x43){ spi_G_ERASE();}if(sate_temp==0x01){ spi_pu ();}if(sate_temp==0x02){ spi_stop();}if(sate_temp==0x03){ spi_Rest ();}if(sate_temp==0x06){spi_RD_play_ptr();}if(sate_temp==0x07){spi_pd();}if(sate_temp==0x08){ spi_RD_rec_ptr();}if(sate_temp==0x41){ spi_rec();}if(sate_temp==0x42){ spi_erase();}if(sate_temp==0x45){spi_wr_apc1 ();}if(sate_temp==0x65){ spi_wr_apc2 ();}if(sate_temp==0x46){ spi_wr_nvcfg ();}if(sate_temp==0x47){ spi_ld_nvcfg ();}if(sate_temp==0x48){ spi_fwd ();}if(sate_temp==0x49){ spi_chk_mem();}if(sate_temp==0x60){ spi_CurrRowAddr();} if(sate_temp==0x80){spi_set_opt(ISD1700_SET_PLAY|ISD_LED);//spi_set_opt(ISD1700_SET_PLAY);}if(sate_temp==0x81){spi_set_opt(ISD1700_SET_REC|ISD_LED);//spi_set_opt(ISD1700_SET_REC);ISD_COMM_RAM_C[0]=ISD1700_SET_REC ;seril_back_sate(1);}if(sate_temp==0x82){spi_set_opt(ISD1700_SET_ERASE|ISD_LED);//spi_set_opt(ISD1700_SET_ERASE);}if(sate_temp==ISD1700_WR_APC2){RI=0;while(!RI);apc_temp=SBUF;apc_temp=apc_temp<<8;RI=0;while(!RI);apc_temp|=SBUF;RI=0;ISD_SS=0;isd1700_par2_comm(ISD1700_WR_APC2,apc_temp); ISD_SS=1;}RI=0;}if(re_fig){rest_isd_comm_ptr();sate_temp=0;do{SBUF=*back_data_ptr++;while(!TI);TI=0;}while(++sate_temp<=2);re_fig=0;}}void spi_set_opt(uchar spi_set_comm){uint start_addr,end_addr;RI=0;while(!RI);start_addr=SBUF;start_addr=start_addr<<8;RI=0;while(!RI);start_addr|=SBUF;RI=0;while(!RI);end_addr=SBUF;end_addr=start_addr<<8;RI=0;while(!RI);end_addr|=SBUF;RI=0;ISD_SS=0;isd1700_7byte_comm(spi_set_comm, start_addr, end_addr); ISD_SS=1;}void spi_pu (void){ISD_SS=0;isd1700_Npar_comm(ISD1700_PU,2);ISD_SS=1;}void spi_stop (void){ISD_SS=0;isd1700_Npar_comm(ISD1700_STOP,2);ISD_SS=1;ISD_COMM_RAM_C[0]=ISD1700_STOP ;seril_back_sate(1);}void spi_Rest (void){ISD_SS=0;isd1700_Npar_comm(ISD1700_REST,2);ISD_SS=1;}void spi_CLR_INT(void){ISD_SS=0;isd1700_Npar_comm(ISD1700_CLR_INT,2);ISD_SS=1;}void spi_RD_STAUS(void){ uchar i;ISD_SS=0;isd1700_Npar_comm(ISD1700_RD_STAUS,3);ISD_SS=1;i=ISD_COMM_RAM_C[1];//j=ISD_COMM_RAM_C[2];ISD_COMM_RAM_C[1]=ISD_COMM_RAM_C[0];ISD_COMM_RAM_C[0]=i;seril_back_sate(3);}void spi_CurrRowAddr(void){ uchar i;ISD_SS=0;isd1700_Npar_comm(ISD1700_RD_STAUS,3);ISD_SS=1;i=ISD_COMM_RAM_C[1];ISD_COMM_RAM_C[1]=ISD_COMM_RAM_C[0]>>5|ISD_COMM_RAM_C[1]<<3; ISD_COMM_RAM_C[0]= i >>5;seril_back_sate(3);}void spi_RD_play_ptr(void){ uchar i;ISD_SS=0;isd1700_Npar_comm(ISD1700_RD_PLAY_PTR,4);ISD_SS=1;i=ISD_COMM_RAM_C[3]&0x03;ISD_COMM_RAM_C[3]=ISD_COMM_RAM_C[2];ISD_COMM_RAM_C[2]=i;seril_back_sate(4);}void spi_pd(void){ISD_SS=0;isd1700_Npar_comm(ISD1700_PD,2);ISD_SS=1;}void spi_RD_rec_ptr(void){ uchar i;ISD_SS=0;isd1700_Npar_comm(ISD1700_RD_REC_PTR,4);ISD_SS=1;i=ISD_COMM_RAM_C[3]&0x03;ISD_COMM_RAM_C[3]=ISD_COMM_RAM_C[2];ISD_COMM_RAM_C[2]=i;seril_back_sate(4);}void spi_devid(void){ISD_SS=0;isd1700_Npar_comm(ISD1700_DEVID,3);ISD_SS=1;ISD_COMM_RAM_C[2]=ISD_COMM_RAM_C[2]&0xf8;seril_back_sate(3);}void spi_play(void){ISD_SS=0;isd1700_Npar_comm(ISD1700_PLAY|ISD_LED,2);ISD_SS=1;}void spi_rec (void){ISD_SS=0;isd1700_Npar_comm(ISD1700_REC|ISD_LED,2);ISD_SS=1;ISD_COMM_RAM_C[0]=ISD1700_REC ;seril_back_sate(1);}void spi_erase (void){ISD_SS=0;isd1700_Npar_comm(ISD1700_ERASE|ISD_LED,2);ISD_SS=1;}void spi_G_ERASE (void){ISD_SS=0;isd1700_Npar_comm(ISD1700_G_ERASE|ISD_LED,2);ISD_SS=1;}void spi_rd_apc(void){ISD_SS=0;isd1700_Npar_comm(ISD1700_RD_APC,4);ISD_SS=1;seril_back_sate(4);}void spi_wr_apc1 (void){}void spi_wr_apc2 (void){ISD_SS=0;isd1700_par2_comm(ISD1700_WR_APC2, 0x0400);ISD_SS=1;}void spi_wr_nvcfg (void){ISD_SS=0;isd1700_Npar_comm(ISD1700_WR_NVCFG,2);ISD_SS=1;}void spi_ld_nvcfg (void){ISD_SS=0;isd1700_Npar_comm(ISD1700_LD_NVCFG ,2);ISD_SS=1;}void spi_fwd (void){ISD_SS=0;isd1700_Npar_comm(ISD1700_FWD,2);ISD_SS=1;}void spi_chk_mem(void){ISD_SS=0;isd1700_Npar_comm(ISD1700_CHK_MEM,2);ISD_SS=1;}void seril_back_sate(uchar byte_number){uchar sate_temp;rest_isd_comm_ptr();sate_temp=0;do{SBUF=*back_data_ptr++;while(!TI);TI=0;}while(++sate_temp<byte_number);}void rest_isd_comm_ptr(void){isd_comm_ptr=ISD_COMM_RAM;back_data_ptr=ISD_COMM_RAM_C;}void isd1700_Npar_comm (uchar comm_par,comm_byte_count) {uchar i;i=0;ISD_COMM_RAM[0]=comm_par;isd_comm_ptr=&ISD_COMM_RAM[1];do{*isd_comm_ptr++=NULL;}while(++i<comm_byte_count-1);rest_isd_comm_ptr();i=0;do{*back_data_ptr++=T_R_comm_byte(*isd_comm_ptr++);i++;}while(i<comm_byte_count);}void isd1700_par2_comm(uchar comm_par, uint data_par){uchar i;ISD_COMM_RAM[0]=comm_par;ISD_COMM_RAM[1]=data_par;ISD_COMM_RAM[2]=data_par>>8;rest_isd_comm_ptr();i=0;do{*back_data_ptr++=T_R_comm_byte(*isd_comm_ptr++);i++;}while(i<3);}void isd1700_7byte_comm(uchar comm_par, uint star_addr, uint end_addr) {uchar i;ISD_COMM_RAM[0]=comm_par;ISD_COMM_RAM[1]=NULL;ISD_COMM_RAM[2]=star_addr;ISD_COMM_RAM[3]=star_addr>>8;ISD_COMM_RAM[4]=end_addr;ISD_COMM_RAM[5]=end_addr>>8;ISD_COMM_RAM[6]=NULL;rest_isd_comm_ptr();i=0;do{*back_data_ptr++=T_R_comm_byte(*isd_comm_ptr++);i++;}while(i<=7);}uchar T_R_comm_byte( uchar comm_data ){uchar bit_nuber;uchar temp;bit_nuber=0;temp=0;do{ISD_SCLK=0;isd_delay(1);if((comm_data>>bit_nuber&0x01)!=0){ISD_MOSI=1;}else{ISD_MOSI=0;}if(ISD_MISO){temp=(temp>>1)|0x80;}else{temp=temp>>1;}ISD_SCLK=1;isd_delay(1);}while(++bit_nuber<=7);ISD_MOSI=0;return (temp);}void isd_delay(int x){uchar i;for(; x>=1; x--){for(;i<=20;i++);}}void init(void){TMOD=0x21;SCON=0x50;TL0=0x00; //25msTH0=0x70; //25msTH1=0xE8;TL1=0xE8; //波特率:1200bps(12MHz:0xE6 11.0592MHz:0xE8)ET0=1;EA=1;TR1=1;IT0 = 0;EX0 = 0;spi_pu();spi_devid();}12864.h#ifndef _12864_H#define _12864_H#include "main.h"sbit RS =P3^2;sbit RW=P3^3;sbit EN=P3^4;void buzy();void TransferData(char data1,bit DI);void Dingwei(unsigned char line,unsigned char row); void delayms(unsigned int n);void delay(unsigned int m);void lcd_mesg(unsigned char code *adder1);void displayonechar(unsigned int data2);void initinal(void) ; //LCD字库初始化程序void clrram(void);void lcd_pos(unsigned char ,unsigned char );void write_dat(unsigned char);extern unsigned char time_show[];extern unsigned int aaa;#endif12864.c#include "12864.h"#define DataPort P1void initinal(void) //LCD字库初始化程序{TransferData(0x30,0); //8BIT设置,RE=0: basic instruction setTransferData(0x08,0); //Display on ControlTransferData(0x10,0); //Cursor Display Control光标设置TransferData(0x0C,0); //Display Control,D=1,显示开TransferData(0x01,0); //Display Clear}void buzy(){DataPort=0xff;RW=1;RS=0;EN=1;while(DataPort&0x80);EN=0;}void Dingwei(unsigned char line,unsigned char row) //定位在哪行哪列显示{unsigned int i;switch(line){case 1: i=0x80+row;break;case 2: i=0x90+row;break;case 3: i=0x88+row;break;case 4: i=0x98+row;break;default: i=0x80;break;}TransferData(i,0);delay(1);}void lcd_mesg(unsigned char code *addr) //传送一个字符串{while(*addr>0){TransferData(*addr,1);addr++;}}void TransferData(char data1,bit DI) //传送数据或者命令,当DI=0,传送命令,当DI=1,传送数据.{buzy();RW=0;RS=DI;DataPort=data1;EN=1;EN=0;}void delayms(unsigned int n) //延时10×n毫秒程序{unsigned int i,j;for(i=0;i<3*n;i++)for(j=0;j<2000;j++);}void delay(unsigned int m) //延时程序,微妙级{while(m--){_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}}void write_cmd(unsigned char cmd){RS=0;RW=0;EN=0;P1=cmd;delayms(1);EN=1;delayms(1);EN=0;}void write_dat(unsigned char dat){RS=1;RW=0;EN=0;P1=dat;delayms(1);EN=1;delayms(1);EN=0;}void lcd_pos(unsigned char x,unsigned char y){unsigned char pos;if(x==0)x=0x80;else if(x==1)x=0x90;else if(x==2)x=0x88;else if(x==3)x=0x98;pos=x+y;write_cmd(pos);}void clrram(void){write_cmd(0x30);write_cmd(0x01);}Sound.h#ifndef _SOUND_H#define _SOUND_H#include "main.h"//以下为语音信息对应播放起始地址定义,A为开始,B为结束#define sound_0A 0x0012#define sound_0B 0x0017#define sound_1A 0x0019#define sound_1B 0x0025#define sound_2A 0x0027#define sound_2B 0x002e#define sound_3A 0x002f#define sound_3B 0x0039#define sound_4A 0x003b#define sound_4B 0x0048#define sound_5A 0x004a#define sound_5B 0x004f#define sound_6A 0x0052#define sound_6B 0x0159#define sound_7A 0x005c#define sound_7B 0x0062#define sound_8A 0x0065#define sound_8B 0x0131#define sound_9A 0x006f#define sound_9B 0x015F#define sound_10A 0x0079#define sound_10B 0x015E#define sound_11A 0x0082#define sound_11B 0x018A#define sound_12A 0x0091#define sound_12B 0x0100#define sound_13A 0x009f#define sound_13B 0x0100#define sound_14A 0x00ac#define sound_14B 0x0100void GetSound(unsigned char soundtick); void PlaySoundTick(unsigned char number);void delay_isd(unsigned int time);void short_delay();void long_delay();#endifSound.c#include "sound.h"void GetSound(unsigned char soundtick){ISD_SS=0;switch(soundtick){case 0:{ isd1700_7byte_comm(ISD1700_SET_PLAY|ISD_LED, sound_0A, sound_0B); }break;case 1:{ isd1700_7byte_comm(ISD1700_SET_PLAY|ISD_LED, sound_1A, sound_1B); }break;case 2:{ isd1700_7byte_comm(ISD1700_SET_PLAY|ISD_LED, sound_2A, sound_2B); }break;case 3:{ isd1700_7byte_comm(ISD1700_SET_PLAY|ISD_LED, sound_3A, sound_3B); }break;case 4:{ isd1700_7byte_comm(ISD1700_SET_PLAY|ISD_LED, sound_4A, sound_4B); }break;case 5:{ isd1700_7byte_comm(ISD1700_SET_PLAY|ISD_LED, sound_5A, sound_5B); }break;case 6:{ isd1700_7byte_comm(ISD1700_SET_PLAY|ISD_LED, sound_6A, sound_6B); }break;case 7:{ isd1700_7byte_comm(ISD1700_SET_PLAY|ISD_LED, sound_7A, sound_7B); }break;case 8:{ isd1700_7byte_comm(ISD1700_SET_PLAY|ISD_LED, sound_8A, sound_8B); }break;case 9:{ isd1700_7byte_comm(ISD1700_SET_PLAY|ISD_LED, sound_9A, sound_9B); }break;case 10:{ isd1700_7byte_comm(ISD1700_SET_PLAY|ISD_LED, sound_10A, sound_10B); }break;case 11:{ isd1700_7byte_comm(ISD1700_SET_PLAY|ISD_LED, sound_11A, sound_11B); }break;case 12:{ isd1700_7byte_comm(ISD1700_SET_PLAY|ISD_LED, sound_12A, sound_12B); }break;case 13:{ isd1700_7byte_comm(ISD1700_SET_PLAY|ISD_LED, sound_13A, sound_13B); }break;case 14:{ isd1700_7byte_comm(ISD1700_SET_PLAY|ISD_LED, sound_14A, sound_14B); }break;default: break;}ISD_SS=1;}void PlaySoundTick(unsigned char number) {spi_stop ();delay_isd(30000);GetSound(number);}void delay_isd(unsigned int time){while(time--!=0);}void short_delay(){delay_isd(30000);delay_isd(30000);delay_isd(30000);delay_isd(30000);delay_isd(30000);delay_isd(30000);delay_isd(30000);delay_isd(30000);delay_isd(30000);}void long_delay(){short_delay();short_delay();short_delay();short_delay();}Key.h#ifndef _KEY_H#define _KEY_H#include "main.h"sbit KEY1=P2^0;sbit KEY2=P2^1;sbit KEY3=P2^2;sbit KEY4=P2^3;sbit KEY5=P2^4;sbit KEY6=P2^5;sbit KEY7=P2^6;sbit KEY8=P2^7;sbit KEY_SURE=P3^6;void key_delay(unsigned char z); unsigned char keyscan_nor();#endifKey.c#include "key.h"unsigned char keyscan_nor(){if(!KEY1){key_delay(20);if(!KEY1){LED1=0;return 1;}}if(!KEY2){key_delay(20);if(!KEY2){LED2=0;return 2;}}if(!KEY3){key_delay(20);if(!KEY3){LED3=0;return 3;}}if(!KEY4){key_delay(20);if(!KEY4){LED4=0;return 4;}}if(!KEY5){key_delay(20);if(!KEY5){LED5=0;return 5;}}if(!KEY6){key_delay(20);if(!KEY6){LED6=0;return 6;}}if(!KEY7){key_delay(20);if(!KEY7){LED7=0;return 7;}}if(!KEY8){key_delay(20);if(!KEY8){LED8=0;return 8;}}return 0;}void key_delay(unsigned char z){unsigned char x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}五.参与制作人员ZYL(注:可编辑下载,若有不当之处,请指正,谢谢!)。
基于51单片机的12864液晶显示的万年历
附录程序
/*****************说明*********************************** 基于 51 单片机的 12864 液晶显示的万年历
版权所有,如需转载请通知本人,不得用于商业用途 ,仅限学习交流之用
*****************************************************************/
3
图-1 主控制系统
2.3.2 时钟电路模块的设计 DS1302 是一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、
时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。采用三线接口与CPU进 行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一 个31×8的用于临时性存放数据的RAM寄存器。DS1302是DS1202的升级产品,与DS1202兼容, 但增加了主电源/后背电源双电源引脚,同时提供了对后背电源进行涓细电流充电的能力。
//延时 1MS/次
unsigned char
{
sec,min,hour,day,month,year,cen,week,
unsigned char i;
next,aa,bb,cc,dd,mm,temp0,LunarMonth,
while(--a)
LunarDay,LunarYear;
{
int temp;
9三三系统的软件设计系统的软件设计3131程序流程框图程序流程框图图图aa主程序流程图主程序流程图10图b计算阳历程序流程图计算阳历程序流程图1112图图cc时间调整程序流程图时间调整程序流程图yynnyynnyy图图dd设置温度报警闹钟的数据保存到设置温度报警闹钟的数据保存到at24c02at24c02中中是否进入温度报警上下限温度设置设置是否进入设置闹钟时间设置报警温度上下限开始设置闹钟的时间开始报警闹钟的开关是否开起at24c02存设置的功能保蜂鸣器开启闹钟报警功能开启结束设置13五五作品功能实现作品功能实现通过硬件的焊接与程序的编写本电子万年历终于完成了实现的功能如下
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; }}}}}}}}}。
51系列单片机制作万年历
目录摘要 (I)Abstract .................................................... I I 第一章前言.. (1)1.1 研究目的和意义 (1)1.2 国内外研究现状 (1)1.3 研究内容和方法 (1)第二章设计方案论证 (3)2.1 系统基本方案选择和论证 (3)2.2 控制部分的方案选择 (3)2.2 显示部分的方案选择 (4)第三章系统硬件设计 (6)3.1 系统硬件框图 (6)3.2 控制部分电路设计 (6)3.3 显示部分电路设计 (13)3.4 时钟电路模块的设计 (14)第四章系统软件设计 (18)4.1 主程序 (18)4.2 阳历部分 (18)4.3 阴历部分 (20)4.4 阳历日和阴历日的对应调整 (22)4.5 键盘防抖程序 (24)第五章结论与建议 (25)致谢 (26)参考文献 (27)附录一整体电路图 (28)附录二程序 (29)摘要万年历的设计过程在硬件与软件方面进行同步设计。
硬件部分主要由AT89S51单片机,LED 显示电路,以及调时按键电路等组成。
在单片机的选择上本人使用了AT89S51单片机,该单片机适合于许多较为复杂控制应用场合。
显示器使用2片7SEG-MPX8-CA和一片7SEG-MPX4-CA。
7SEG-MPX8-CA是一种八个共阳二极管显示器,7SEG-MPX4-CA是一种四个共阳二极管显示器。
为了能更轻松的控制这三片显示器,本人使用了3片74HC164来驱动。
74HC164是8位边沿触发式移位寄存器,串行输入数据,然后并行输出。
软件方面主要包括日历程序、时间调整程序,公历转阴历程序,显示程序等。
程序采用汇编语言编写,以便更简单地实现调整时间及阴历显示功能。
关键词:时钟电钟,动态扫描,单片机AbstractCalendar of the design process in hardware and software to synchronize the design. Hardware mainly by the AT89S51 micro-controller, LED display circuit, and the tune composed of the circuit when the button. In the SCM choice I used the AT89S51 micro-controller, which is suitable for many of the more complex control applications. Monitor the use of two 7SEG-MPX8-CA and a 7SEG-MPX4-CA. 7SEG-MPX8-CA is a total of eight-yang diode display, 7SEG-MPX4-CA is a total of four-yang diode display. In order to more easily control the three monitors, I use three 74HC164 to drive.74HC164 is an 8-bit edge-triggered shift register, serial input data, and parallel output. The software includes calendar program, time to adjust procedures, turn the lunar calendar programs, display programs. Programs written in assembly language used in order to more easily adjust the time and the realization of the lunar calendar display.Keywords:Clock electric clock, Dynamic scan, SCM第一章前言1.1 研究目的和意义电子万年历是实现对年,月,日,时,分,秒数字显示的计时装置,广泛用于个人家庭,车站,码头,办公室,银行大厅等场所,成为人们日常生活中的必需品。
单片机课程设计--基于51单片机的万年历
单片机课程设计--基于51单片机的万年历单片机课程设计基于 51 单片机的万年历一、引言在现代生活中,时间的准确记录和显示对于我们的日常生活和工作具有重要意义。
万年历作为一种能够同时显示年、月、日、星期、时、分、秒等信息的设备,给人们带来了极大的便利。
本次课程设计旨在利用 51 单片机实现一个简单实用的万年历系统。
二、系统设计方案(一)硬件设计1、单片机选型选择经典的 51 单片机,如 STC89C52 单片机,其具有性能稳定、价格低廉、资源丰富等优点,能够满足本设计的需求。
2、显示模块采用液晶显示屏(LCD1602)作为显示设备,能够清晰地显示数字和字符信息。
3、时钟芯片选用DS1302 时钟芯片,它可以提供精确的实时时钟数据,包括年、月、日、星期、时、分、秒等。
4、按键模块设置三个按键,分别用于调整时间、选择调整项(年、月、日、时、分、秒等)以及切换显示模式(正常显示和设置模式)。
(二)软件设计1、主程序流程系统初始化后,首先读取 DS1302 中的时间数据,并将其显示在LCD1602 上。
然后进入循环,不断检测按键状态,根据按键操作进行相应的时间调整和显示模式切换。
2、时间读取与显示程序通过与 DS1302 进行通信,读取实时时间数据,并将其转换为适合LCD1602 显示的格式进行显示。
3、按键处理程序检测按键的按下状态,根据不同的按键执行相应的操作,如调整时间、切换显示模式等。
三、硬件电路设计(一)单片机最小系统单片机最小系统包括单片机芯片、晶振电路和复位电路。
晶振电路为单片机提供时钟信号,复位电路用于系统初始化时将单片机的状态恢复到初始值。
(二)显示电路LCD1602 显示屏通过数据总线和控制总线与单片机相连。
数据总线用于传输要显示的数据,控制总线用于控制显示屏的读写操作和显示模式。
(三)时钟电路DS1302 时钟芯片通过串行通信接口与单片机进行通信。
单片机通过发送特定的指令和数据,对 DS1302 进行读写操作,获取或设置时间信息。
51单片机汇编语言万年历完美版.
;**************万年历制作 BY----信工七班 ;**************************** ;***************************** ;----------------------------------------------------------------------------------------- RCK BIT P0.5 SCK BIT P0.4 DAT BIT P0.7 RST BIT P0.6 BUZZER BIT P1.3 ;蜂鸣器 BYTE EQU 40H ;用于给锁存器送入数据 GEWEI EQU 41H ;用于存放数码管显示的第一位 SHIWEI EQU 42H ;用于存放数码管显示的第二位 BAIWEI EQU 43H ;用于存放数码管显示的第三位 QIANWEI EQU 44H ;用于存放数码管显示的第四位 TEMP1 EQU 45H TEMP2 EQU 46H COUNT EQU 47H ;用于扩展定时器计数时间 KTIME EQU 49H TEMP EQU 50H DMS EQU 51H ;用于存放运动秒表的最低位 DSECOND EQU 52H ;用于存放运动秒表的秒 DMIN EQU 53H ;用于存放运动秒表的分钟 CLKMIN EQU 54H ;用于存放闹钟分钟 CLKHOUR EQU 55H ;用于存放闹钟时 CLKF EQU 56H ;用于闹钟开启的标志位 ;----------------------------------------------------------------------------------------- ORG 0000H AJMP MAIN ORG 000BH ;定时器0中断入口地址 AJMP T0_INT ORG 001BH ;定时器1中断入口地址 AJMPT1_INT ;********************************主程序************************************************* ;----------------------------------------------------------------------------------------- MAIN: MOV R4,#00 ;计数秒 MOVR5,#50 ;计数分 MOV R6,#15 ;计数时 MOV R0,#14H ;2013年 MOV R1,#0DH MOV R2,#6 ;6月 MOV R3,#18 ;18日 MOV COUNT,#0H MOV A,#5 ;开始使A不等于0,用于后面的判断 MOV CLKMIN,#0H MOV CLKHOUR,#0H MOV CLKF,#0H MOV SP,#60H MOV TMOD,#11H ;设置定时器0为工作模式1 MOV TH0, #03CH MOV TL0, #0B0H ;定时50000 us MOV TH1, #0D8H MOV TL1, #0F0H ;定时1000us=1MS SETB ET0 ;允许定时器中断 SETB ET1 SETB EA ;允许全局中断 SETB PT0 ;定时器中断设为高优先级 SETB EX0 ;允许外部中断 SETB EX1 SETB IT0 ;外部中断设为下降沿触发 SETB IT1 SETB TR0 ;启动定时器 ;--------------------------------------- START: MOV DPTR,#TABLE LJMP KEYSCAN ;首先进入时间显示,由于地址相差太远所以代码顺序有所改变 ;-------------------------------------- MARK2: LJMP KEYSCAN ;地址差跳远无法跳转,此处进行中间跳转到时间显示界面 KEYCLK: MOV A,CLKF ;此处为闹钟设置刚进入时的程序,由按键s12进入 JNZ KEYCLKF ;进入后通过CLKF来判断闹钟功能是否启动,未启动时正常 ;显示为SHOWCLKF,启动时显示SHOWCLKF1,此两种显示差一个数码管最低位标志的点 KEYCLK1: LCALL SHOWCLK ;此处判定未启动闹钟功能时的显示 LCALL S4 ;在闹钟界面查看有无切换显示模式(此处也可认为是确定 ;按键)的按键s4按下, JZ MARK2 ;按下后跳转到时间显示 LCALL S8 ;在闹钟显示界面下查看启动闹钟功能的键s8是否按下MOV A,CLKF JNZ KEYCLKF ;按下后显示SHOWCLKF1的显示 LCALL S16 ;未按下则显示没有闹钟标志的数码管显示,再查看有无进 ;入调节s16的键按下,CJNE A,#7EH,KEYCLK1 ;未按下继续闹钟界面显示 KEYCLK2: LCALL SCLKMIN ;按下进入调节 MOV A,CLKMIN ;显示设置分钟的调节 MOV TEMP,A LCALL KEYSUB1 ;通过加减键s8,s12来设置闹钟 LCALL KEYADD1 MOV A,TEMP SUBB A,#60 ;调节分钟不超过59 JC REMAIN0 MOV TEMP,#0 REMAIN0: MOV A,TEMP MOV CLKMIN,A LCALL S16 ;查看有无进入调节s16的键按下, CJNE A,#7EH,KEYCLK2 ;未按下继续显示分钟调节 KEYCLK3: LCALL SCLKHOUR ;按下进入显示时调节 MOV A,CLKHOUR MOV TEMP,A ;送入参数,通过加减键进行调节设置 LCALL KEYSUB2 LCALL KEYADD2 MOV A,TEMP SUBB A,#24 ;时的设置不超过24 JC REMAIN1 MOV TEMP,#0 ;超过24置0 REMAIN1: MOVA,TEMP MOV CLKHOUR,A LCALL S16 CJNE A,#7EH,KEYCLK3 ;再次判断有无调节的切换键(按3次为确定)按下 KEYCLK4: LCALL SHOWCLK ;按下后跳转为闹钟的界面正常显示 LCALL S4 ;再判断有无切换显示模式的键按下,按下跳转显示 JZ KEYSCAN LCALL S8 ;再判断有无启动(关闭)闹钟功能的键按下 MOV A,CLKF ;根据CLKF(闹钟功能启动)的标志位显示不同的闹钟界面 JNZ KEYCLKF ;闹钟功能启动,跳转到KEYCLKF显示闹钟启动标记 GOON: LCALL S16 ;未启动则又判断有无进入调节的键按下 CJNE A,#7EH,KEYCLK4 ;没有按下继续正常显示 AJMP KEYCLK2 ;按下后重复KEYCLK2开始的内容 KEYCLKF: LCALL SHOWCLK1 ;显示出闹钟功能启动后的标记(数码管最低位标记) LCALLS4 ;查看有无切换显示模式(闹钟设置确定后)键按下 JZ KEYSCAN ;按下后跳转到显示时间的界面 LCALL S8 ;未按则扫描开启(关闭)闹钟功能的键按下 MOV A,CLKF JZ KEYCLK4 ;根据闹钟功能的标记位跳转显示,若判断闹钟功能关闭则 ;跳转到KEYCLK4 显示无标志的闹钟 LCALL S16 ;若判断闹钟功能开启则扫描有无进入调节的按键s16按下CJNE A,#7EH,KEYCLKF ;未按下则继续显示有标记的闹钟界面 AJMP KEYCLK2 ;按下后则又进入调节界面KEYCLK2 ;-------------------------------------------------- MARK3: LJMP MARK1 ;地址差跳远无法跳转,此处进行中间跳转到闹钟界面 ;---------------------------------------------------- KEYSCAN: LCALL HOURMINUTE ;显示时间 PUSH ACC ;为s12的判断先把A入堆栈,否则s12出会出现判断错误LCALL S4 ;查看有无切换键s4按下,按下跳转显示秒 JZ KEYSCAN1 MOVA,CLKF ;在显示时间时判断闹钟功能是否开启,未开则跳转显示 JZ GO MOVA,R6 ;判断是否与闹钟设置的时间相等,R6---时 CJNE A,CLKHOUR,GO MOV A,R5 ;R5--分 CJNE A,CLKMIN,GO LCALL SOUND ;闹钟功能开启,时分相等,则闹铃响 ;-------------------------------------------------- GO: POP ACC ; 如果不pop,A=0一直成立,此时出现错误跳转 LCALL S12 ;查看有无进入闹钟设置的键按下 JZ MARK3 ; 按下则跳入显示闹钟设置界面 LCALL S16 ;查看有无进入调节键s16按下,按下进入调节 CJNE A,#7EH,KEYSCAN ;未按下则继续显示时间 SMINUTE: LCALL MINUTE ;s16按下后进入分调节显示 MOV TEMP,R5 ;将要调节的分钟送入函数参数 LCALL KEYADD1 ;进入调节后查看是否按下加法键s8,按下加一LCALL KEYSUB1 ;进入调节后查看是否按下减法键s8,按下减一 MOV A,TEMP SUBB A,#60 ;调节不超过60 JC REMAIN2 MOV TEMP,#0 REMAIN2: MOVR5,TEMP ;把运算完后的分钟送出显示 LCALL S16 CJNE A,#7EH,SMINUTE ;没有s16按下,继续显示分调节 SHOUR: LCALL HOUR ;按下后进入显示时调节 MOV TEMP,R6 ;R6为装时的寄存器,送入参数进行调节 LCALL KEYADD2 LCALL KEYSUB2 MOV A,TEMP SUBB A,#24 ;调节不超过24 JC REMAIN3 MOV TEMP,#0 REMAIN3: MOV R6,TEMP LCALL S16 ; 再次按下s16键可确定时间调节完成 CJNE A,#7EH,SHOUR AJMP KEYSCAN ;调节完后重新正常显示时间 ;--------------------------------------- ;--------------------------------------- KEYSCAN1: LCALL SHOWSECOND ;按切换键s4后进入的秒显示 LCALL S4 ;与时间显示的时候一样查看有无切换模式的键按下 JZ KEYSCAN2 ;按下则跳转显示日期 LCALL S12 ;此处为查看有无进入闹钟功能的键按下,有则跳转 JZ MARK1 LCALL S16 ;若无闹钟键按下,查看有无进入调节的键s16按下 CJNE A,#7EH,KEYSCAN1 SMS: LCALL MS ;调节键按下显示需要调节内容 MOV A,COUNT ;与之前的一样把调节参数送入进行调节,此处调姐秒显示的低位 MOV TEMP,A LCALL KEYADD1 LCALL KEYSUB1 MOV A,TEMP SUBB A,#60 ;调节不超过60 JC REMAIN4 MOV TEMP,#0 MOV A,TEMP REMAIN4: MOVA,TEMP MOV COUNT,A LCALL S16 ;查看有无切换调节内容的键s16按下CJNE A,#7EH,SMS ;没有s16键按下则显示原先调节内容 SSECOND: LCALL SECOND ;有键s16按下则显示进入秒的调节 MOV TEMP,R4 ;参数送入进行调节LCALL KEYADD2 LCALL KEYSUB2 MOV A,TEMP SUBB A,#60 ;调节不超过60 JC REMAIN9 MOV TEMP,#0 REMAIN9: MOV R4,TEMP LCALL S16 ; 再次按下s16键可确定时间调节完成 CJNE A,#7EH,SSECOND ;未按下则继续显示选中的调节内容 AJMP KEYSCAN1 ;---------------------------------------- MARK1: LJMP KEYCLK ;地址差跳远无法跳转,此处进行中间跳转到闹钟界面 ;---------------------------------------- KEYSCAN2: LCALL SHOWDAY ;此处为日期显示,当切换模式键按下两下后进入显示 LCALL S4 ;与时间显示的时候一样查看有无切换模式的键按下JZ KEYSCAN3 ;按下则跳转显示年份 LCALL S12 ;此处为查看有无进入闹钟功能的键按下,有则跳转 JZ MARK1 LCALL S16 ;若无闹钟键按下,查看有无进入调节的键s16按下 CJNE A,#7EH,KEYSCAN2 SDAY: LCALL DAY ;调节键按下显示需要调节内容,此处为日 MOV TEMP,R3 ; 把日期寄存器R2的值送入临时变量用于调节 LCALL KEYADD1 ;调用加减按键扫描,按下后进行操作 LCALL KEYSUB1 MOV A,TEMP SUBB A,#32 ;调节不超过31 JC REMAIN5 MOV TEMP,#0 REMAIN5: MOV R3,TEMP LCALL S16 ;查看有无切换调节内容的键s16按下 CJNE A,#7EH,SDAY ;没有s16键按下则显示原先调节内容 SSMOUNTH: LCALL MOUNTH ;有键s16按下则显示进入月的调节 MOV TEMP,R2 LCALL KEYADD2LCALL KEYSUB2 MOV A,TEMP SUBB A,#13 ;调节不超过12 JC REMAIN6 MOV TEMP,#0 REMAIN6: MOV R2,TEMP LCALL S16 ; 再次按下s16键可确定时间调节完成 CJNE A,#7EH,SSMOUNTH ;未按下则继续显示选中的调节内容 AJMP KEYSCAN2 ;--------------------------------------------- ;---------------------------------------------- KEYSCAN3: LCALL SHOWYEAR ;此处为日期显示,当切换模式键按下三下后进入显示 LCALL S4 JZ SHOW0 ;代码的内容除了显示的内容不同其他和以上的一样 LCALL S12 JZ MARK1 LCALL S16 CJNE A,#7EH,KEYSCAN3 SYEAR1: LCALL YEAR1 MOV TEMP,R1 LCALL KEYADD1 LCALL KEYSUB1 MOVA,TEMP SUBB A,#100 ;调节不超过99 JC REMAIN7 MOV TEMP,#0 REMAIN7: MOV R1,TEMP LCALL S16 ; CJNE A,#7EH,SYEAR1 SYEAR2: LCALL YEAR2 MOV TEMP,R0 LCALL KEYADD2 LCALL KEYSUB2 MOV A,TEMP SUBBA,#100 ;调节不超过99 JC REMAIN8 MOV TEMP,#0 REMAIN8: MOV R0,TEMP LCALL S16 CJNE A,#7EH,SYEAR2 AJMP KEYSCAN3 ;------------------------------------------ MARK: LJMP KEYSCAN ;地址差跳远无法跳转,此处进行中间跳转到时间显示界面 ;------------------------------------------ SHOW0: MOV DMS,#0 ;切换键按下四次后此时切换到运动秒表计时从0开始计时 MOV DMIN,#0 MOV DSECOND,#0 LCALL SHOWDD ; 刚进入运动秒表模式,显示全为0 LCALL S4 JZ MARK LCALL S16 CJNE A,#7EH,SHOW0 ;运动秒表开始键按下,则计时开始,否则继续显示0 SETB TR1 ;开启定时器1 SHOWD: LCALL SHOWDD ;开始键s16按下后显示变化的数字 LCALL S4 ;查看有无模式显示键的按下 JZ MARK ;按下则跳转显示LCALL S16 ;查看s16有无按下 CJNE A,#7EH,SHOWD ;再次按下该键s16,停止计时 CLR TR1 ;关闭定时器1 SHOWTING: LCALL SHOWDD ;显示为定时的内容LCALL S4 ;查看有无模式显示键的按下 JZ MARK LCALL S16 CJNEA,#7EH,SHOWTING ;再次按下s16,显示继续上次状态开始计时 SETB TR1 ;再次开启定时器 SHOWTING1: LCALL SHOWDD ;显示定时变化的定时内容 LCALL S4 JZ MARK LCALL S16 CJNE A,#7EH,SHOWTING1 ;再按一下s16再次进入暂停状态 CLR TR1 SHOWTING2: LCALL SHOWDD LCALL S4 JZ MARK LCALL S16CJNE A,#7EH,SHOWTING2 AJMP SHOW0 ;再按一下s16 内容清零,重新进入初始化运动秒表模式 ;---------------------------------------------此段主要为调节、显示的过程内容 ;************主程序结束****************************************************************** ;--------------出程序结束,一下为各个子函数 ;向74hc595发送一个字,并显示数据 ;----------------------------------------------------------------------------------------- SENDBYTE: MOV BYTE,A ;送入需要写入锁存器的参数 MOV A, #1 ;用1来移位选取各个位的数据ANL A,BYTE ;用与来选取数据 JNZ SEND CLR DAT ;与后结果为0则送入0 CLR SCK ;将写入的数据进行右移 SETB SCK AJMP LOOP ;跳转继续重复7次 SEND: SETB DAT ;与后结果不为0,则送入数据1 CLR SCK SETB SCK ;--------送入第一位数据 LOOP: MOV R7,#7 MOV A, #1 LOOP1: RL A MOV B,A ANL A,BYTE JNZ SEND1 SEND0: CLR DAT ;送0 AJMP SUOCUN SEND1: SETB DAT ;送1 AJMP SUOCUN SUOCUN: CLR SCK SETB SCK MOV A,B DJNZ R7,LOOP1 CLR RCK SETB RCK RET ;------------------------以上为数据进行输入锁存 DISPLAY: ACALL JISUAN DISPLAY1: MOV P0,#00H MOV A,GEWEI ACALL SENDBYTE ORLP0,#08H ;给出最左边数码管的位选 MOV R7,#10H LCALL DLY ;-----------显示最左边的数码管 MOV P0,#00H MOV R7,#03H LCALL DLY MOV A,SHIWEI ACALL SENDBYTE ORL P0,#04H ;给出第二位数码管的位选 MOV R7,#10H LCALL DLY ;--------------显示第二位数码管MOV P0,#00H MOV R7,#03H LCALL DLY MOV A,BAIWEI ACALL SENDBYTE ORL P0,#02H ;给出第三位数码管的位选 MOV R7,#10H LCALL DLY ;----------------显示第三位数码管 MOV P0,#00H MOV R7,#03H LCALL DLY MOV A,QIANWEI ACALL SENDBYTE ORL P0,#01H ;给出第三位数码管的位选 MOV R7,#10H LCALL DLY ;-------------------显示第四位数码管 RET ; ------------------------以上为数据显示 ;计算各位数的值把要显示的数进行分解 ;----------------------------------------- JISUAN: MOV A,TEMP1 MOV B,#10 DIV AB MOV TEMP1,B MOVC A,@A+DPTR MOV SHIWEI,A MOV A,TEMP1 MOVC A,@A+DPTR MOV GEWEI,A MOVA,TEMP2 MOV B,#10 DIV AB MOV TEMP2,B MOVC A,@A+DPTR MOVQIANWEI,A MOV A,TEMP2 MOVC A,@A+DPTR MOV BAIWEI,A RET ;-----------------以上为计算各个位数 ;----------------------------------------------------------------------------------------- ;显示高两位数(用于调节的时候显示) ;---------------------------------------------------------------------------------------- DISPLAY4: ACALL JISUAN MOV P0,#00H MOV A,BAIWEI ACALL SENDBYTE ORL P0,#02H MOV R7,#03H LCALL DLY ;----------------显示第三位数码管 MOV P0,#00H MOV R7,#03H LCALL DLY MOVA,QIANWEI ACALL SENDBYTE ORL P0,#01H MOV R7,#03H LCALL DLY ;-------------------显示第四位数码管 RET ;------------------------------------------------------------------------------------------ ;只显示低两位数(用于调节的时候显示) ;------------------------------------------------------------------------------------------ DISPLAY2: LCALL JISUAN MOV P0,#00H MOV A,GEWEI LCALL SENDBYTE ORL P0,#08H MOV R7,#03H LCALL DLY ;-----------显示最左边的数码管 MOV P0,#00H MOV R7,#03H LCALL DLY MOV A,SHIWEI LCALL SENDBYTE ORL P0,#04H MOV R7,#03H LCALL DLY ;--------------显示第二位数码管 MOV P0,#00H MOV R7,#03H LCALL DLY RET ;----------------------------------------------------------------------------------------- ;显示时间子程序 ;----------------------------------------------------------------------------------------- HOURMINUTE: MOV TEMP2,R6 MOV TEMP1,R5 LCALL JISUAN ORL BAIWEI,#01H ;--------第三个数码管显示小数点 LCALL DISPLAY1 RET ;由于只有四个数码管,此处显示时、分 SHOWSECOND: MOV TEMP2,R4 MOV A,COUNT MOV TEMP1,A LCALL JISUAN ORL BAIWEI,#01H LCALL DISPLAY1 RET ;此处单独显示秒 SHOWYEAR: MOV TEMP2,R0 MOV TEMP1,R1 LCALL DISPLAY RET SHOWDAY: MOV TEMP2,R2 MOV TEMP1,R3 LCALL DISPLAY RET SHOWCLK: MOV TEMP2,CLKHOUR MOV TEMP1,CLKMIN LCALL JISUAN ORL BAIWEI,#01H LCALL DISPLAY1 RET SHOWCLK1: MOV TEMP2,CLKHOUR MOV TEMP1,CLKMIN LCALL JISUAN ORL BAIWEI,#01H ORL GEWEI,#01H LCALL DISPLAY1 RET ;----------------------------------------------------------------------------------------- ;调节时间日期时独立显示每两位(用于调节的时候显示) ;---------------------------------------------------------------------------------------- MS: MOV TEMP1,COUNTLCALL DISPLAY2 RET SECOND: MOV TEMP2,R4 LCALL DISPLAY4 RET MINUTE: MOV TEMP1,R5 LCALL DISPLAY2 RET HOUR: MOV TEMP2,R6 LCALL DISPLAY4 RET DAY: MOV TEMP1,R3 LCALL DISPLAY2 RET MOUNTH: MOV TEMP2,R2 LCALL DISPLAY4 RET YEAR1: MOV TEMP1,R1 LCALL DISPLAY2 RET YEAR2: MOV TEMP2,R0 LCALL DISPLAY4 RET SCLKMIN: MOV TEMP1,CLKMIN LCALL DISPLAY2 RET SCLKHOUR: MOVTEMP2,CLKHOUR LCALL DISPLAY4 RET ;----------------------------------------------------------------------------------------- ;键盘扫描函数 ;---------------------------------------------------------------------------------------- ;切换调节显示内容键 S16: MOV P2,#0FFH CLRP2.7 JB P2.0,S16END MOV R7,#18H LCALL DLY JNB P2.0,$ ;当键盘松开时往下执行否则停留在这一步 MOV A,#7EH S16END: RET ;切换模式显示内容键 S4: MOV P2,#0FFH CLR P2.7 JB P2.3,S4END MOV R7,#18H LCALL DLY JNB P2.3,$ ;当键盘松开时往下执行否则停留在这一步 MOV A,#0H ;设置扫描标志位A=0 S4END: RET ;设置闹钟键扫描与减法键位同一键s12 S12: MOV P2,#0FFH CLR P2.7 JBP2.1,S12END MOV R7,#18H LCALL DLY JNB P2.1,$ ;当键盘松开时往下执行否则停留在这一步 MOV A,#0 ;设置扫描标志位A=0 S12END: RET ;用于确定启动闹钟功能的键盘扫描,与加法键位同一个 S8: MOV P2,#0FFH CLR P2.7 JB P2.2,S8END MOV R7,#18H LCALL DLY JNB P2.2,$ ;当键盘松开时往下执行否则停留在这一步MOV A,CLKF CPL A ;设置扫描标志位A=1 MOV CLKF,A S8END: RET ;单步、连续调节加法键 ;----------------------------------------------------------------------------------------- ;----------------------------------------------------------------------------------------- KEYADD2: MOV P2,#0FFH CLR P2.7 JB P2.2,ADDEND2 MOV R7,#18H LCALL DLY JT1: JNB P2.2,KT1 INC TEMP AJMP ADDEND2 KT1: INC KTIME MOV R7,#10H LCALL DLY ;用于调节高两位 MOV A,KTIME CJNEA,#30,JT1 ADD2: INC TEMP MOV A,TEMP CJNE A,#99,ON2 MOV TEMP,#0 ON2: MOV R7,TEMP MOV TEMP2,R7 LCALL DISPLAY4 MOV R7,#30H LCALL DLY JNB P2.2,ADD2 ADDEND2: RET KEYADD1: MOV P2,#0FFH CLR P2.7 JBP2.2,ADDEND1 MOV R7,#18H LCALL DLY JT2: JNB P2.2,KT2 INC TEMP AJMPADDEND1 ;用于调节低两位 KT2: INC KTIME MOV R7,#10H LCALL DLY MOV A,KTIME CJNE A,#30,JT2 ADD1: INC TEMP MOV A,TEMP CJNE A,#99,ON3 MOV TEMP,#0 ON3: MOV R7,TEMP MOV TEMP1,R7 LCALL DISPLAY2 MOV R7,#30H LCALL DLY JNB P2.2,ADD1 ADDEND1: RET ;----------------------------------------------------------------------------------------- ;单步、连续调节减法键 KEYSUB2: MOVP2,#0FFH CLR P2.7 JB P2.1,SUBEND2 MOV R7,#18H LCALL DLY JT3: JNBP2.1,KT3 DEC TEMP AJMP SUBEND2 KT3: INC KTIME MOV R7,#10H ;用于调节高两位 LCALL DLY MOV A,KTIME CJNE A,#30,JT3 SUB2: DEC TEMP MOVA,TEMP CJNE A,#0,ON MOV TEMP,#99 ON: MOV R7,TEMP MOV TEMP2,R7 LCALL DISPLAY4 MOV R7,#30H LCALL DLY JNB P2.1,SUB2 SUBEND2: RET ;----------------------------------------------------------------------------------------- KEYSUB1: MOV P2,#0FFH CLR P2.7 JB P2.1,SUBEND1 MOV R7,#18H LCALL DLY JT4: JNB P2.1,KT4 DEC TEMP AJMP SUBEND2 KT4: INC KTIME MOV R7,#10H ; LCALL DLY MOV A,KTIME CJNE A,#30,JT4 SUB1: DEC TEMP ;用于调节低两位 MOV A,TEMP CJNE A,#0,ON1 MOV TEMP,#99 ON1: MOV R7,TEMP MOV TEMP1,R7 LCALL DISPLAY2 MOV R7,#30H LCALL DLY JNB P2.1,SUB1 SUBEND1: RET ;蜂鸣器响的子程序 ;----------------------------------------------------------------------------------------- SOUND: CLR BUZZER MOV R7,#5H LCALL DLY SETB BUZZER MOVR7,#04H LCALL DLY RET ;----------------------------------------------------------------------------------------- ;延时子程序 ;----------------------------------------------------------------------------------------- DLY: PUSH 07H DY1: PUSH 07H DY2: PUSH 07H DY3: DJNZR7,DY3 POP 07H DJNZ R7,DY2 POP 07H DJNZ R7,DY1 POP 07H DJNZ R7,DLY RET ;----------------------------------------------------------------------------------------- ;定时器中断程序: ;----------------------------------------------------------------------------------------- T0_INT: MOV TH0,#3CH ;定时中断子程序。
基于51单片机的万年历毕业设计
中文摘要本设计万年历以AT89C51为控制中心,与温度传感器DS18B20,时钟芯片DS1302综合应用为一体,不仅能够准确显示时间、日期,闹钟设置,环境温度测量及温度高低温报警等功能。
单片机是一种集CPU、RAM、ROM、I/O接口和中断系统等于一体的器件,只需要外加电源和晶振就可实现对数字信息的处理和控制。
单片机与数字万年历相结合,用于时间显示,温度测试等不仅具有控制方便、组态简单和灵活性大等优点,而且可以大幅度提高被检测数值的技术指标,从而能够大大提高产品的质量和数量。
关键词:单片机,温度传感器,C语言,液晶显示ABSTRACTThis design USES AT89C51 as calendar control center, and the temperature sensor DS18B20, the clock DS1302 chip integrated application as a whole, and not only be able to accurately display the time, date, alarm, the environment temperature measurement and high temperature, low temperature alarm functions. SCM is a collection of CPU, RAM, ROM, I/O interface and interrupt system is one of the devices, only require additional power can be used for vibration and grain is the process of digital information and control. Single-chip microcomputer and digital calendar, combining for time to show, temperature testing has not only control convenient, simple and flexible configuration advantages, and which could increase the technical index of the tested value, which can greatly improve the quality of the products and quantity.Key words:Single-chip microcomputer, Temperature Sensor,C language,Liquid crystal displ目录第一章前言 (4)1.1系统开发背景及现状 (4)1.2 系统开发的目的 (4)第二章总体设计 (5)2.1 本设计实现的功能和要求 (5)2.2 设计的选择方案和论证 (5)2.2.1单片机芯片的选择方案和论证 (5)2.2.2显示模块选择方案和论证 (5)2.2.3 时钟芯片的选择方案和论证 (6)2.3.4 温度传感器的选择方案与论证 (6)2.3总体设计框图 (6)第三章硬件设计 (7)3.1 主要元器件介绍 (7)3.1.1 单片机简介 (7)3.1.2 传感器DS18B20介绍 (8)3.1.3 LCD1602液晶显示介绍 (9)3.2 各模块设计 (10)3.2.1 主控制电路 (10)3.2.2 LCD1602显示模块设计 (11)3.2.3 DS18B20温度传感器模块 (11)3.2.4 键盘输入模块设计 (12)3.2.5 蜂鸣器模块设计 (12)3.2.6 DS1302时钟电路模块 (13)第四章软件设计 (14)第五章安装与调试 (16)5.1 安装制作 (16)5.2 硬件调试 (16)5.2.1布线的原则与焊接 (16)5.2.2 硬件调试与测试 (17)5.3 软件调试 (17)5.3.1 软件测试仪器 (17)5.3.2 软件调试与测试 (17)5.4 联调 (18)5.5测试结果分析与结论 (19)第六章总结 (20)参考文献 (21)附录A (22)附录B (24)致谢 (26)第一章前言1.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_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寄存器。
完美万年历(单片机汇编语言版)
RET
INT_T1:PUSH ACC
PUSH PSW
MOV TH1,#(65536-500) / 256
MOV TL1,#(65536-500) MOD 256
INC CNTA
MOV A,CNTA
CJNE A,#100,NEXT
INC CNTB
TEMP EQU 51H
TEMP1 EQU 52H
CNTA EQU 53H
CNTB EQU 54H
YEARL EQU 59H
YEARH EQU 60H
NZBZ BIT 60H
BSBZ BIT 61H
FLAG BIT 62H
ORG 0000H
LJMP MAIN
ORG 000BH
CJNE A,#0AH,ZDRQEND
MOV YEARS,#00H
INC YEARB
MOV A,YEARB
CJNE A,#0AH,ZDRQEND
MOV YEARB,#00H
INC YEARQ
MOV A,YEARQ
CJNE A,#0AH,ZDRQEND
MOV YEARQ,#00H
MOV A,#38H ;显示模式设置(以后均检测忙信号)
LCALL LCDWC
MOV A,#08H ;显示关闭
LCALL LCDWC
MOV A,#01H ;显示清屏
LCALL ZDRQ
AJMP T0END
T01:CJNE A,#0AH,T0END
MOV HOURL,#00H;开始无此和下一条指令,19点无法变20点
INC HOURH
基于-51单片机的万年历设计
单片机课程设计题目基于51单片机的万年历设计学生专业班级学号院(系)指导教师完成时间目录1课程设计的目的12课程设计的任务与要求1 2.1设计任务12.2设计要求13单片机发展概况14设计原理与功能说明44.1设计思想44.2总体电路图54.3时钟模块64.4液晶显示模块64.5按键模块75系统测试75.1硬件测试75.2软件测试86总结8参考文献10附录一:总体电路原理图11附录二:主程序12附录三:元器件清单27 附录四:实物图281课程设计的目的1.通过制作万年历,可以对单片机这门课程更好的认识。
2.理论与实践结合,提高自己的动手能力。
3.学会与合作者更好的交流学习,共同进步和提高。
4.能够增长查阅资料的能力,视野更加开阔。
5.拓展其他学科的联系,全面发展。
6.培养自我发现问题,解决问题的能力。
2课程设计的任务与要求2.1设计任务1.可以去学校图书馆或者网上,搜集整理相关的资料,做好前期理论准备,为以后设计电路,看懂电路图做理论支持。
2.构想万年历电路图,并且具有可行性,画出电路图。
3.列举电路所需的电子元件,仔细对比所需的元件的参数,通过去电子元件经销商或者网购购买。
2.2设计要求1.显示年、月、日、时、分、秒。
2.可通过键盘自动调整时间。
3.计时精度:月误差小于20秒。
3单片机发展概况单片机诞生于20世纪70年代末,它的发展史大致可分为三个阶段:第一阶段(1976-1978):初级单片机微处理阶段。
该时期的单片机具有 8 位CPU,并行 I/O 端口、8 位时序同步计数器,寻址围 4KB,但是没有串行口。
第二阶段(1978-1982):高性能单片机微机处理阶段,该时期的单片机具有I/O 串行端口,有多级中断处理系统,15 位时序同步技术器,RAM、ROM 容量加大,寻址围可达 64KB。
第三阶段(1982-至今)位单片机微处理改良型及 16 位单片机微处理阶段民用电子产品、计算机系统中的部件控制器、智能仪器仪表、工业测控、网络与通信的职能接口、军工领域、办公自动化、集散控制系统、并行多机处理系统和局域网络系统。
用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();}}}}。
基于MCS-51单片机实现的万年历详细!
摘要本设计是一个基于MCS-51单片机实现的万年历。
本文首先描述系统硬件工作原理,并附以系统结构框图加以说明,着重介绍了本系统所应用的各硬件接口技术和各个接口模块的功能及工作过程,其次,详细阐述了程序的各个模块和实现方法。
本设计以数字集成电路技术为基础,AT89S52单片机技术为核心。
本文编写的主导思想是软、硬件相结合,以硬件为基础,来进行各功能模块的编写。
本系统以单片机的汇编语言进行软件设计,为了便于扩展和更改,软件的设计采用模块化结构,使程序设计的逻辑关系更加简洁明了。
系统通过LED显示数据,所以具有人性化的操作和直观的显示效果。
可以显示时间、阳历日期、星期,并有闹铃及检测温度的功能。
关键词:单片机;DS1302;DS18B20;LEDAbstractThe design is a based on the MCS-51 perpetual calendar.This article first describes the system hardware principle of work,and attaches by the system structure diagram performs to explain,emphatically introduced this system applies various hardware connection technology and each interface module function and the workprocess, next, it is elaborated the procedure of each module and how they realized. This design is based on the digital IC, and the core of AT89C52 MCU technique. This article writed with the guiding of software and hardware unifies, take the hardware as thefoundation, writing each programme for each functions module.This system’s software design whth th e MCU HUIBIAN language, in order to be advantageous for theexpansion and change, the software design uses the design of modularization, so that the logical of the programmer become clear and it is easy to understand .This system LED to show the data,so it has the humanize operation and the intuitionistic show effect. It can show the time, Gregorian calendar, week, bell, pronunciation of time and the temperature examination.Key Words:MCU; DS1302; DS18B20; LED目录摘要......................................................................................................................................I ABSTRACT.......................................................................................................................... II 1设计方案论证 (1)1.1功能要求 (1)1.2方案确定 (1)2 主控制器和外围器件 (4)2.1AT89S52单片机 (4)2.2温度芯片DS18B20 (5)2.3日历时钟芯片DS1302 (6)2.4数码管LED (9)2.5译码器74HC138 (9)3 硬件设计 (10)3.1电源设计 (10)3.2主电路设计 (11)4软件设计 (13)4.1主程序设计 (13)4.2键盘子程序设计 (15)4.3温度子程序设计 (17)4.4日历时钟子程序设计 (19)4.5 显示子程序设计 (21)4.6 闹钟子程序设计 (21)5系统调试 (23)5.1软件调试 (23)5.2硬件调试 (23)结论 (25)致谢 (26)附录一原理图 (27)附录二PCB图 (28)附录三程序清单 (29)主要参考文献 (48)1 设计方案论证1.1 功能要求1、能显示年、月、日、星期、时、分、秒。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
MOV COUNT,#0H
MOV A,#5 ;开始使A不等于0,用于后面的判断
MOV CLKMIN,#0H
MOV CLKHOUR,#0H
MOV CLKF,#0H
MOV SP,#60H
LCALL KEYADD1
MOV A,TEMP
SUBB A,#60 ;调节分钟不超过59
JC REMAIN0
MOV TEMP,#0
REMAIN0: MOV A,TEMP
MOV CLKMIN,A
LCALL S16 ;查看有无进入调节s16的键按下,
LCALL KEYADD2
MOV A,TEMP
SUBB A,#24 ;时的设置不超过过24置0
REMAIN1: MOV A,TEMP
MOV CLKHOUR,A
LCALL S16
CJNE A,#7EH,KEYCLK3 ;再次判断有无调节的切换键(按3次为确定)按下
DMS EQU 51H ;用于存放运动秒表的最低位
DSECOND EQU 52H ;用于存放运动秒表的秒
DMIN EQU 53H ;用于存放运动秒表的分钟
CLKMIN EQU 54H ;用于存放闹钟分钟
CLKHOUR EQU 55H ;用于存放闹钟时
CJNE A,#7EH,KEYCLK2 ;未按下继续显示分钟调节
KEYCLK3: LCALL SCLKHOUR ;按下进入显示时调节
MOV A,CLKHOUR
MOV TEMP,A ;送入参数,通过加减键进行调节设置
LCALL KEYSUB2
KEYCLK4: LCALL SHOWCLK ;按下后跳转为闹钟的界面正常显示
LCALL S4 ;再判断有无切换显示模式的键按下,按下跳转显示
JZ KEYSCAN
LCALL S8 ;再判断有无启动(关闭)闹钟功能的键按下
MOV A,CLKF ;根据CLKF(闹钟功能启动)的标志位显示不同的闹钟界面
CJNE A,#7EH,KEYCLK1 ;未按下继续闹钟界面显示
KEYCLK2: LCALL SCLKMIN ;按下进入调节
MOV A,CLKMIN ;显示设置分钟的调节
MOV TEMP,A
LCALL KEYSUB1 ;通过加减键s8,s12来设置闹钟
JNZ KEYCLKF ;闹钟功能启动,跳转到KEYCLKF显示闹钟启动标记
GOON: LCALL S16 ;未启动则又判断有无进入调节的键按下
CJNE A,#7EH,KEYCLK4 ;没有按下继续正常显示
AJMP KEYCLK2 ;按下后重复KEYCLK2开始的内容
JZ MARK3 ; 按下则跳入显示闹钟设置界面
LCALL S16 ;查看有无进入调节键s16按下,按下进入调节
CJNE A,#7EH,KEYSCAN ;未按下则 继续显示时间
SMINUTE: LCALL MINUTE ;s16按下后进入分调节显示
AJMP KEYCLK2 ;按下后则又进入调节界面KEYCLK2
;--------------------------------------------------
MARK3: LJMP MARK1 ;地址差跳远无法跳转,此处进行中间跳转到闹钟界面
;----------------------------------------------------
MOV TEMP,R5 ;将要调节的分钟送入函数参数
LCALL KEYADD1 ;进入调节后查看是否按下加法键s8,按下加一
CLKF EQU 56H ;用于闹钟开启的标志位
;-----------------------------------------------------------------------------------------
ORG 0000H
AJMP MAIN
MOV TMOD,#11H ;设置定时器0为工作模式1
MOV TH0, #03CH
MOV TL0, #0B0H ;定时50000 us
MOV TH1, #0D8H
MOV TL1, #0F0H ;定时1000us=1MS
KEYCLK: MOV A,CLKF ;此处为闹钟设置刚进入时的程序,由按键s12进入
JNZ KEYCLKF ;进入后通过CLKF来判断闹钟功能是否启动,未启动时正常
;显示为SHOWCLKF,启动时显示SHOWCLKF1,此两种显示差一个数码管最低位标志的点
LCALL S8 ;在闹钟显示界面下查看启动闹钟功能的键s8是否按下
MOV A,CLKF
JNZ KEYCLKF ;按下后显示SHOWCLKF1的显示
LCALL S16 ;未按下则显示没有闹钟标志的数码管显示,再查看有无进
;入调节s16的键按下,
;-----------------------------------------------------------------------------------------
MAIN: MOV R4,#00 ;计数秒
MOV R5,#50 ;计数分
MOV R6,#15 ;计数时
MOV R0,#14H ;2013年
MOV R1,#0DH
MOV R2,#6 ;6月
START: MOV DPTR,#TABLE
LJMP KEYSCAN ;首先进入时间显示,由于地址相差太远所以代码顺序有所改变
;--------------------------------------
MARK2: LJMP KEYSCAN ;地址差跳远无法跳转,此处进行中间跳转到时间显示界面
KEYCLKF: LCALL SHOWCLK1 ;显示出闹钟功能启动后的标记(数码管最低位标记)
LCALL S4 ;查看有无切换显示模式(闹钟设置确定后)键按下
JZ KEYSCAN ;按下后跳转到显示时间的界面
LCALL S8 ;未按则扫描开启(关闭)闹钟功能的键按下
MOV A,CLKF
BUZZER BIT P1.3 ;蜂鸣器
BYTE EQU 40H ;用于给锁存器送入数据
GEWEI EQU 41H ;用于存放数码管显示的第一位
SHIWEI EQU 42H ;用于存放数码管显示的第二位
BAIWEI EQU 43H ;用于存放数码管显示的第三位
KEYCLK1: LCALL SHOWCLK ;此处判定未启动闹钟功能时的显示
LCALL S4 ;在闹钟界面查看有无切换显示模式(此处也可认为是确定
;按键)的按键s4按下,
JZ MARK2 ;按下后跳转到时间显示
KEYSCAN: LCALL HOURMINUTE ;显示时间
PUSH ACC ;为s12的判断先把A入堆栈,否则s12出会出现判断错误
LCALL S4 ;查看有无切换键s4按下,按下跳转显示秒
JZ KEYSCAN1
ORG 000BH ;定时器0中断入口地址
AJMP T0_INT
ORG 001BH ;定时器1中断入口地址
AJMP T1_INT
;********************************主程序*************************************************
MOV A,CLKF ;在显示时间时判断闹钟功能是否开启,未开则跳转显示
JZ GO
MOV A,R6 ;判断是否与闹钟设置的时间相等,R6---时
CJNE A,CLKHOUR,GO
MOV A,R5 ;R5--分
CJNE A,CLKMIN,GO
QIANWEI EQU 44H ;用于存放数码管显示的第四位
TEMP1 EQU 45H
TEMP2 EQU 46H
COUNT EQU 47H ;用于扩展定时器计数时间
KTIME EQU 49H
TEMP EQU 50H
;-----------------------------------------------------------------------------------------
RCK BIT P0.5
SCK BIT P0.4
DAT BIT P0.7
RST BIT P0.6
SETB ET0 ;允许定时器中断
SETB ET1
SETB EA ;允许全局中断
SETB PT0 ;定时器中断设为高优先级
SETB EX0 ;允许外部中断
LCALL SOUND ;闹钟功能开启,时分相等,则闹铃响
;--------------------------------------------------
GO: POP ACC ; 如果不pop,A=0一直成立,此时出现错误跳转
LCALL S12 ;查看有无进入闹钟设置的键按下
JZ KEYCLK4 ;根据闹钟功能的标记位跳转显示,若判断闹钟功能关闭则
;跳转到KEYCLK4 显示无标志的闹钟
LCALL S16 ;若判断闹钟功能开启则扫描有无进入调节的按键s16按下
CJNE A,#7EH,KEYCLKF ;未按下则继续显示有标记的闹钟界面
SETB EX1
SETB IT0 ;外部中断设为下降沿触发
SETB IT1
SETB TR0 ;启动定时器
;---------------------------------------
;**************万年历制作 BY----信工七班