当前位置:文档之家› 12864LCD万年历

12864LCD万年历

12864LCD+DS1302万年历设计proteus仿真(2011-05-18 23:09:40)标签:it原理图程序代码//DS1302与12864设计的可调式电子日历与时钟//#include<reg51.h>#include<intrins.h>#include<string.h>#define uchar unsigned char#define uint unsigned intextern void LCD_Initialize();extern void Display_A_Char_8x16(ucharP,ucharL,uchar *M)reentrant; extern void Display_A_WORD(ucharP,ucharL,uchar *M)reentrant;//在调整日期时间时,用该位决定是否反白显示//extern bit Reverse_Display;sbit SDA =P1^0; //DS1302数据线sbit CLK =P1^1; //DS1302时钟线sbit RST =P1^2; //DS1302复位线sbit K1 =P3^4; //选择sbit K2 =P3^5; //加sbit K3 =P3^6; //减sbit K4 =P3^7; //确定uchartCount =0;//一年中每月的天数,2月的天数由年份决定ucharMonthsDays[]={0,31,0,31,30,31,30,31,31,30,31,30,31};//所读取的日期时间ucharDateTime[7];//当前调整的时间对象:秒,分,时,日,月,年(0,1,2,3,4,6)//5对应星期,星期调节由年月日调整自动完成char Adjust_Index=-1;//水平与垂直偏移ucharH_Offset=10,V_Page_Offset=0;//年月日,星期,时分秒汉字点阵(16*16)------uchar code DATE_TIME_WORDS[]={//0x40,0x20,0x10,0x0C,0xE3,0x22,0x22,0x22,0xFE,0x22,0x22,0x22,0x22,0x02,0x00,0x00, 0x04,0x04,0x04,0x04,0x07,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x04,0x04,0x00, //0x00,0x00,0x00,0x00,0x00,0xFF,0x11,0x11,0x11,0x11,0x11,0xFF,0x00,0x00,0x00,0x00,0x00,0x40,0x20,0x10,0x0C,0x03,0x01,0x01,0x01,0x21,0x41,0x3F,0x00,0x00,0x00,0x00,//0x00,0x00,0x00,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x3F,0x00,0x00,0x00,0x00,//0x00,0x00,0x00,0xBE,0x2A,0x2A,0x2A,0xEA,0x2A,0x2A,0x2A,0x2A,0x3E,0x00,0x00,0x00, 0x00,0x48,0x46,0x41,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0x49,0x49,0x41,0x40,0x00,//0x00,0x04,0xFF,0x54,0x54,0x54,0xFF,0x04,0x00,0xFE,0x22,0x22,0x22,0xFE,0x00,0x00,0x42,0x22,0x1B,0x02,0x02,0x0A,0x33,0x62,0x18,0x07,0x02,0x22,0x42,0x3F,0x00,0x00,//0x00,0xFC,0x44,0x44,0x44,0xFC,0x10,0x90,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x00,0x00,0x07,0x04,0x04,0x04,0x07,0x00,0x00,0x03,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,//0x80,0x40,0x20,0x98,0x87,0x82,0x80,0x80,0x83,0x84,0x98,0x30,0x60,0xC0,0x40,0x00,0x00,0x80,0x40,0x20,0x10,0x0F,0x00,0x00,0x20,0x40,0x3F,0x00,0x00,0x00,0x00,0x00,//0x12,0x12,0xD2,0xFE,0x91,0x11,0xC0,0x38,0x10,0x00,0xFF,0x00,0x08,0x10,0x60,0x00,0x04,0x03,0x00,0xFF,0x00,0x83,0x80,0x40,0x40,0x20,0x23,0x10,0x08,0x04,0x03,0x00,//0x00,0x02,0x02,0xF2,0x12,0x12,0x12,0x12,0xF2,0x02,0x02,0x02,0xFE,0x02,0x02,0x00, 0x00,0x00,0x00,0x07,0x02,0x02,0x02,0x02,0x07,0x10,0x20,0x40,0x3F,0x00,0x00,0x00,//0x20,0x21,0xEE,0x04,0x00,0x00,0xFF,0x29,0xA9,0xBF,0xA9,0xA9,0x01,0xFF,0x00,0x00, 0x00,0x00,0x1F,0x88,0x44,0x30,0x0F,0x00,0x0F,0x04,0x04,0x4F,0x80,0x7F,0x00,0x00,//0x00,0x02,0x02,0x02,0x02,0x82,0x7E,0x22,0x22,0x22,0x22,0xF2,0x22,0x02,0x02,0x00,0x00,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x20,0x60,0x20,0x1F,0x00,0x00,0x00,0x00,//0x00,0x00,0xFE,0x02,0x22,0x22,0x22,0x22,0xFA,0x22,0x22,0x22,0xE2,0x02,0x02,0x00, 0x40,0x30,0x0F,0x00,0x40,0x20,0x18,0x06,0x01,0x00,0x20,0x60,0x3F,0x00,0x00,0x00,//0x00,0x02,0x82,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0xC2,0x82,0x02,0x00,0x00,0x00, 0x20,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x30,0x20,0x00,//0x42,0x42,0xFE,0x42,0x42,0xE0,0x00,0xFF,0x00,0x42,0x42,0xFE,0x42,0x42,0x42,0x00, 0x10,0x10,0x0F,0x88,0x49,0x20,0x18,0x07,0x20,0x20,0x20,0x3F,0x20,0x20,0x20,0x00,//0x00,0xFE,0x22,0x52,0x8E,0x00,0xC4,0xB4,0x8C,0xE7,0x84,0x84,0x84,0x84,0x04,0x00, 0x00,0xFF,0x02,0x04,0x23,0x10,0x0C,0x40,0x80,0x7F,0x00,0x02,0x04,0x18,0x30,0x00,/0x00,0x10,0x10,0x92,0x72,0xA2,0xA2,0xF2,0xAA,0xAA,0x66,0xA2,0x12,0x18,0x00,0x00, 0x10,0x08,0x06,0x01,0x04,0x44,0x84,0x7F,0x04,0x04,0x04,0x01,0x06,0x18,0x08,0x00,};//星期几的汉字点阵(16*16)uchar code WEEKDAY[]={//0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,///0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,///0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,///0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,};//半角数字点阵(8*16)uchar code DIGITS[]={////0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,///0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,///0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,///0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00, };//向DS1302写、读一字节--------//向DS1302写入一字节void Write_A_Byte_TO_DS1302(uchar x){uchar i;for (i=0;i<8;i++){SDA=x&1;CLK=1;CLK=0;x>>=1;}}//从DS1302读取一字节uchar Get_A_Byte_FROM_DS1302(){uchari,b,t;for(i=0;i<8;i++){b>>=1;t=SDA;b|=t<<7;CLK=1;CLK=0;}//BCD码转换return b/16*10+b;}//DS1302指定位置读数据ucharRead_Data(ucharaddr){uchardat;RST=0;CLK=0;RST=1;Write_A_Byte_TO_DS1302(addr);dat=Get_A_Byte_FROM_DS1302();CLK=1;RST=0;return dat;}//向DS1302某地址写入数据void Write_DS1302(ucharaddr,uchardat){CLK=0;RST=1;Write_A_Byte_TO_DS1302(addr);Write_A_Byte_TO_DS1302(dat);CLK=0;RST=0;}//设置时间void SET_DS1302(){uchar i;Write_DS1302(0x8E,0x00);//秒分时日月年依次写入for(i=0;i<7;i++){//秒的起始地址10000000(0x80),//后续依次是分,时,日,月,周,年,写入地址每次递增2 Write_DS1302(0x80+2*i,(DateTime[i]/10<<4)|(DateTime[i])); }Write_DS1302(0x8E,0x80);}//读取当前日期时间void GetTime(){uchar i;for(i=0;i<7;i++){DateTime[i]=Read_Data(0x81+2*i);}}//判断是否为闰年ucharisLeapYear(uint y){return(y%4==0&&y0!=0)||(y@0==0);}//----------------------------------------void RefreshWeekDay(){uinti,d,w=5;for(i=2000;i<2000+DateTime[6];i++){d=isLeapYear(i)?366:365;w=(w+d)%7;}d=0;for (i=1;i<DateTime[4];i++)d+=MonthsDays[i];d+=DateTime[3];DateTime[5]=(w+d)%7+1;}//年月日时分秒++--void DateTime_Adjust(char x){switch(Adjust_Index){case 6://年00-99if(x==1&&DateTime[6]<99) DateTime[6]++;if(x==-1&&DateTime[6]>0)DateTime[6]--;//获取2月天数MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28; //如果年份变化后当前月份的天数大于上限则设为上限if(DateTime[3]>MonthsDays[DateTime[4]])DateTime[3]=MonthsDays[DateTime[4]];RefreshWeekDay();//刷新星期break;case 4://月01-12if(x==1&&DateTime[4]<12)DateTime[4]++;if(x==-1&&DateTime[4]>1)DateTime[4]--;//获取2月天数MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28;//如果年份变化后当前月份的天数大于上限则设为上限if(DateTime[3]>MonthsDays[DateTime[4]])DateTime[3]=MonthsDays[DateTime[4]];RefreshWeekDay();//刷新星期break;case 3://日00-28/29/30/31;调节前首先根据年份得出该年中2月的天数MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28;//根据当前月份决定调节日期的上限if(x==1&&DateTime[3]<MonthsDays[DateTime[4]])DateTime[3]++;if(x==-1&&DateTime[3]>0)DateTime[3]--;RefreshWeekDay();//刷新星期break;case 2://时if(x==1&&DateTime[2]<23)DateTime[2]++;if(x==-1&&DateTime[2]>0)DateTime[2]--;break;case 1://分if(x==1&&DateTime[1]<59)DateTime[1]++;if(x==-1&&DateTime[1]>0)DateTime[1]--;break;case 0://秒if(x==1&&DateTime[0] <59) DateTime[0]++;if(x==-1&&DateTime[0] >0) DateTime[0]--;break;}}//定时器0每秒刷新LCD显示void T0_INT() interrupt 1{TH0=-50000/256;TL0=-50000%6;if(++tCount!=2)return;tCount=0;//年(后两位)Reverse_Display=Adjust_Index==6;Display_A_Char_8x16(V_Page_Offset,16+H_Offset,DIGITS+DateTime[6]/10*16); Display_A_Char_8x16(V_Page_Offset,24+H_Offset,DIGITS+DateTime[6]*16);//月Reverse_Display=Adjust_Index==4;Display_A_Char_8x16(V_Page_Offset,48+H_Offset,DIGITS+DateTime[4]/10*16); Display_A_Char_8x16(V_Page_Offset,56+H_Offset,DIGITS+DateTime[4]*16);//日Reverse_Display=Adjust_Index==3;Display_A_Char_8x16(V_Page_Offset,80+H_Offset,DIGITS+DateTime[3]/10*16); Display_A_Char_8x16(V_Page_Offset,88+H_Offset,DIGITS+DateTime[3]*16);//星期Reverse_Display=Adjust_Index==5;Display_A_Char_8x16(V_Page_Offset+3,104+H_Offset, WEEKDAY+DateTime[5]*16-16);//时Reverse_Display=Adjust_Index==2;Display_A_Char_8x16(V_Page_Offset+6,16+H_Offset,DIGITS+DateTime[2]/10*16); Display_A_Char_8x16(V_Page_Offset+6,24+H_Offset,DIGITS+DateTime[2]*16);//分Reverse_Display=Adjust_Index==1;Display_A_Char_8x16(V_Page_Offset+6,48+H_Offset,DIGITS+DateTime[1]/10*16); Display_A_Char_8x16(V_Page_Offset+6,56+H_Offset,DIGITS+DateTime[1]*16);//秒Reverse_Display=Adjust_Index==0;Display_A_Char_8x16(V_Page_Offset+6,80+H_Offset,DIGITS+DateTime[0]/10*16); Display_A_Char_8x16(V_Page_Offset+6,88+H_Offset,DIGITS+DateTime[0]*16);} //键盘中断(INT0)void EX_INT0() interrupt 0{if (K1 == 0) //选择调整对象{if (Adjust_Index == -1 || Adjust_Index == 0) Adjust_Index = 7;Adjust_Index--;if (Adjust_Index == 5) Adjust_Index = 4; //跳过对星期的调整}elseif (K2 == 0)DateTime_Adjust( 1); //加elseif (K3 == 0)DateTime_Adjust( -1 ); //减elseif (K4 == 0) //确定{SET_DS1302();Adjust_Index = -1;}}void main(){//液晶初始化LCD_Initialize();//显示年的固定前两位Display_A_Char_8x16(V_Page_Offset,0+H_Offset,DIGITS+2*16);Display_A_Char_8x16(V_Page_Offset,8+H_Offset,DIGITS);//显示固定汉字:年月日,星期,时分秒Display_A_WORD(V_Page_Offset,32+H_Offset,DATE_TIME_WORDS+0*32); Display_A_WORD(V_Page_Offset,64+H_Offset,DATE_TIME_WORDS+1*32); Display_A_WORD(V_Page_Offset,96+H_Offset,DATE_TIME_WORDS+2*32); Display_A_WORD(V_Page_Offset+3,72+H_Offset,DATE_TIME_WORDS+3*32); Display_A_WORD(V_Page_Offset+3,88+H_Offset,DATE_TIME_WORDS+4*32); Display_A_WORD(V_Page_Offset+6,32+H_Offset,DATE_TIME_WORDS+5*32); Display_A_WORD(V_Page_Offset+6,64+H_Offset,DATE_TIME_WORDS+6*32); Display_A_WORD(V_Page_Offset+6,96+H_Offset,DATE_TIME_WORDS+7*32); Display_A_WORD(V_Page_Offset+2,0+H_Offset,DATE_TIME_WORDS+8*32); Display_A_WORD(V_Page_Offset+2,16+H_Offset,DATE_TIME_WORDS+9*32); Display_A_WORD(V_Page_Offset+2,32+H_Offset,DATE_TIME_WORDS+10*32); Display_A_WORD(V_Page_Offset+2,48+H_Offset,DATE_TIME_WORDS+11*32); Display_A_WORD(V_Page_Offset+4,0+H_Offset,DATE_TIME_WORDS+12*32); Display_A_WORD(V_Page_Offset+4,16+H_Offset,DATE_TIME_WORDS+13*32); Display_A_WORD(V_Page_Offset+4,32+H_Offset,DATE_TIME_WORDS+14*32); Display_A_WORD(V_Page_Offset+4,48+H_Offset,DATE_TIME_WORDS+15*32);//允许INT0,T0中断IE=0x83;IP=0x01;IT0=0x01;TH0=-50000/256;TL0=-50000/256;TR0=1;while(1){//如果未执行调整操作则正常读取当前时间if(Adjust_Index==-1)GetTime();}}// 名称:12864LCD显示驱动程序(不带字库)//------------------------------------------------------------- #include <reg51.h>#include <intrins.h>#define unchar unsigned char#define uint unsigned int#define LCD_DB_PORT P0 //液晶DB0-DB7 #define LCD_START_ROW 0xC0 //起始行#define LCD_PAGE 0xB8 //页指令#define LCD_COL 0x40 //列指令//液晶引脚定义sbit DI =P2^0 ;sbit RW =P2^1 ;sbit E =P2^2 ;sbit CS1 =P2^3 ;sbit CS2 =P2^4 ;sbit rst =P2^5 ;bit Reverse_Display =0;//----------------------------------------------------------- //检查LCD是否忙//-----------------------------------------------------------bit LCD_Check_Busy (){LCD_DB_PORT =0xFF;RW =1; _nop_(); DI =0;E =1;_nop_(); E =0;return (bit) (P0 & 0x80);}//-----------------------------------------------------------// 向LCD发送命令//-----------------------------------------------------------void LCD_Write_Command( unchar c){while (LCD_Check_Busy ());LCD_DB_PORT =0xFF; RW =0; _nop_();DI =0;LCD_DB_PORT = c; E =1; _nop_();E =0;}//-----------------------------------------------------------//向LCD发送数据//-----------------------------------------------------------//向LCD发送数据void LCD_Write_Data(uchar d ){while(LCD_Check_Busy());LCD_DB_PORT = 0xFF;RW = 0; _nop_();DI = 1;//根据Reverse_Display决定是否反相显示if (! Reverse_Display) LCD_DB_PORT = d; else LCD_DB_PORT = ~d;E = 1 ;_nop_(); E = 0;}//初始化LCDvoid LCD_Initialize(){CS1 = 1; CS2 = 1;LCD_Write_Command(0x38);LCD_Write_Command(0x0F);LCD_Write_Command(0x01);LCD_Write_Command(0x06);LCD_Write_Command(LCD_START_ROW);}void Common_Show(ucharP,ucharL,ucharW,uchar *r)reentrant {uchar i;if(L<64)//显示在左半屏或左右半屏{CS1=1; CS2=0;LCD_Write_Command( LCD_PAGE+P);LCD_Write_Command(LCD_COL + L);if(L+W<64){for(i=0;i<W;i++) LCD_Write_Data(r[i]);}else//如果月结则跨越左右半屏显示{for(i=0;i<64-L;i++) LCD_Write_Data(r[i]);CS1=0;CS2=1;LCD_Write_Command(LCD_PAGE+P);LCD_Write_Command(LCD_COL);for(i=64-L;i<W;i++) LCD_Write_Data(r[i]);}}else // 全屏显示在右半屏{CS1=0;CS2=1;LCD_Write_Command(LCD_PAGE + P);LCD_Write_Command(LCD_COL+L-64);for (i=0;i<W;i++)LCD_Write_Data(r[i]);}}//显示一个8X16点阵字符//void Display_A_Char_8X16(ucharP,ucharL,uchar *M) reentrant {Common_Show( P, L, 8, M );Common_Show( P +1,L,8,M+8 );}//显示一个16x16点阵汉字void Display_A_WORD(ucharP,ucharL,uchar *M) reentrant {Common_Show( P, L, 16, M); //显示汉字上半部分Common_Show( P + 1,L, 16, M +16); //显示汉字下半部分}。

相关主题