看完这些链接就完全懂了
LCD字符显示
字库创建
字模
lcd显示bmp图片程序
lcd显示图片
字符编码
字符编码
12864显示汉字 通过区位码
12864显示汉字 单片机程序
12864手册
lcd显示点阵 单片机程序
lcd显示点阵 单片机程序2
lcd显示点阵图片
LCD12864串行和并行显示
12864LCD管脚定义及相关资料
显示图片
显示字符和图片
混合显示汇总
字模生成软件
公司要用LCD屏显示希伯来语,这个以前是显示汉字的。直接试了一下,乱码了。查了下需要字库,因为汉字和希伯来语的编码方式是不同的。
学了下字符编码,最早的计算机字符编码是美国的ASCII编码,中文做了一个扩展是GB2312,支持九千多个汉字,后来再次扩展为GB18030,支持三万多个汉字和其他字符、繁体。欧洲是ISO8859和unicode编码,最后国际上兼容所以字符的UTF-8,UTF-16编码。
由于是嵌入式开发,用的是ANSI编码的GB2312的格式,LCD是12864型号的,仅有一个汉字字库扩展。显示汉字是用的区位码进行显示的(获取区位码,进字库查找,显示)。
后来找到了用图片显示的方法,画图,转格式,取字模,显示。这个方法就能显示图片了,也能通过这个来显示二维码。这个就比显示汉字要好许多。
LCD12864屏分为四行从上到下,从左到右显示图片,取字模也得按照这个方向取,不然显示的图片就不一样。
后来想做一个上半屏显示图片,下半屏通过字库显示时间(变化的数字),试了一下发现会相互冲掉。查了下是LCD12864这款屏在显示图片时是以画图板的模式来显示的,这会重新绘制整个屏幕所以冲掉了数字,哪怕没对那半边屏进行写入操作也会造成丢失。最后采取了切换显示的方式。
下面是代码
头文件部分:LCD12864指令表
//每行的首地址,基于RT12864-4M型液晶
#define LINE_ONE_ADDRESS 0x80
#define LINE_TWO_ADDRESS 0x90
#define LINE_THREE_ADDRESS 0x88
#define LINE_FOUR_ADDRESS 0x98
//LCD12864指令表
#define LCD12864_Clr 0x01 //清除显示屏幕,把DDRAM位址计算器调整为"00H"
#define LCD12864_Back 0x02 //把DDRAM位址计数器调整为"00H",游标回原点,该功能不影响显示DDRAM
#define LCD12864_Left 0x05 //整体显示移动,光标左移
#define LCD12864_Right 0x07 //整体显示移动,光标右移
#define LCD12864_OFF 0x08 //整体显示关闭
#define LCD12864_ON 0x0C //整体显示打开,游标关闭
#define LCD12864_ON_1 0x0E //整体显示打开,游标打开
#define LCD12864_ON_2 0x0F //整体显示打开,游标打开,游标位置显示闪烁
#define LCD12864_DisMov_Left 0x18 //整体显示左移动,光标跟随移动,AC值不变
#define LCD12864_DisMov_Right 0x1C //整体显示左移动,光标跟随移动,AC值不变
#define LCD12864_8Bit 0x30 //基本指令集动作,8位数据模式
#define LCD12864_Praint_OFF 0x34 //扩充指令集动作,关闭绘图显示
#define LCD12864_Praint_ON 0x36 //扩充指令集动作,打开绘图显示
#define LCD12864_SetCGRAM 0x40 //设定CGRAM位址到位址计算器(AC)(40H-7FH)
#define LCD12864_SetGDRAM 0x80 //设定GDRAM位址到位址计数器(AC)(80H-FFH)
#define LCD12864_TurnWhite13 0x04 //选择1,3行同时反白显示
#define LCD12864_TurnWhite24 0x05 //选择2,4行同时反白显示
//基本指令集预定义
#define LCD_DATA 1 //数据位
#define LCD_COMMAND 0 //命令位
#define LCD_CLEAR_SCREEN 0x01 //清屏
#define LCD_ADDRESS_RESET 0x02 //地址归零
#define LCD_BASIC_FUNCTION 0x30 //基本指令集
#define LCD_EXTEND_FUNCTION 0x34 //扩充指令集
//扩展指令集预定义
#define LCD_AWAIT_MODE 0x01 //待命模式
#define LCD_ROLLADDRESS_ON 0x03 //允许输入垂直卷动地址
#define LCD_IRAMADDRESS_ON 0x02 //允许输入IRAM地址
#define LCD_SLEEP_MODE 0x08 //进入睡眠模式
#define LCD_NO_SLEEP_MODE 0x0c //脱离睡眠模式
#define LCD_GRAPH_ON 0x36 //打开绘图模式
#define LCD_GRAPH_OFF 0x34 //关闭绘图模式
#define LCD12864_Praint_OFF 0x34 //扩充指令集动作,关闭绘图显示
#define LCD12864_Praint_ON 0x36 //扩充指令集动作,打开绘图显示
#define LCD12864_8Bit 0x30 //基本指令集动作,8位数据模式
#define LCD_YouBiao_ON 0x0f //游标打开
#define LCD_YouBiao_OFF 0x0
#define LCD_MoveYB_WithDis 0x1d //光标向右移动的同时真个屏幕的显示的内容一起向右移动
#define LCD_MoveYB_WithOutDIs 0x14 //只将光标向右移动
和前面不同的点是写入端口driver_lcd_send_byte();
前面例子都是通过sbit进行DB位操作,这个是通过set和reset操作rw位,
//显示图片
void application_dmp_display(uint8_t addr,uint8_t * dmp)
{
uint8_t x,y;
driver_lcd_gpio_initial();
driver_lcd_write_command(LCD12864_Praint_ON);
for(y=0;y<16;y++)
{
driver_lcd_write_command(START_ROW+y); //Y
driver_lcd_write_command(addr); //X addr=0x80
for(x=0;x<16;x++)
{
driver_lcd_write_data(*dmp++);
}
}
}
//写指令
void driver_lcd_write_command(u8 cmdcode)
{
LCD_RS_H;
driver_lcd_send_byte(0xf8);
driver_lcd_send_byte(cmdcode & 0xf0);
driver_lcd_send_byte((cmdcode << 4) & 0xf0);
driver_delay_xus(100);
LCD_RS_L;
}
//写数据
void driver_lcd_write_data(u8 Dispdata)
{
LCD_RS_H;
driver_lcd_send_byte(0xfa); //11111,RW(0),RS(1),0
driver_lcd_send_byte(Dispdata & 0xf0); //显示字模的高四位
driver_lcd_send_byte((Dispdata << 4) & 0xf0);//显示字模的低四位
driver_delay_xus(100);
LCD_RS_L;
}
//发送数据到端口
void driver_lcd_send_byte(uint8_t data)
{
uint8_t i;
for(i = 0; i < 8; i++)
{
if((data << i) & 0x80) //生成字模后,取其每位
LCD_RW_H; //若当前位为1,则点亮
else
LCD_RW_L; //若当前位为0,则不点亮
LCD_EN_H; //导入EN位
LCD_EN_L;
}
}
//端口初始化
void driver_lcd_gpio_initial(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = LCD_RESET_PIN | LCD_BACKGROUND_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LCD_RESET_BK_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = LCD_PSB_PIN | LCD_E_PIN | LCD_RW_PIN | LCD_RS_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LCD_CONTROL_PORT, &GPIO_InitStructure);
/* LCD的有效复位 */
GPIO_ResetBits(LCD_RESET_BK_PORT, LCD_RESET_PIN);
driver_delay_xms(100);
GPIO_SetBits(LCD_RESET_BK_PORT, LCD_RESET_PIN);
driver_delay_xms(10);
GPIO_SetBits(LCD_RESET_BK_PORT, LCD_BACKGROUND_PIN); //开背光灯
GPIO_ResetBits(LCD_CONTROL_PORT, LCD_PSB_PIN); // 并行工作模式选择 PSB=H
}
//初始化以显示字符模式
void driver_lcd_initial(void)
{
driver_lcd_gpio_initial();
driver_delay_xms(100);
driver_lcd_write_command(LCD12864_8Bit); //基本指令集
driver_delay_xus(50);
driver_lcd_write_command(LCD12864_Back); //地址归位
driver_delay_xus(50);
driver_lcd_write_command(LCD12864_ON); //打开显示,关闭游标
driver_delay_xus(50);
driver_lcd_write_command(LCD12864_Clr); //清除显示
driver_delay_xus(50);
driver_lcd_write_command(0x06); //游标右移
driver_delay_xus(50);
driver_lcd_write_command(START_ROW); //设定显示的起始地址
driver_delay_xus(50);
}
//每行显示字符
void driver_lcd_display_row(uint8_t row, char *ptr)
{
uint8_t row_address = 0x00;
uint8_t len= strlen(ptr);
uint8_t i=0;
switch(row)
{
case 1:
row_address = ROW_1;
break; //第一行首地址
case 2:
row_address = ROW_2;
break; //第二行首地址
case 3:
row_address = ROW_3;
break; //第三行首地址
case 4:
row_address = ROW_4;
break; //第四行首地址
default:return;
}
driver_lcd_write_command(row_address);
for(i=0;iBSRR = GPIO_Pin;
}
//复位
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));
GPIOx->BRR = GPIO_Pin;
}
这是原理图部分