完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
第十五节:液晶屏第二大类定律—横向显示八个点(RA8835驱动320240屏)
第二大类定律:横向显示八个点的类型。 这类液晶屏在横向上以八个点(一个字节)为基本单位,因此X坐标数值的最大范围是横向上的点阵数除以八,然后再减去一(因为从零开始)。而Y坐标数值的最大范围就直接是纵向上的点阵数减去一(因为从零开始)。 (1) 开场白: 这节 我以驱动芯片为RA8835的320240液晶屏为例子,来继续深入了解第二大类定律:横向显示八个点的类型。RA8835驱动芯片的驱动范围很大,它可以直接驱动一块320240的液晶屏,因此320240液晶屏实际上就是由一块320240液晶屏组成的,没有分屏合并的概念。320240屏在横向上是320个点,纵向上是240个点,也就是一个长方形的屏。因为它属于第二大类的屏,所以X轴坐标数值的最大范围是(320/8)-1=39,而纵向坐标数值的最大范围是240-1=239. 正常的操作思路是这样的,先发送X轴与Y轴的位置数据,确定位置后,就发送一个字节(八个点)的显示数据。这类屏还有一个特征,连续发送显示数据时,在横向(X轴上)的位置数据会自动加一,因此如果在不换行的情况下,只要设定一次位置,就可以从左到右连续发送显示的数据。当换行显示数据时,必须重新设定一下坐标位置。 横向取模,字节正序与倒序的概念解释:当我们一次在横向上显示八个点的基本单位时,实际上等于我们发送了一个字节的显示数据,比如0x01,如果是正序的屏,那么从左到右的八个点中,只有第8个点是显示的,其它的是空白,而如果是倒序的屏,则只有第1个点是显示的,其它是空白的。320240这个屏是属于正序的屏。 取模软件是必须的,读者可以在网上自己下载,资料很多。 (2)功能需求: 在320240屏上分别显示8X16的字符,16X16的汉字,24X24的汉字。 (3)硬件原理: 液晶屏的VEE接20K可调电阻的左边端口,VO接可调电阻的中间端口,VSS接可调电阻的右边端口,此可调电阻在这里用来调节液晶屏的对比度。模块与背光的电源线接上5V,其它数据线跟单片机的IO口连接上。这个大家都懂。 (4)源码适合的单片机:SST89E516RD,晶振为11.0592MHz。 (5)源代码讲解如下: #include #include #define LcmXPixel 320 //横向宽度 #define LcmYPixel 240 //纵向高度 #define Uchar unsigned char #define Uint unsigned int #define SystemSet 0x40 //硬件寄存器的驱动信息,具体是什么意思没必要知道 #define Scroll 0x44 #define BasePart1 0x00 //显示区1 #define BasePart2 0x40 //显示区2 #define BasePart3 0x80 //显示区3 #define BasePart4 0x00 //显示区4 #define DispOn 0x59 #define DispOff 0x58 #define Ovlay 0x5b #define HdotScr 0x5a #define CsrDirR 0x4c #define CsrDirL 0x4d #define CsrDirU 0x4e #define CsrDirD 0x4f #define CsrW 0x46 #define CsrR 0x47 #define mWrite 0x42 #define mRead 0x43 #define paraP9 (LcmXPixel/8) //补充说明:吴坚鸿程序风格是这样的,凡是输出IO后缀都是_dr,凡是输入的//IO后缀都//是_sr,凡是数据总线后缀都是_bus #define LcmDataBus P1 //数据总线 ***it WR_dr=P3^0; ***it RD_dr=P3^1; ***it CS_dr = P3^5; ***it RS_dr = P3^3; ***it RES_dr = P3^4; void delay(unsigned int t); //时序延时函数声明 void write_com(unsigned char cmdcode); //往液晶模块写入指令 void write_data(unsigned char Di_drspdata); //往液晶模块写入数据 void LocateXY(unsigned char x,unsigned char y);//设定显示地址函数,驱动液晶程序的一部分 void screen_clear(); //清空屏的内容 void ***_display816(unsigned char col, unsigned char pag,const unsigned char * zk,unsigned char opposite_flag); //显示8X16的字符函数,本节的核心内容 void hz_display1616(unsigned char col, unsigned char pag,const unsigned char * zk,unsigned char opposite_flag); //显示16X16的汉字函数,本节的核心内容 void hz_display2424(unsigned char col, unsigned char pag,const unsigned char * zk,unsigned char opposite_flag); //显示24X24的汉字函数,本节的核心内容 void init_lcd(); //初始化液晶模块 Uchar code ParaSysTable8[]={ //P1-P8参数,估计是设置硬件寄存器的信息,我也不懂,没必要懂 0x30,0x87,0x07,(LcmXPixel/8-1),(10000000/9/LcmYPixel/70),LcmYPixel,(LcmXPixel/8),0x00 }; Uchar code ParaScrTable10[]={ //P1-P10参数,估计是设置硬件寄存器的信息,我也不懂,没必要懂 0x00,BasePart1,0xF0,0x00,BasePart2,0xF0,0x00,BasePart3,0x00,BasePart4 }; unsigned char Lcm_Layer = 1; //显示所在层1,2,3分别表示1 2 3区,具体含义我也不懂,没必要懂 //补充说明:吴坚鸿程序风格是这样的,凡是字库内容,如果是字符,则前缀用***,然后紧//跟着点阵数,接着下划线,最后紧跟显示的字符。如果有重复的,则多加一个序列号标识。如果是汉字,则前缀用hz,其它的一样。 unsigned char code ***816_V[]=//从取模软件中复制的字库,横向取模,字节正序 { /*-- 文字: V --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/ 0x00,0x00,0x00,0xE7,0x42,0x42,0x44,0x24,0x24,0x28,0x28,0x18,0x10,0x10,0x00,0x00, }; unsigned char code ***816_5[]= { /*-- 文字: 5 --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/ 0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x58,0x64,0x02,0x02,0x42,0x44,0x38,0x00,0x00, }; unsigned char code hz1616_hong[]= { /*-- 文字: 鸿 --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/ 0x40,0x20,0x20,0x40,0x20,0xFC,0x0E,0xC4,0x84,0xA4,0x54,0xA4,0x54,0x8C,0x24,0x80, 0x24,0xFE,0x26,0x02,0xD8,0x02,0x43,0xFA,0x40,0x02,0x40,0x02,0x40,0x0A,0x00,0x04, }; unsigned char code hz1616_ge[]= { /*-- 文字: 哥 --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/ 0x00,0x00,0x7F,0xFC,0x00,0x10,0x1F,0x90,0x10,0x90,0x1F,0x90,0x10,0x90,0x00,0x04, 0xFF,0xFE,0x00,0x10,0x1F,0x90,0x10,0x90,0x1F,0x90,0x10,0x90,0x00,0x50,0x00,0x20, }; unsigned char code hz2424_hong[]= { /*-- 文字: 鸿 --*/ /*-- 宋体18; 此字体下对应的点阵为:宽x高=24x24 --*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0xC0,0x08,0x00,0x80,0x0C,0x01,0x00,0x00, 0x17,0xF8,0x03,0xFC,0x18,0x44,0x44,0x98,0x24,0x44,0xD0,0x34,0x44,0x10,0x14,0x44, 0x10,0x08,0x44,0x70,0x08,0x44,0x20,0x08,0x44,0x04,0x08,0x57,0xFC,0x08,0xE0,0x0C, 0x33,0x00,0x0C,0x10,0x00,0x6C,0x10,0x3F,0x98,0x10,0x00,0x08,0x10,0x00,0x08,0x18, 0x00,0xF8,0x18,0x00,0x30,0x00,0x00,0x00, }; unsigned char code hz2424_ge[]= { /*-- 文字: 哥 --*/ /*-- 宋体18; 此字体下对应的点阵为:宽x高=24x24 --*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x1F,0xFF,0xF8,0x00,0x00,0x40,0x02, 0x08,0x40,0x03,0xF8,0x40,0x02,0x08,0x40,0x02,0x08,0x40,0x03,0xF8,0x40,0x00,0x00, 0x40,0x00,0x00,0x0C,0x1F,0xFF,0xF0,0x00,0x00,0x40,0x07,0xF8,0x40,0x06,0x08,0x40, 0x06,0x08,0x40,0x06,0x08,0x40,0x07,0xF8,0x40,0x06,0x08,0x40,0x00,0x00,0x40,0x00, 0x03,0xC0,0x00,0x00,0xC0,0x00,0x00,0x00, }; //主程序 void main(void) { init_lcd(); //初始化液晶屏 screen_clear ();//清空整屏显示内容 //左边,正显,16X16的汉字,鸿哥V5,X轴的范围是0到39 hz_display1616(0, 0,hz1616_hong,0); hz_display1616(2, 0,hz1616_ge,0); ***_display816(4, 0,***816_V,0); ***_display816(5, 0,***816_5,0); //右边,反显,24X24的汉字,鸿哥,X轴的范围是0到39 hz_display2424(30, 0,hz2424_hong,1); hz_display2424(33, 0,hz2424_ge,1); while(1) { ; } } //------------------时序延时子程序----------------------------- void delay(unsigned int t) { unsigned int i; for(i=0;i } //------------------写命令到LCD,,驱动液晶程序的一部分------------------------------ void write_com(unsigned char cmdcode) { CS_dr = 0; RS_dr = 1; LcmDataBus = cmdcode; _nop_();_nop_(); WR_dr = 0; _nop_();_nop_(); WR_dr = 1; _nop_();_nop_(); CS_dr = 1; LcmDataBus = 0xff; } //-------------------写数据到LCD,,驱动液晶程序的一部分---------------------------- void write_data(unsigned char Di_drspdata) { CS_dr = 0; RS_dr = 0; LcmDataBus = Di_drspdata; _nop_();_nop_(); WR_dr = 0; _nop_();_nop_(); WR_dr = 1; _nop_();_nop_(); CS_dr = 1; LcmDataBus = 0xff; } //设定显示地址函数,驱动液晶程序的一部分---------------------------- void LocateXY(unsigned char x,unsigned char y) //内部到底什么含义,我也是看得两眼冒星星。只要我们会用就行 { Uint temp,locateH,locateL; temp = (Uint)y*paraP9+x; locateL = (Uchar)(temp & 0xff); locateH = (Uchar)(temp / 256 ); if( Lcm_Layer == 2 ) { locateH = locateH + BasePart2; } if( Lcm_Layer == 3 ) { locateH = locateH + BasePart3; } write_com( CsrW ); write_data( locateL ); write_data( locateH ); } //*------------------清空屏幕的内容,内部的时序细节可以不管,因为我也没仔细去研究过,知道是用来干什么的就行---------------*/ void screen_clear () { Uint i=32768; write_com(DispOff); //清屏之前先发关闭显示的命令,固有的命令格式,不用在意 write_com( CsrDirR ); //清屏命令 LocateXY(0,0); write_com( mWrite ); while(i--) { write_data( 0 ); //发送清屏的数据0 } write_com(DispOn); //清屏之后发打开显示的命令,固有的命令格式,不用在意 write_data( 0x54 ); //固有的命令格式,不用在意 } //显示8X16的字符函数,本节的核心内容。col代表X轴,pag代表Y轴,zk代表显示相对//应的字库,opposite_flag代表是否反显,0表示正常显示,1表示反显 void ***_display816(unsigned char col, unsigned char pag,const unsigned char *zk,unsigned char opposite_flag) { unsigned char j=0,i=0; write_com( CsrDirR ); //硬件固有的命令模式,不用管具体的含义 for(j=0;j<16;j++) //此处j代表Y轴的数据,也就是显示第几行了,一个8X16字符只占用16行 { LocateXY(col,pag+j); //每次换行重新设置一次显示的起始地址 write_com( mWrite ); //硬件固有的命令模式,不用管具体的含义 for(i=0;i<1;i++) //此处i代表X轴的数据,每发送一个显示数据,X轴地址会自动加一,横向类的屏,8X16字符的宽度是8个点阵,范围是(只有一个0),(8/8)-1=0. { if(opposite_flag ==1) //反显 { write_data(~zk [1*j+i]); //发送显示的字节数据,一行1个字节,因此1*j } else //正显 { write_data(zk [1*j+i]); //发送显示的字节数据,一行1个字节,因此1*j } } } } //显示16X16的汉字函数,本节的核心内容。col代表X轴,pag代表Y轴,zk代表显示相//对应的字库,opposite_flag代表是否反显,0表示正常显示,1表示反显 void hz_display1616(unsigned char col, unsigned char pag,const unsigned char *zk,unsigned char opposite_flag) { unsigned char j=0,i=0; write_com( CsrDirR ); //硬件固有的命令模式,不用管具体的含义 for(j=0;j<16;j++) //此处j代表Y轴的数据,也就是显示第几行了,一个16X16汉字只占用16行 { LocateXY(col,pag+j); //每次换行重新设置一次显示的起始地址 write_com( mWrite ); //硬件固有的命令模式,不用管具体的含义 for(i=0;i<2;i++) //此处i代表X轴的数据,每发送一个显示数据,X轴地址会自动加一,横向类的屏,16X16汉字的宽度是16个点阵,范围是(0到1),(16/8)-1=1. { if(opposite_flag ==1) //反显 { write_data(~zk [2*j+i]); //发送显示的字节数据,一行2个字节,因此2*j } else //正显 { write_data(zk [2*j+i]); //发送显示的字节数据,一行2个字节,因此2*j } } } } //显示24X24的汉字函数,本节的核心内容。col代表X轴,pag代表Y轴,zk代表显示相//对应的字库,opposite_flag代表是否反显,0表示正常显示,1表示反显 void hz_display2424(unsigned char col, unsigned char pag,const unsigned char *zk,unsigned char opposite_flag) { unsigned char j=0,i=0; write_com( CsrDirR ); //硬件固有的命令模式,不用管具体的含义 for(j=0;j<24;j++) //此处j代表Y轴的数据,也就是显示第几行了,一个24X24汉字只占用24行 { LocateXY(col,pag+j); //每次换行重新设置一次显示的起始地址 write_com( mWrite ); //硬件固有的命令模式,不用管具体的含义 for(i=0;i<3;i++) //此处i代表X轴的数据,每发送一个显示数据,X轴地址会自动加一,横向类的屏,24X24汉字的宽度是24个点阵,范围是(0到2),(24/8)-1=2. { if(opposite_flag ==1) //反显 { write_data(~zk [3*j+i]); //发送显示的字节数据,一行3个字节,因此3*j } else //正显 { write_data(zk [3*j+i]); //发送显示的字节数据,一行3个字节,因此3*j } } } } //*------------------初始化LCD屏--------------------------*/ void init_lcd() { Uchar i; delay(34760); //上机延时一会 RES_dr = 1; delay(4920); RES_dr = 0; //复位 delay(4920); RES_dr = 1; delay(14760); write_com( SystemSet ); //以下几行是硬件初始化,没必要知道具体含义,照抄就行 for (i=0;i<8;i++) { write_data( ParaSysTable8[i] ); } write_com( Scroll ); for (i=0;i<10;i++) { write_data( ParaScrTable10[i] ); } write_com( HdotScr ); write_data( 0 ); write_com( Ovlay ); write_data( 0x0C ); write_com( 0x60 ); //13700多出来的灰度设置 write_data( 0 ); //1bpp单色 } (6)小结: 读者要重点弄清楚void ***_display816, void hz_display1616, void hz_display2424这三个函数他们之间的联系与规律,即可掌握本节内容的精髓。 今天我一个好朋友看到我在电子发烧友网站上发表的这个连载文章,他打电话问我,为什么不搞一个子函数可以显示任意点阵像素字体的液晶驱动函数呢?为什么不搞一个可以兼容跨屏显示的子函数呢?我的答案是:一方面可以让读者更加容易了解“吴坚鸿液晶显示三大类定律”的精髓,另一方面是在实战中,其实没有读者想象中那么复杂,一般的项目只要求显示两种点阵像素的字体即可,一个是字符的8x16,一个是汉字的16X16。而一个字体跨屏显示,在我们考虑显示菜单布局的时候就可以人为的过滤掉这种方案。接着他又跟我争论,做一个兼容所有不同点阵像素的驱动程序,可以更加省容量。我又笑了,鸿哥在做那么多项目中,从来不差容量,容量也不是我第一个考虑的问题,除非是迫不得已我才会想办法压缩容量。我第一个考虑的问题是,编写的程序运行效率要高,思路要清晰,书写的“队形”要整齐,要有自己的基本套路。 (未完待续,下节更精彩,不要走开哦) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
牛人!!!!!!!!!!!!!!!!!膜拜你
|
|
|
|
|
|
接着膜拜!!!!!!!!!!
|
|
|
|
|
|
|
|
|
|
有看门狗的话,程序跑飞之后相当于重新开机复位一样,不同的系统有不同的效果。比如,有的设备是通过一个按钮启动,然后自动运行的,当正在运行时,程序跑飞了,就会被看门狗自动复位,复位后,机器其实已经停了下来,要重新通过一个按钮才能启动。而有的设备,是一上电就自动循环运行的,在运行中,即使跑飞了,看门狗也会自动复位,复位后继续跑,感觉没有受到什么影响。实际上大部分的单片机抗干扰能力都很好的,如果老是***扰跑飞,即使有看门狗,这个系统也是不合格的。一般的系统有看门狗肯定要比没有看门狗好一点点,起码也是一个心理的安慰。 |
|
|
|
|
|
终于看完了鸿哥的力作!!不容易!!
|
|
|
|
|
|
|
|
|
|
只有小组成员才能发言,加入小组>>
求解外围电路实现的是4脚给持续低电平复位并正常工作,高电平不工作的原因
2077 浏览 1 评论
3505 浏览 3 评论
PIC1946程序有一个变量在运行过程中恢复初始值其他变量保持不变
2333 浏览 2 评论
2760 浏览 0 评论
PIC16F1825的RC5引脚,在主程序中操作无效,在中断中可以改变是为什么?
4015 浏览 5 评论
966浏览 0评论
用XC8编译PIC18F25K80时提示下面Error,求怎么解决这个问题
6349浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-27 18:18 , Processed in 1.119486 second(s), Total 86, Slave 78 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号