本帖最后由 caizhiwei 于 2015-11-5 11:04 编辑
虽然很久之前(51时代)就开始接触lcd12864,如今在工控机里面,LCD12864还是应用比较普遍的!
我用的lcd12864类型为串行接口,3.3V st7920
代码优化说明:
1.修复了字符串,汉字串不能自动换行的bug
注意:
1.在使用带jtag接口的I/O时要特别注意
PA13:SWDIO/JTAG_TMS
PA14:SWCLK/JTAG_TCK
PA15:JTAG_TDI
PB3:JTAG_TDO
PB4:JTAG_RST
硬件设计缺陷:
1.没有引出LCM的复位引脚,导致偶尔显示不正常之后,mcu复位(LCM并没有复位)
也无法解决,只能强行断电重启。
2.BLK液晶背光引脚的输入电流至少在20mA以上,没有用三极管驱动,而是直接用IO驱动,
需要较大的驱动电流。
3.
编译器缺陷:
1.由于使用的是iar6.70版本,编译器在编译汉字串数组的时候可能会使带字库液晶产生乱码。
所以在有汉字数组的C文件中统一使用简体中文(GB2312)(全选--右键--Charracter Encoding)
部分硬件结构说明:
1.按键按下,(上连接VCC)连接电阻下拉到地,检测IO连接上端,检测到高电平。
2.lcd12864底板反面接线图:
从反面看:
5V RW GND GND LED K2 K4 GND
GND RS E BLK GND K1 K3 5V
2015-6-10 原工程代码在23楼!|r
2015-7-12 程序更新了,,代码在35楼!
更新记录:
1.增加了24*32大字体显示功能;
2.增加了16*32大字体显示功能;
3.优化了读LCD忙的代码;
4.新增了是sprintf的任意位数数字直接显示;
5.新增了CGRAM的写入,读出操作函数;
6.优化了绘图GDRAM函数的操作,绘图速度提高;
2015.11.04 ,看到很多评论说链接失效,现在重新找了一份完整的工程代码,整理之后传到网盘:
这个代码优化了.h文件中的宏定义,方便用户移植,C文件和gui.c文件均不用修改。
https://pan.baidu.com/s/1pJw3wHd
-
- #include "gui.h"
- /*******************************************************************************
- DDRAM地址
- 0x80 0x81 0x82 0x83 0x84 0x85 0x86 0x87 //第一行汉字位置
- 0x90 0x91 0x92 0x93 0x94 0x95 0x96 0x97 //第二行汉字位置
- 0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f //第三行汉字位置
- 0x98 0x99 0x9a 0x9b 0x9c 0x9d 0x9e 0x9f //第四行汉字位置
- *******************************************************************************/
- /*******************************************************************************
- * 名称 : LCD_SetPos
- * 功能 : 设定显示位置
- * 输入 : x (0~3)行
- y (0~7)列
- * 输出 : 无
- *******************************************************************************/
- void LCD_SetPos(u8 row, u8 col)
- {
- u8 pos;
- if( row == 0)
- row = 0x80;
- else if(row == 1)
- row = 0x90;
- else if(row == 2)
- row = 0x88;
- else if(row == 3)
- row = 0x98;
- pos = row + col;
- LCD_WriteCMD(pos);//在写入数据前先指定显示地址
- delay_us(10);
- }
- /********************************************************************
- * 名称 : ShowASCII
- * 功能 : 在当前坐标位置显示单个字符
- * 输入 : *s
- * 输出 : 无
- ***********************************************************************/
- void ShowASCII(u8 i)
- {
- LCD_WriteDATA(i);
- }
-
- void ShowCharPos(u8 row, u8 col,u8 dat)
- {
- LCD_SetPos(row, col);
- ShowASCII(dat);
- }
- /*******************************************************************************
- * 名称 : ShowEnString(u8 *s)
- * 功能 : 显示英文字符串
- * 输入 : *s
- * 输出 : 无
- *******************************************************************************/
- void ShowString(u8 *s)
- {
- u8 i = 0;
- while(s[i] != '\0')
- {
- ShowASCII(s[i++]);
- }
- }
- void ShowStringPos(u8 row, u8 col,u8 *s) //col is full char wide
- {
- u8 i = 0;
- LCD_SetPos(row, col);
- while(s[i] != '\0')
- {
- ShowASCII(s[i++]);
- if((2*col+i)%(16)==0) //must 16, is OK
- {
- LCD_SetPos(++row,0); //display start at next row.
- }
-
- }
- }
- /*******************************************************************************
- * 名称 : ShowGB
- * 功能 : 显示单个汉字
- * 输入 : i
- * 输出 : 无
- ********************************************************************************/
- void ShowGB( unsigned char *HZ)
- {
- LCD_WriteDATA(HZ[0]); //写入汉字的高八位数据
-
- LCD_WriteDATA(HZ[1]); //写入汉字的低八位数据
-
- }
- void ShowGBPos(u8 row, u8 col, u8 *HZ)
- {
- LCD_SetPos(row, col);
- ShowGB(HZ);
- }
- /********************************************************************
- * 名称 : ShowGBStringPos
- * 功能 : 显示多个汉字
- * 输入 : u8 row, u8 col :汉字串的起始地址
- * 输出 : 无
- * 说明 : 自动换行:lcm默认换行顺序是乱的,0--2--1--3--0
- ***********************************************************************/
- void ShowGBStringPos(u8 row, u8 col, u8 *s)
- {
- u8 i = 0;
- LCD_SetPos(row, col);
- while (s[i] != '\0')
- {
- ShowGB(s+i);
- i+=2;
- if((2*col+i)%(16)==0) //如果满一行
- {
- LCD_SetPos(++row,0); //重新设置显示的起始地址
- }
-
- }
- }
- /*******************************************************************************
- 测试函数
- Function: 用户移植程序之后,用该函数测试液晶是否初始化成功!
- ********************************************************************************/
- void LCD_Test(void)
- {
- ShowCharPos(0,0,0x10); //右箭头
- ShowCharPos(1,0,0x10); //右箭头
- ShowString("Hello,world!") ;
- ShowCharPos(2,0,0x10); //右箭头
- ShowASCII(0x11);//左箭头
- }
-
- //自定义字符写入CGRAM
- void Write_USR_CGRAM(u8 data1,u8 data2,u8 addr)
- {
- u8 i;
- for(i=0;i<16;)
- {
- LCD_WriteCMD(addr+i); //设定CGRAM地址
- LCD_WriteDATA(data1);
- LCD_WriteDATA(data1);
- i++;
- LCD_WriteCMD(addr+i); //设定CGRAM地址
- LCD_WriteDATA(data2);
- LCD_WriteDATA(data2);
- i++;
- }
- }
- //显示自定义的字符,并把这个字符填满全屏16*16
- void Show_USR_CGRAM_Char(u8 addr,u8 i)
- {
- u8 j;
- for(j=0;j<0x20;)
- {
- LCD_WriteCMD(addr+j); //设定DDRAM地址
- LCD_WriteDATA(0x00);
- LCD_WriteDATA(i);
- j++;
- }
- }
- //写入GDRAM 绘图,Y是Y绘图坐标,2个字节一行,X是图形起始坐标,CLONG是图形长度,以字节
- //为单位;HIGHT是图形高度,TAB是图形数据表.12864M的图形显示范围是256*32点阵.
- //要在12864M里显示全屏,取模时一幅图横切成两半
- /*
- ST7920提供64×32 个字节的空间(由扩充指令设定绘图RAM 地址),最多可以控制256×64
- 点阵的二维绘图缓冲空间,在更改绘图RAM时,由扩充指令设置GDRAM地址先垂直地址后水平
- 地址(连续2个字节的数据来定义垂直和水平地址),再2个字节的数据给绘图RAM(先高8位
- 后低8 位)
- */
- void WRGDRAM(u8 Y,u8 clong,u8 hight,u8 *TAB1)
- {
- u16 k=0;
- u8 j;
- u8 i;
- LCD_WriteCMD(0x34);
- LCD_WriteCMD(0x36);
- for(j=0;j<hight;)
- {
- LCD_WriteCMD(Y+j);
- LCD_WriteCMD(0x80);//X坐标
- for(i=0;i<clong;i++)//
- {
- LCD_WriteDATA(TAB1[k]);
- k++;
- }
- j++;
- }
- }
- /********************************************************************
- * 名称 : ShowBlankPos
- * 功能 : 在当前坐标位置显示单个字符
- * 输入 : num 半宽字符的个数
- * 功能 : 黑板擦功能,擦除不显示的内容
- ***********************************************************************/
- void ShowBlankPos(u8 row, u8 col, u8 num)
- {
- u8 i ;
- LCD_SetPos(row,col);
- for (i = 0; i < num;i++)
- LCD_WriteDATA(0x20); //写空格
- }
复制代码 上图:
Hellokity:
|
点评
需要创建一个屏幕大小的缓冲区数组,将要显示的字模数据放入数组里面,后面再使用绘图模式,统一将数组刷上去就可以实现了
是的,多了一个字母~~
这个是3.3V的屏,很好驱动的撒,这个是标准屏,目前还是用的很广的
还是没有花羊羊好看吧!!!