作者 张小波
CS1=1; CS2=0;
Write_Byte_To_LCD(LCD_PAGE+P); Write_Byte_To_LCD(LCD_COL+L); if(L+W<64) {
for(i=0;i Write_Data_To_LCD(r[i]); } else { for(i=0;i<64-L;i++) Write_Data_To_LCD(r[i]); CS1=0; CS2=1; Write_Byte_To_LCD(LCD_PAGE+P); Write_Byte_To_LCD(LCD_COL); for(i=64-L;i Write_Data_To_LCD(r[i]); } } else { CS1=0; CS2=1; Write_Byte_To_LCD(LCD_PAGE+P); Write_Byte_To_LCD(LCD_COL+L-64); for(i=0;i Write_Data_To_LCD(r[i]); } } (6) 显示一个8×16点阵字符 void Display_char(uchar P1,uchar L1,uchar *M) reentrant { LCD_Show(P1,L1,8,M); LCD_Show(P1+1,L1,8,M+8); } (7) 显示一个16×16点阵字符 (汉字上半部分与下半部分分别处在相邻两页中) void Display_Word(uchar P2,uchar L2,uchar *M) reentrant { LCD_Show(P2,L2,16,M); LCD_Show(P2+1,L2,16,M+16); } 2、DS1302时钟程序 作者 张小波 DS1302时钟程序上一项目有详细介绍,在此忽略。 3、字符汉字显示程序 在此程序中,我们主要定义了3个数组,分别为: (1)年、月、日、星期、时、分、秒等汉字点阵(16×16) 数组uchar code DATE_TIME_WORDS[]; (2)一、二、三、四、五、六和天等汉字点阵(16×16)uchar code WEEK_WORDS[]; (3)0-9等数字点阵(8×16)uchar code Digits[]; 各个汉字数字的具体字模可用专门的取字模软件得到,在文后的完整程序代码中有它们的具体字模数组。 4、主程序 主程序较简单,有初始化子程序Initialization(),其中包括LCD的初始化、显示初始化以及中断初始化工作。有2个中断服务子程序:一个用来刷新显示,一个用来处理4个按键。 ☆ 课堂小结 本文主要针对不含字库的LCD12864进行了时钟和日期的显示,具体的介绍了LCD12864显示程序的设计。同时我们在程序设计时也要善于把程序分解,分解成一个一个的小程序,这对于C程序的应用大有好处。当然通过这个项目的学习,我们也学习到了如何应用字模软件得到我们所要显示的汉字和数字的字模。 希望同学们仔细研究文后的完整程序代码。 ☆ 完整程序代码 1、 LCD12864显示驱动程序 //--------------------------LCD_12864.c------------------------- // 名称 :12864LCD显示驱动程序(不带字库) //----------------------------------------------------------------- #include #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 // 列指令 bit Reverse_Display=0;//是否反相显示(白底黑字/黑底白字) //液晶引脚定义 sbit DI=P2^0; sbit RW=P2^1; sbit E=P2^2; sbit CS1=P2^3; sbit CS2=P2^4; sbit RST=P2^5; //--------------------------------------------------------------- // 检查LCD是否忙 //-------------------------------------------------------------- bit LCD_IS_BUSY() { 作者 张小波 LCD_DB_PORT=0xFF; RW=1; _nop_(); DI=0; E=1; _nop_(); E=0; return (bit)(P0&0x80); } //--------------------------------------------------------------- // 向LCD写入一个字节(一般用于发送命令) //-------------------------------------------------------------- void Write_Byte_To_LCD(uchar comand) { while(LCD_IS_BUSY()); LCD_DB_PORT=0xFF; RW=0; _nop_(); DI=0; LCD_DB_PORT=comand; E=1; _nop_(); E=0; } //--------------------------------------------------------------- // 向LCD写入数据 //-------------------------------------------------------------- void Write_Data_To_LCD(uchar dat) { while(LCD_IS_BUSY()); LCD_DB_PORT=0xFF; RW=0; _nop_(); DI=1; if(!Reverse_Display) //根据Reverse_Display决定是否反相显示 LCD_DB_PORT=dat; else LCD_DB_PORT=~dat; E=1; _nop_(); E=0; } //--------------------------------------------------------------- // 初始化LCD 作者 张小波 //-------------------------------------------------------------- void LCD12864_Initialization() { CS1=1; CS2=1; Write_Byte_To_LCD(0x38); Write_Byte_To_LCD(0x0F); Write_Byte_To_LCD(0x01); Write_Byte_To_LCD(0x06); Write_Byte_To_LCD(LCD_START_ROW); } //--------------------------------------------------------------- // 通用显示函数 从第P页第L列显示W个字节数据,具体显示的数据在r所指的数组中 //-------------------------------------------------------------- void LCD_Show(uchar P,uchar L,uchar W,uchar *r) reentrant { uchar i; if(L<64) { CS1=1; CS2=0; Write_Byte_To_LCD(LCD_PAGE+P); Write_Byte_To_LCD(LCD_COL+L); if(L+W<64) { for(i=0;i Write_Data_To_LCD(r[i]); } else { for(i=0;i<64-L;i++) Write_Data_To_LCD(r[i]); CS1=0; CS2=1; Write_Byte_To_LCD(LCD_PAGE+P); Write_Byte_To_LCD(LCD_COL); for(i=64-L;i Write_Data_To_LCD(r[i]); } } else { CS1=0; CS2=1; 作者 张小波 Write_Byte_To_LCD(LCD_PAGE+P); Write_Byte_To_LCD(LCD_COL+L-64); for(i=0;i Write_Data_To_LCD(r[i]); } } //--------------------------------------------------------------- // 显示一个8×16点阵字符 //-------------------------------------------------------------- void Display_char(uchar P1,uchar L1,uchar *M) reentrant { LCD_Show(P1,L1,8,M); LCD_Show(P1+1,L1,8,M+8); } //-------------------------------------------------------------------- // 显示一个16×16点阵字符 (汉字上半部分与下半部分分别处在相邻两页中) //---------------------------------------------------------------------- void Display_Word(uchar P2,uchar L2,uchar *M) reentrant { LCD_Show(P2,L2,16,M); LCD_Show(P2+1,L2,16,M+16); } 2、 DS1302时钟程序 #include #define uchar unsigned char #define uint unsigned int sbit SDA=P1^0; //DS1302数据线 sbit CLK=P1^1; //DS1302时钟线 sbit RST=P1^2; // DS1302 复位线 char Adjust_Index=-1; //当前调节的时间对象:秒,分,时,日,月,年(0,1,2,3,4,6) uchar MonthsDays[]={0,31,0,31,30,31,30,31,31,30,31,30,31}; // 一年中每个月的天数,二月的天数由年份决定 uchar DateTime[7];//所读取的日期时间 //函数声明 void Write_Byte_TO_DS1302(uchar X); // 向DS1302写入一个字节 uchar Read_Byte_FROM_DS1302(); //从DS1302中读取一个字节 uchar Read_Data_FROM_DS1302(uchar addr); //从DS1302指定位置读取数据 , 读数据 void Write_Data_TO_DS1302(uchar addr,uchar dat); // 向DS1302指定位置写入数据, 写数据 void SET_DS1302(); // 设置时间 void GetTime(); // 读取当前时间 uchar Is_Leapyear(uint year);// 判断是否为闰年 //*--------写字节函数,向DS1302写入一个字节--------*//