完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
鸿哥确实是奇人一个,有个性,幽默,也有创意!和我认识的一个朋友非常非常像!
他是搞上位机软件出身的,中间做过下位机单片机的程序,思路和您一样,自己一个人苦思凝想的想出来做一个程序构架,和您的很像都是类似于状态机的原理,但又不同!他这个人也是幽默感十足,乐于分享,喜欢教别人,你们太像了!可惜,我们在北方,距离太远。。。。。。。 |
|
|
|
|
|
|
|
|
|
|
|
|
|
吴哥!ST7920驱动的12864屏适用于你的第三大类定律吧
|
|
|
|
|
|
本帖最后由 jianhong_wu 于 2013-2-1 14:09 编辑
应该是适应于第一或者第二类定律。关键是你要找出它显示的基本单位是横向的还是纵向的,然后按我提供的那个套路编写各种点阵字体的函数。ST7920这个是带字库的,还可以用串口和并口这两种驱动方式。如果在同等的条件下,我建议你用不带字库的屏。因为对于单片机的项目来说,字库我们可以自己建立,虽然会多开销一些程序容量,但是字体我们可以随意更改,除非是涉及到拼音输入法的项目。反正我做的项目,尽量不选带字库的屏,字库都是自己建的,即使这个屏本身自带字库,我也不会去用它。关于ST7920的源代码,我不方便提供,因为我的源代码没有经过整理,有很多公司的信息,我也比较忙,不愿意花这个时间去整理它,你自己在网上找找,如果真找不到源代码,那就不要用这个屏,还是换成KS0107驱动的屏吧。 |
|
|
|
|
|
本帖最后由 jianhong_wu 于 2013-2-3 02:46 编辑
第十七节:液晶屏第三大类定律—任意位置显示一个点(HT1621驱动段码液晶屏) (1) 开场白: 段码液晶屏往往应用在出货量比较大的家用消费类电子,比如空调遥控器,小时候带的电子手表等,都是段码屏。段码屏是非标屏,都是客户定做的,第一次开模费大概一两千元,厂家一般都会有起订量的要求,除此之外,它的单位成本相对要比点阵屏要便宜,而且我个人认为显示的效果要比点阵屏漂亮。 段码屏的驱动程序跟数码管的静态驱动程序一样,只要我们弄懂了怎样显示一个基本单位,根据此基本单位编写一个字库表,然后用与(&)和或(|)这两种位运算符就可以随心所欲编写我们要显示的数字或者形状。有两种常用的驱动方案: 第一种:如果单片机内部集成了seg和com引脚的液晶驱动模块,直接用单片机驱动。 第二种:单片机用3个IO口跟HT1621进行通讯,用 HT1621驱动段码屏。 这节我重点介绍第二种。HT1621有4个COM,分别是com3,com2,com1,com0。有32个SEG,分别是SEG0,SEG1….SEG31。 什么是COM,什么是SEG?用鸿哥的思路来解释,COM就是横向上的X坐标,SEG就是纵向上的Y坐标。X坐标与Y坐标组合成一张表格,每格代表一个显示点。比如HT1621,有4个COM,32个SEG,组成一个32行,每行装4个点的表格,一共有128个点,也就是最多可以显示128个点,用数码管的思路,最多可以显示128个LED灯。因为纵向上有32行,因此Y轴的地址范围是0到31。每一行X轴上的4个点,我们用一个字节来表示。一个字节有8位,高4位分别代表这个4个点,低4位为空。比如第一行(SEG0行)的第1个(COM3)要显示,第2个(COM2)要显示,第3个(COM1)不要显示,第4个(COM0)不要显示,那么用一个字节来表示就是十六进制的0xc0.要把这两个点点亮,只要把X轴的数据设置成0xc0,Y轴的数据设置成0x00,然后放到鸿哥精心研制的seg_display(unsigned char col, unsigned char pag)驱动程序里就可以了. (2)功能需求: 在COM和SEG组成的4X32表格中,显示第二行的第3和第4两个点。 (3) 硬件原理: 用单片机的3个IO口分别跟HT1621的CS,WR,DATA连接。 (4)源码适合的单片机:STC11F04E,晶振为11.0592MHz。 (5)源代码讲解如下: #include "REG52.H" #include "absacc.h" #include "intrins.h" #include "stdio.h" #define BIAS 0X52 //此处千万小心,鸿哥在上个月的一个项目中就是在这里被卡了7天。 //必须跟硬件电路的COM匹配。1个或者2个COM:0x42。3个COM:0x4A。4个COM:0x52 #define RC256 0X30 #define SYSTEN 0X02 #define SYSDIS 0X00 #define LCDON 0X06 void SendBitToHT1621(unsigned char nbit,unsigned char n);//发送一个字节中的N位到HT1621里,驱动程序的最底层部分 void write_com(unsigned char cmdcode); //写命令到LCD void init_lcd(); //--初始化LCD屏 void seg_display(unsigned char col, unsigned char pag); //显示基本单位点 void screen_clear (); //清空屏幕的内容 //补充说明:吴坚鸿程序风格是这样的,凡是输出IO后缀都是_dr,凡是输入的//IO后缀都//是_sr ***it ht162x_data_dr=P3^1; ***it ht162x_cs_dr=P3^6; ***it ht162x_wr_dr=P3^0; main() { init_lcd(); //初始化液晶屏 screen_clear ();//清空整屏显示内容 seg_display(0x30,1); //在COM和SEG组成的4X32表格中,显示第二行的第3和第4两个点。 while(1) { ; } } //发送一个字节中的N位到HT1621里,驱动程序的最底层部分 void SendBitToHT1621(unsigned char nbit,unsigned char n) { unsigned char i; for(i=0;i ht162x_wr_dr=0; if(nbit>=0x80) //判断最高位 ht162x_data_dr=1; else ht162x_data_dr=0; _nop_(); _nop_(); _nop_(); ht162x_wr_dr=1; _nop_(); _nop_(); _nop_(); nbit<<=1; } } //------------------写命令到LCD,,驱动液晶程序的一部分------------------------------ void write_com(unsigned char cmdcode) { ht162x_cs_dr=0; //选通HT1621 _nop_(); _nop_(); SendBitToHT1621(0x80,4); SendBitToHT1621(cmdcode,8); _nop_(); _nop_(); ht162x_cs_dr=1; _nop_(); _nop_(); _nop_(); } //*------------------初始化LCD屏--------------------------*/ void init_lcd() { write_com(SYSTEN); //Turn on system oscillator write_com(RC256); //启动内部256KRC 振荡器 write_com(BIAS); // 1/3 bais . 4 duty write_com(LCDON); //开启LCD } //显示基本单位点,本节的核心内容。col代表X轴,X轴的数据用位来表示,一个字节中的高4位来表示。pag代表Y轴 void seg_display(unsigned char col, unsigned char pag) { pag<<=2; ht162x_cs_dr=0; //选通HT1621 _nop_(); _nop_(); SendBitToHT1621(0xA0,3); //发送写数据模式101 SendBitToHT1621(pag,6); //发送Y轴数据 SendBitToHT1621(col,4); //发送X轴数据 ht162x_cs_dr=1; _nop_(); _nop_(); } //*------------------清空屏幕的内容---------------*/ void screen_clear () { unsigned char i; unsigned char y=0; for(i=0;i<32;i++) { seg_display(0x00,y); y=y+1; } } (6)小结: 因为段码屏是一种客户定做的屏,每种屏的字库表都会不一样,因此我在这节只列出最核心的驱动程序,上层的应用程序大家以后根据项目自己编写,只要多利用查表,与(&)和或(|)这两种位运算符来处理,不难。软件设置初始化HT1621的配置参数时,要特别注意实际电路上用了多少个COM,然后设置相等的COM配置,否则,应用在大段码显示屏的项目时,有可能因为驱动力不够,会显示乱码。鸿哥在上个月的一个项目中就是被这样的问题卡住了,还好鸿哥功力深厚,仅仅用了7天就找出了问题,现在分享给大家。 (未完待续,下节更精彩,不要走开哦) |
|
|
|
|
|
本帖最后由 jianhong_wu 于 2013-2-3 12:04 编辑
第十八节:ADS7843驱动的320240电阻型触摸屏 (1) 开场白: 320240的触摸屏是由320240液晶显示屏和320240电阻触摸薄膜组成。320240液晶显示屏披上一层触摸膜的皮就是触摸屏了。显示和读取触摸信息是各自独立的,我们通过编写程序,两者有机结合起来,让客户产生错觉,以为触摸和显示是一体的。 320240液晶屏的程序在第十五节已经讲过。现在重点介绍一下电阻触摸薄膜的原理。它的本质是利用电阻分压的原理。假如我在桌面上放了一条很长的裸露电阻,我们的手触摸到电阻的某点时,就相当于可调电阻的中间移动点,按到哪一点位置,我们只要通过AD把被分压后的电压读取出来,就知道你的手按到了哪个位置。一张触摸膜相当于在X轴和Y轴都放了一个很宽很长的裸露电阻,手按到哪一点,只要把该点的X轴和Y轴的分压通过AD读取出来,就可以得到被触摸的X轴和Y轴坐标。驱动电阻型触摸屏,就相当于单片机驱动一个外部AD转换芯片,这个AD芯片就是ADS7843。 编程技巧:我们要在显示屏上先做一个显示程序,专门用来显示按下去的X轴坐标和Y轴坐标,这样方便我们记录按键的位置信息。有了具体某个按键的位置信息,我们才可以针对此按键进行后续的触发程序编写。 (2)功能需求: 在触摸屏上按下一个矩形按键,此按键马上反显,表示被触发。同时把相对应的X轴和Y轴坐标数据在液晶屏上显示出来。 (3)硬件原理: 跟320240液晶显示屏的接线请参考第十五节。然后用单片机的4个IO口分别跟ADS7843的DCLK, CS, DIN, DOUT连接。ADS7843的PENIRQ引脚可以不接悬空,如果读者想把此键盘中断请求信号也用上,请自己查看pdf文档编写相对应的程序。 (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) //cnt_key_x_lower1和cnt_key_x_upper1是X轴的触摸有效范围,cnt_key_y_lower1和cnt_key_y_upper1是Y轴的触摸有效范围, //此数据的得来,要靠我们自己编写的X轴和Y轴的坐标显示程序。 #define cnt_key_x_lower1 900 //触摸矩形按键的有效触摸范围 #define cnt_key_x_upper1 1900 #define cnt_key_y_lower1 1900 #define cnt_key_y_upper1 2100 #define cnt_key_wd 50 //被触摸的按键反显后的停留时间, //补充说明:吴坚鸿程序风格是这样的,凡是输出IO后缀都是_dr,凡是输入的//IO后缀都//是_sr,凡是数据总线后缀都是_bus #define LcmDataBus P1 //数据总线 ***it WR_dr=P3^0; //320240液晶显示屏的驱动IO口 ***it RD_dr=P3^1; ***it CS_dr = P3^5; ***it RS_dr = P3^3; ***it RES_dr = P3^4; //ads7843的驱动IO口 ***it ads7843_DCLK_dr = P2^0; //时钟信号,下降沿有效 ***it ads7843_CS_dr = P2^3; //片选信号,低电平有效 ***it ads7843_DIN_dr = P2^2; //串行数据输入 ***it ads7843_DOUT_sr = P2^1; //串行数据输出 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 draw_rec(unsigned int x,unsigned int y,unsigned int x_length,unsigned int y_length); //画矩形,用来制造矩形按键 void RevBmp(unsigned char ox,unsigned char oy,unsigned char Lengh,unsigned char High); //把选中的矩形反显 void ClearBmp(unsigned char ox,unsigned char oy,unsigned char Lengh,unsigned char High); //把选中的矩形清空内容 void ADS7843_start(); //ADS7843启动 void ADS7843_wr(unsigned char dat); unsigned int ADS7843_rd(); //读ADS7843 void key_scan(); //触摸按键扫描 void key_service(); //触摸服务程序 unsigned int average(unsigned int c[3]); //取三个数据中的中间数值 void display_data(unsigned int x,unsigned int y,unsigned char number);//显示数字函数 void init_lcd(); //初始化液晶模块 unsigned char key_lock=0; //按键自锁 unsigned char key_sec=0; //被触发的按键 unsigned int key_wd_cnt=0; //触摸按键反显后的停留延时计数器 unsigned char a[4]; unsigned char b[4]; unsigned int avex=0; unsigned int avey=0; unsigned char wd_update=1; 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 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, }; unsigned char code hz1616_zuo[]= { /*-- 文字: 坐 --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/ 0x01,0x00,0x01,0x00,0x11,0x10,0x11,0x10,0x11,0x10,0x29,0x10,0x25,0x28,0x45,0x44, 0x81,0x80,0x01,0x00,0x3F,0xF8,0x01,0x00,0x01,0x00,0x01,0x00,0xFF,0xFE,0x00,0x00, }; unsigned char code hz1616_biao[]= { /*-- 文字: 标 --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/ 0x10,0x00,0x11,0xFC,0x10,0x00,0x10,0x00,0xFC,0x00,0x13,0xFE,0x38,0x20,0x34,0x20, 0x55,0x28,0x51,0x24,0x92,0x26,0x14,0x22,0x10,0x22,0x10,0x20,0x10,0xA0,0x10,0x40, }; unsigned char code ***816_0[]= { /*-- 文字: 0 --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/ 0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00, }; unsigned char code ***816_1[]= { /*-- 文字: 1 --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/ 0x00,0x00,0x00,0x10,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00, }; unsigned char code ***816_2[]= { /*-- 文字: 2 --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/ 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x04,0x04,0x08,0x10,0x20,0x42,0x7E,0x00,0x00, }; unsigned char code ***816_3[]= { /*-- 文字: 3 --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/ 0x00,0x00,0x00,0x3C,0x42,0x42,0x04,0x18,0x04,0x02,0x02,0x42,0x44,0x38,0x00,0x00, }; unsigned char code ***816_4[]= { /*-- 文字: 4 --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/ 0x00,0x00,0x00,0x04,0x0C,0x14,0x24,0x24,0x44,0x44,0x7E,0x04,0x04,0x1E,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 ***816_6[]= { /*-- 文字: 6 --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/ 0x00,0x00,0x00,0x1C,0x24,0x40,0x40,0x58,0x64,0x42,0x42,0x42,0x24,0x18,0x00,0x00, }; unsigned char code ***816_7[]= { /*-- 文字: 7 --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/ 0x00,0x00,0x00,0x7E,0x44,0x44,0x08,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, }; unsigned char code ***816_8[]= { /*-- 文字: 8 --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/ 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x24,0x18,0x24,0x42,0x42,0x42,0x3C,0x00,0x00, }; unsigned char code ***816_9[]= { /*-- 文字: 9 --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/ 0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x26,0x1A,0x02,0x02,0x24,0x38,0x00,0x00, }; unsigned char code ***816_X[]= { /*-- 文字: X --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/ 0x00,0x00,0x00,0xE7,0x42,0x24,0x24,0x18,0x18,0x18,0x24,0x24,0x42,0xE7,0x00,0x00, }; unsigned char code ***816_Y[]= { /*-- 文字: Y --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/ 0x00,0x00,0x00,0xEE,0x44,0x44,0x28,0x28,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, }; unsigned char code ***816_maohao[]= { /*-- 文字: : --*/ /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x18,0x18,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); ClearBmp(8,120,10,18); //把选中的矩形清空内容 draw_rec(8,120,10,18); //画一个矩形表示按键,一旦触摸到此按键,此按键马上反显。 while(1) { key_scan(); //触摸按键扫描 key_service(); //按键服务程序 if(key_wd_cnt>1) //触摸反显的停留时间 { key_wd_cnt--; if(key_wd_cnt<=1) { ClearBmp(8,120,10,18); //把选中的矩形清空内容 draw_rec(8,120,10,18); //重画没有反显的按键 } } if(wd_update==1) { wd_update=0; a[0]=avex/1000; //观察当前按下的X轴坐标位置结果 a[1]=avex%1000/100; a[2]=avex%100/10; a[3]=avex%10; b[0]=avey/1000; //观察当前按下的Y轴坐标位置结果 b[1]=avey%1000/100; b[2]=avey%100/10; b[3]=avey%10; hz_display1616(7+1,44,hz1616_zuo,0); //坐 hz_display1616(9+1,44,hz1616_biao,0); //标 ***_display816(11+1,44,***816_X,0); //X ***_display816(12+1,44,***816_maohao,0); //冒号 display_data(13+1,44,a[0]); //坐标信息 display_data(14+1,44,a[1]); display_data(15+1,44,a[2]); display_data(16+1,44,a[3]); hz_display1616(21+1,44,hz1616_zuo,0); //坐 hz_display1616(23+1,44,hz1616_biao,0); //标 ***_display816(25+1,44,***816_Y,0); //Y ***_display816(26+1,44,***816_maohao,0); //冒号 display_data(27+1,44,b[0]); //坐标信息 display_data(28+1,44,b[1]); display_data(29+1,44,b[2]); display_data(30+1,44,b[3]); } } } //------------------时序延时子程序----------------------------- 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; } //-------------------从LCD中读取数据,,驱动液晶程序的一部分---------------------------- unsigned char read_data() { unsigned char Rdata; CS_dr = 0; RS_dr = 1; //读数据命令 _nop_();_nop_(); LcmDataBus = 0xff; _nop_();_nop_(); RD_dr = 0; Rdata = LcmDataBus ; RD_dr = 1; CS_dr = 1; _nop_();_nop_(); return Rdata; } //设定显示地址函数,驱动液晶程序的一部分---------------------------- 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 } } } } void draw_rec(unsigned int x,unsigned int y,unsigned int x_length,unsigned int y_length) //画矩形,用来制造矩形按键 { unsigned int i; write_com( CsrDirR ); for(i=0;i LocateXY(x,y+i); write_com( mWrite ); write_data(0x80); } write_com( CsrDirR ); for(i=0;i LocateXY(x+x_length-1,y+i); write_com( mWrite ); write_data(0x01); } write_com( CsrDirR ); LocateXY(x,y); write_com( mWrite ); for(i=0;i write_data(0xff); } write_com( CsrDirR ); LocateXY(x,y+y_length-1); write_com( mWrite ); for(i=0;i write_data(0xff); } } void RevBmp(unsigned char ox,unsigned char oy,unsigned char Lengh,unsigned char High) //把选中的矩形反显 { Uchar i,j,Y; write_com( CsrDirR ); for(i=0;i LocateXY(ox,oy+i); _nop_();_nop_(); for(j=0;j write_com(mRead); Y=~read_data(); LocateXY(ox+j,oy+i); write_com(mWrite); write_data(Y); } } } void ClearBmp(unsigned char ox,unsigned char oy,unsigned char Lengh,unsigned char High) //把选中的矩形清空内容 { Uchar i,j,Y; write_com( CsrDirR ); for(i=0;i LocateXY(ox,oy+i); _nop_();_nop_(); for(j=0;j write_com(mRead); Y=~read_data(); LocateXY(ox+j,oy+i); write_com(mWrite); write_data(0x00); //写入0x00显示数据就等于清空内容 } } } //显示数字函数 void display_data(unsigned int x,unsigned int y,unsigned char number) { switch(number) { case 0: ***_display816(x,y,***816_0,0); break; case 1: ***_display816(x,y,***816_1,0); break; case 2: ***_display816(x,y,***816_2,0); break; case 3: ***_display816(x,y,***816_3,0); break; case 4: ***_display816(x,y,***816_4,0); break; case 5: ***_display816(x,y,***816_5,0); break; case 6: ***_display816(x,y,***816_6,0); break; case 7: ***_display816(x,y,***816_7,0); break; case 8: ***_display816(x,y,***816_8,0); break; case 9: ***_display816(x,y,***816_9,0); break; } } //*------------------初始化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 ); } write_com( Scroll ); for (i=0;i<10;i++) { write_data( ParaScrTable10 ); } write_com( HdotScr ); write_data( 0 ); write_com( Ovlay ); write_data( 0x0C ); write_com( 0x60 ); //13700多出来的灰度设置 write_data( 0 ); //1bpp单色 } void ADS7843_start() //ADS7843启动 { ads7843_DCLK_dr=0; ads7843_CS_dr=1; ads7843_DIN_dr=1; ads7843_DCLK_dr=1; ads7843_CS_dr=0; } void ADS7843_wr(unsigned char dat) //写ADS7843 { unsigned char count; ads7843_DCLK_dr=0; for(count=0;count<8;count++) { dat<<=1; ads7843_DIN_dr=CY; ads7843_DCLK_dr=0; _nop_(); _nop_(); _nop_(); ads7843_DCLK_dr=1; _nop_(); _nop_(); _nop_(); } } unsigned int ADS7843_rd() //读ADS7843 { unsigned char count=0; unsigned int dat=0; for(count=0;count<12;count++) { dat<<=1; ads7843_DCLK_dr=1; _nop_();_nop_();_nop_(); //下降沿有效 ads7843_DCLK_dr=0; ads7843_DOUT_sr=1; _nop_();_nop_();_nop_(); if(ads7843_DOUT_sr) dat++; } return(dat); } void key_scan() { unsigned int XX=0,YY=0,i_n,x2[8],y2[8]; for(i_n=0;i_n<3;i_n++) //进行3次数据采集 { ADS7843_start(); delay(2); ADS7843_wr(0x90);//送控制字 10010000 即用差分方式读X坐标 delay(2); ads7843_DCLK_dr=1; _nop_(); _nop_(); _nop_(); _nop_(); ads7843_DCLK_dr=0; _nop_(); _nop_(); _nop_(); _nop_(); XX=ADS7843_rd(); //读X轴坐标 x2[i_n]=XX; ADS7843_wr(0xD0); //送控制字 11010000 即用差分方式读Y坐标 ads7843_DCLK_dr=1; _nop_(); _nop_(); _nop_(); _nop_(); ads7843_DCLK_dr=0; _nop_(); _nop_(); _nop_(); _nop_(); YY=ADS7843_rd(); //读Y轴坐标 y2[i_n]=YY; ads7843_CS_dr=1; } avex=average(x2); //X坐标数据处理,取中间数值 avey=average(y2); //Y坐标数据处理,取中间数值 if(avey==0||avey==4095) //在没有触摸的情况下,y坐标是0或者4095。 { key_lock=0; } else if(key_lock==0) { //cnt_key_x_lower1和cnt_key_x_upper1是X轴的触摸有效范围,cnt_key_y_lower1和cnt_key_y_upper1是Y轴的触摸有效范围, //此数据的得来,要靠我们自己编写的X轴和Y轴的坐标显示程序。 if(avex>=cnt_key_x_lower1&&avex<=cnt_key_x_upper1&&avey>=cnt_key_y_lower1&&avey<=cnt_key_y_upper1) { key_lock=1; key_sec=1; } wd_update=1; //显示当前坐标位置 } else //只要被触摸,马上不断显示当前坐标位置 { wd_update=1; //显示当前坐标位置 } } void key_service() { switch(key_sec) { case 1: RevBmp(8,120,10,18); //把矩形按键反显一小段时间,表示对应的按键被触发 key_wd_cnt=cnt_key_wd; //按键被触发后反显的停留时间 key_sec=0; break; } } unsigned int average(unsigned int c[3]) //取三个数据中的中间数值 { unsigned int max,min,i_t,ave=0,sum=0; max=c[0]; min=c[0]; for(i_t=0;i_t<3;i_t++) { if(min>c[i_t])min=c[i_t]; if(max } ave=(sum-min-max)/1; return ave; } (6)小结: 我今天凌晨两点发表了第十七节,今天中午马上又发表第十八节,完全出于“我每个星期至少出一节”的诺言。今天是2月3日,我今晚就要回广西老家过年了,要到2月15日才返回深圳。在广西老家这段时间不方便发帖,因此现在提前多交一个星期的“公粮”。 前天有个客户在QQ上高价找我做项目,我一看是违法的项目,就直接跟他说这个项目我做不了。他问为什么。我说我对这个项目不感兴趣。他说他出高价。我说我不差钱。然后直接把他的QQ拉入黑名单。违法的项目千万不能做,这是鸿哥的原则。 昨天又有个新客户给我打电话找我做项目,这个项目不涉及法律问题。我就跟他说我明天晚上要回广西老家过年,不“接客”了。他说小伙子有生意都不做,那过完年后有没有时间。我说我的档期都排到下个月30号了,真的没有时间。他在电话那边感叹,真羡慕你们搞电子开发的,找了很多工程师都没空,有经验的工程师供不应求。 年终总结:总的来说,今年比去年有所进步,无论是技术还是收入都比去年有所提高,要是央视记者来采访我“你幸福吗?”,我会告诉他我很幸福。 (未完待续,下节更精彩,不要走开哦) |
|
|
|
|
|
鸿哥,我觉得你可以出一本书,可以包含你的一些项目经验、编程方法技巧等,绝对畅销!
|
|
|
|
|
|
|
|
|
|
只有小组成员才能发言,加入小组>>
求解外围电路实现的是4脚给持续低电平复位并正常工作,高电平不工作的原因
2076 浏览 1 评论
3489 浏览 3 评论
PIC1946程序有一个变量在运行过程中恢复初始值其他变量保持不变
2329 浏览 2 评论
2754 浏览 0 评论
PIC16F1825的RC5引脚,在主程序中操作无效,在中断中可以改变是为什么?
4012 浏览 5 评论
960浏览 0评论
用XC8编译PIC18F25K80时提示下面Error,求怎么解决这个问题
6345浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-24 02:05 , Processed in 0.946767 second(s), Total 90, Slave 80 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号