基于小凌派RK2206开发板LCD液晶
一、简介
LCD的应用很广泛,简单如手表上的液晶显示屏,仪表仪器上的液晶显示器或者是电脑笔记本上的液晶显示器,都使用了LCD。在一般的办公设备上也很常见,如传真机,复印机,以及一些娱乐器材玩具等也常常见到LCD的足迹。
本小节使用的是STV,用于单片驱动K色图像TFT-LCD,包含(*3色)x线输出,可以直接以SPI协议,或者8位/9位/16位/18位并行连接外部控制器。STV显示数据存储在片内xx18bits内存中,显示内存的读写不需要外部时钟驱动。
接下来先看本案例的实际操作视频。
二、硬件电路设计
模块整体硬件电路如图1所示,电路中包含了电源电路、液晶接口以及小凌派-RK开发板连接的相关引脚。
图1硬件电路图其中,液晶屏STV的相关引脚资源如图2所示。
图2液晶屏STV硬件资源示意图其中,LCD液晶屏引脚功能描述,如下表1所示。
表1LCD液晶屏引脚功能表
其中,LCD液晶屏与小凌派-RK开发板连接如图3所示。
图32.4寸液晶屏和小凌派-RK开发板三、软件设计
本章节将利用小凌派-RK开发板上的GPIO和SPI接口方式来点亮2.4寸液晶屏,并实现ASCII字符的显示及汉字的显示。
1.主程序设计
如图4所示为LCD液晶屏主程序流程图,开机LiteOS系统初始化后,进入主程序。主程序首先进行GPIO和SPI总线初始化,然后配置LCD液晶屏设备,最后进入循环中。在循环中,主程序控制SPI对LCD液晶屏进行ASCII字符和汉字显示。
图4主程序流程图2.LCD初始化程序设计
LCD初始化程序主要分为GPIO和SPI总线初始化,配置LCD两部分。
其中,GPIO初始化首先用LzGpioInit()函数将GPIO0_PC3初始化为GPIO引脚,然后用LzGpioSetDir()将引脚设置为输出模式,最后调用LzGpioSetVal()输出低电平。
/*初始化GPIO0_C3*/
LzGpioInit(LCD_PIN_RES);
LzGpioSetDir(LCD_PIN_RES,LZGPIO_DIR_OUT);
LzGpioSetVal(LCD_PIN_RES,LZGPIO_LEVEL_HIGH);
/*初始化GPIO0_C6*/
LzGpioInit(LCD_PIN_DC);
LzGpioSetDir(LCD_PIN_DC,LZGPIO_DIR_OUT);
LzGpioSetVal(LCD_PIN_DC,LZGPIO_LEVEL_LOW);
SPI初始化首先用SpiIoInit()函数将GPIO0_PC0复用为SPI0_CS0n_M1,GPIO0_PC1复用为SPI0_CLK_M1,GPIO0_PC2复用为SPI0_MOSI_M1。其次调用LzI2cInit()函数初始化SPI0端口。
LzSpiDeinit(LCD_SPI_BUS);
if(SpiIoInit(m_spiBus)!=LZ_HARDWARE_SUCCESS){
printf("%s,%d:SpiIoInitfailed!\n",__FILE__,__LINE__);
return__LINE__;
}
if(LzSpiInit(LCD_SPI_BUS,m_spiConf)!=LZ_HARDWARE_SUCCESS){
printf("%s,%d:LzSpiInitfailed!\n",__FILE__,__LINE__);
return__LINE__;
}
配置LCD主要是配置STV的工作模式,具体代码如下所示:
/*重启lcd*/
LCD_RES_Clr();
LOS_Msleep();
LCD_RES_Set();
LOS_Msleep();
LOS_Msleep();
lcd_wr_reg(0x11);
/*等待LCDms*/
LOS_Msleep();
/*启动LCD配置,设置显示和颜色配置*/
lcd_wr_reg(0X36);
if(USE_HORIZONTAL==0)
{
lcd_wr_data8(0x00);
}
elseif(USE_HORIZONTAL==1)
{
lcd_wr_data8(0xC0);
}
elseif(USE_HORIZONTAL==2)
{
lcd_wr_data8(0x70);
}
else
{
lcd_wr_data8(0xA0);
}
lcd_wr_reg(0X3A);
lcd_wr_data8(0X05);
/*STS帧刷屏率设置*/
lcd_wr_reg(0xb2);
lcd_wr_data8(0x0c);
lcd_wr_data8(0x0c);
lcd_wr_data8(0x00);
lcd_wr_data8(0x33);
lcd_wr_data8(0x33);
lcd_wr_reg(0xb7);
lcd_wr_data8(0x35);
/*STS电源设置*/
lcd_wr_reg(0xbb);
lcd_wr_data8(0x35);
lcd_wr_reg(0xc0);
lcd_wr_data8(0x2c);
lcd_wr_reg(0xc2);
lcd_wr_data8(0x01);
lcd_wr_reg(0xc3);
lcd_wr_data8(0x13);
lcd_wr_reg(0xc4);
lcd_wr_data8(0x20);
lcd_wr_reg(0xc6);
lcd_wr_data8(0x0f);
lcd_wr_reg(0xca);
lcd_wr_data8(0x0f);
lcd_wr_reg(0xc8);
lcd_wr_data8(0x08);
lcd_wr_reg(0x55);
lcd_wr_data8(0x90);
lcd_wr_reg(0xd0);
lcd_wr_data8(0xa4);
lcd_wr_data8(0xa1);
/*STSgamma设置*/
lcd_wr_reg(0xe0);
lcd_wr_data8(0xd0);
lcd_wr_data8(0x00);
lcd_wr_data8(0x06);
lcd_wr_data8(0x09);
lcd_wr_data8(0x0b);
lcd_wr_data8(0x2a);
lcd_wr_data8(0x3c);
lcd_wr_data8(0x55);
lcd_wr_data8(0x4b);
lcd_wr_data8(0x08);
lcd_wr_data8(0x16);
lcd_wr_data8(0x14);
lcd_wr_data8(0x19);
lcd_wr_data8(0x20);
lcd_wr_reg(0xe1);
lcd_wr_data8(0xd0);
lcd_wr_data8(0x00);
lcd_wr_data8(0x06);
lcd_wr_data8(0x09);
lcd_wr_data8(0x0b);
lcd_wr_data8(0x29);
lcd_wr_data8(0x36);
lcd_wr_data8(0x54);
lcd_wr_data8(0x4b);
lcd_wr_data8(0x0d);
lcd_wr_data8(0x16);
lcd_wr_data8(0x14);
lcd_wr_data8(0x21);
lcd_wr_data8(0x20);
lcd_wr_reg(0x29);
3.LCD的点数据设计
STV采用SPI通信方式,数据传输协议如下:
4-LineSerialInterface=16-bit/pixel(RGB5-6-5-bitinput),65K-Color,3Ah="05h"
数据传输时序图如图5所示。
图5STV液晶屏SPI数据传输时序图
也就是每个像素占用2个字节,RGB为5+6+5。因此,往LCD液晶屏发送某一个像素信息的程序如下所示:
staticvoidlcd_write_bus(uint8_tdat)
{
LzSpiWrite(LCD_SPI_BUS,0,dat,1);
}
staticvoidlcd_wr_data(uint16_tdat)
{
lcd_write_bus(dat8);
lcd_write_bus(dat);
}
staticvoidlcd_wr_reg(uint8_tdat)
{
LCD_DC_Clr();
lcd_write_bus(dat);
LCD_DC_Set();
}
staticvoidlcd_address_set(uint16_tx1,uint16_ty1,uint16_tx2,uint16_ty2)
{
/*列地址设置*/
lcd_wr_reg(0x2a);
lcd_wr_data(x1);
lcd_wr_data(x2);
/*行地址设置*/
lcd_wr_reg(0x2b);
lcd_wr_data(y1);
lcd_wr_data(y2);
/*储存器写*/
lcd_wr_reg(0x2c);
}
staticvoidlcd_wr_data(uint16_tdat)
{
lcd_write_bus(dat8);
lcd_write_bus(dat);
}
voidlcd_draw_point(uint16_tx,uint16_ty,uint16_tcolor)
{
/*设置光标位置*/
lcd_address_set(x,y,x,y);
lcd_wr_data(color);
}
4.LCD的ASCII字符显示设计
预先将规定字号的ASCII字符的LCD液晶屏像素信息存放于在lcd_font.h源代码文件中。该表格依照ASCII的数值来存放像素信息。例如:空格的ASCII数值是0x0,则程序将像素放到第一行像素中,如下源代码所示。
/*12*6的ASCII码显示*/
constunsignedcharascii_[][12]=
{
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"",0*/
{0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x00,0x00,0x04,0x00,0x00},/*"!",1*/
{0x14,0x14,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",2*/
{0x00,0x00,0x0A,0x0A,0x1F,0x0A,0x0A,0x1F,0x0A,0x0A,0x00,0x00},/*"#",3*/
{0x00,0x04,0x0E,0x15,0x05,0x06,0x0C,0x14,0x15,0x0E,0x04,0x00},/*"$",4*/
.......
};
/*16*8的ASCII码显示*/
constunsignedcharascii_[][16]=
{
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"",0*/
{0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x18,0x18,0x00,0x00},/*"!",1*/
{0x00,0x48,0x6C,0x24,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",2*/
{0x00,0x00,0x00,0x24,0x24,0x24,0x7F,0x12,0x12,0x12,0x7F,0x12,0x12,0x12,0x00,0x00},/*"#",3*/
......
};
/*24*12的ASCII码显示*/
constunsignedcharascii_[][48]=
{
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"",0*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
{0x00,0x00,0x00,0x00,0x60,0x06,0x60,0x06,0x30,0x03,0x98,0x01,0x88,0x00,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",2*/
......
};
当需要将某一个字号的ASCII字符投射到LCD液晶屏时,程序根据字号大小找到对应的字号的ASCII字符像素表,然后根据ASCII字符的数值找到对应的像素行,最后将该像素行数据依次通过SPI总线发送给LCD液晶屏。如下源代码所示。
voidlcd_show_char(uint16_tx,uint16_ty,uint8_tnum,uint16_tfc,uint16_tbc,uint8_tsizey,uint8_tmode)
{
uint8_ttemp,sizex,t,m=0;
uint16_ti;
uint16_tTypefaceNum;//一个字符所占字节大小
uint16_tx0=x;
sizex=sizey/2;
TypefaceNum=(sizex/8+((sizex%8)?1:0))*sizey;
/*得到偏移后的值*/
num=num-;
/*设置光标位置*/
lcd_address_set(x,y,x+sizex-1,y+sizey-1);
for(i=0;iTypefaceNum;i++)
{
if(sizey==12)
{
/*调用6x12字体*/
temp=ascii_[num][i];
}
elseif(sizey==16)
{
/*调用8x16字体*/
temp=ascii_[num][i];
}
elseif(sizey==24)
{
/*调用12x24字体*/
temp=ascii_[num][i];
}
elseif(sizey==32)
{
/*调用16x32字体*/
temp=ascii_[num][i];
}
else
{
return;
}
for(t=0;t8;t++)
{
if(!mode)
{/*非叠加模式*/
if(temp(0x01t))
{
lcd_wr_data(fc);
}
else
{
lcd_wr_data(bc);
}
m++;
if(m%sizex==0)
{
m=0;
break;
}
}
else
{/*叠加模式*/
if(temp(0x01t))
{
/*画一个点*/
lcd_draw_point(x,y,fc);
}
x++;
if((x-x0)==sizex)
{
x=x0;
y++;
break;
}
}
}
}
}
5.LCD的汉字显示设计
同上原理,程序将某一个特定字号的汉字信息存放于一个数据结构体数组中。该数据结构体包含字体编码Index和像素数据Msk。具体原代码如下所示。
/*定义中文字符12*12*/
typedefstruct
{
unsignedcharIndex[2];
unsignedcharMsk[24];
}typFNT_GB12;
/*定义中文字符16*16*/
typedefstruct
{
unsignedcharIndex[2];
unsignedcharMsk[32];
}typFNT_GB16;
/*定义中文字符24*24*/
typedefstruct
{
unsignedcharIndex[2];
unsignedcharMsk[72];
}typFNT_GB24;
......
通过汉字像素软件将对应的汉字和像素存放于lcd_font.h文件中。具体源代码如下所示。
consttypFNT_GB12tfont12[]=
{
"小",0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x24,0x01,0x24,0x02,0x22,0x02,0x22,0x04,
0x21,0x04,0x20,0x00,0x20,0x00,0x38,0x00,/*"小"*/
"凌",0x40,0x00,0xF9,0x03,0x42,0x00,0xFC,0x07,0x10,0x01,0x28,0x02,0xE0,0x01,0x14,0x01,
0xAA,0x00,0x41,0x00,0xB0,0x01,0x0C,0x06,/*"凌"*/
"派",0x00,0x03,0xF2,0x00,0x14,0x02,0xD0,0x01,0x51,0x01,0x52,0x05,0x50,0x03,0x50,0x01,
0x54,0x01,0x52,0x02,0xD1,0x02,0x48,0x04,/*"派"*/
};
consttypFNT_GB16tfont16[]=
{
"小",0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x88,0x08,0x88,0x10,0x88,0x20,
0x84,0x20,0x84,0x40,0x82,0x40,0x81,0x40,0x80,0x00,0x80,0x00,0xA0,0x00,0x40,0x00,/*"小",0*/
"凌",0x00,0x02,0x02,0x02,0xC4,0x1F,0x04,0x02,0x00,0x02,0xE0,0x7F,0x88,0x08,0x48,0x11,
0x24,0x21,0x87,0x0F,0xC4,0x08,0x24,0x05,0x04,0x02,0x04,0x05,0xC4,0x08,0x30,0x30,/*"凌",1*/
"派",0x00,0x10,0x04,0x3C,0xE8,0x03,0x28,0x00,0x21,0x38,0xA2,0x07,0xA2,0x04,0xA8,0x44,
0xA8,0x24,0xA4,0x14,0xA7,0x08,0xA4,0x08,0xA4,0x10,0x94,0x22,0x94,0x41,0x88,0x00,/*"派",2*/
};
......
当程序需要将某一个特定字号的汉字投射到LCD液晶屏时,程序就根据对应的字号查找对应字号的tfontXX数组,并将对应的像素行数据发送给LCD液晶屏。具体源代码如下所示。
voidlcd_show_chinese(uint16_tx,uint16_ty,uint8_t*s,uint16_tfc,uint16_tbc,uint8_tsizey,uint8_tmode)
{
uint8_tbuffer[];
uint32_tbuffer_len=0;
uint32_tlen=strlen(s);
memset(buffer,0,sizeof(buffer));
/*utf8格式汉字转化为ascii格式*/
chinese_utf8_to_ascii(s,strlen(s),buffer,buffer_len);
for(uint32_ti=0;ibuffer_len;i+=2,x+=sizey)
{
if(sizey==12)
{
lcd_show_chinese_12x12(x,y,buffer[i],fc,bc,sizey,mode);
}
elseif(sizey==16)
{
lcd_show_chinese_16x16(x,y,buffer[i],fc,bc,sizey,mode);
}
elseif(sizey==24)
{
lcd_show_chinese_24x24(x,y,buffer[i],fc,bc,sizey,mode);
}
elseif(sizey==32)
{
lcd_show_chinese_32x32(x,y,buffer[i],fc,bc,sizey,mode);
}
else
{
return;
}
}
}
四、编译过程
1、打开sdk下面路径的文件
/vendor/lockzhiner/rk/samples/b4_lcd/lcd_example.c
注意:Gitee已有相关源代码,请大家根据上述的需求修改相关源代码。
网址:
转载请注明:http://www.abuoumao.com/hyls/2428.html