一、基础条件
1、3.5寸TFT单色液晶点阵屏。
2、驱动芯片ST7512(该款芯片网上资源不多)。
3、飞思卡尔16位单片机。
二、编译环境
CodeWarrior IDE,带专业模式,方便初始化引脚。
此实例中,仅用到了GPIO功能,故以单个引脚为例,进行初始化。专业版编译器很方便,根据提示设置参数,即可完成,设置完引脚号之后第一个参数为设置电阻,第二个参数为设置输入输出方式(推挽和开漏),第三个参数为输入输出设置,其余参数为初始化时,引脚的默认状态。
三、通讯方式
ST7512支持三种不同的通讯方式:
1、8-bit parallel bi-directional interface with 6800 and 8080
2、4-line SPI
3、3-line SPI
在此项目中,使用第一种方式,以8080通讯协议进行单片机和显示屏之间的数据交换。
8080协议所需的接线方式
四、通讯协议介绍
8080协议通讯支持读写,但不可同时进行,读写时,单片机的引脚状态如下图所示 此实例希望显示屏按照控制器要求显示,故重点为向芯片写数据 ,通讯时序见下图
废话不多说,直接上代码:
#define lcd_cmd 0
#define lcd_dat 1
void GPIO_data(uint16 id,uint16 data) //设置每个引脚的高低电平状态
{
if(id==0)
d0_PutVal(data);
else if(id==1)
d1_PutVal(data);
else if(id==2)
d2_PutVal(data);
else if(id==3)
d3_PutVal(data);
else if(id==4)
d4_PutVal(data);
else if(id==5)
d5_PutVal(data);
else if(id==6)
d6_PutVal(data);
else if(id==7)
d7_PutVal(data);
}
void OLED_Data_Out(uint16 data)//16进制数据逐位解析至每个引脚
{
uint8 i;
for(i=0;i<=7;i++)
GPIO_data(i,((data >> i) & 0x01));
}
void OLED_WR_Byte(uint16 dat, uint16 cmd)//8080协议写数据
{
CS_PutVal(0);
RD_PutVal(1);
DC_PutVal(cmd);
OLED_Data_Out(dat);
WR_PutVal(0);
delay_us(1);
WR_PutVal(1);
delay_us(1);
CS_PutVal(1);
}
以上,在写入数据时,只需要调用LCD_WR_Byte(dat,cmd)即可,第一个参数为想要写入的数据,第二个参数为此条语句是命令(lcd_cmd)还是数据(lcd_dat),注:命令一般为地址,数据一般为向该地址写入的东西,显示芯片会按照设计逻辑执行认为写入的数据。
从显示芯片中读取数据的方式同理,根据协议编写即可,当前未用到,因此暂未实现。
五、芯片初始化
通讯协议实现之后,只需要参照芯片手册,编写初始化函数即可,此处除了特殊需求(屏幕显示方向、像素深度)外一般不需要更改。
void Lcd_BLOCK() //初始化显示内容,当前为空,即屏幕什么都不显示
{
OLED_WR_Byte(0x31,lcd_cmd);
OLED_WR_Byte(0x02,lcd_dat);//此处采用1bpp,低1位有效,只有0和1,0代表空,1代表点亮
OLED_WR_Byte(0xa5,lcd_dat);
OLED_WR_Byte(0xa5,lcd_dat);
OLED_WR_Byte(0xa5,lcd_dat);
delay_us(10);
}
void LCD_PAGE_SET()
{
OLED_WR_Byte(0x22,lcd_cmd);//Y轴坐标
OLED_WR_Byte(0x00,lcd_dat);//开始
OLED_WR_Byte(0x9F,lcd_dat);//结束
OLED_WR_Byte(0x00,lcd_dat);
OLED_WR_Byte(0xA5,lcd_dat);
OLED_WR_Byte(0x23,lcd_cmd);//X轴坐标
OLED_WR_Byte(0x00,lcd_dat);
OLED_WR_Byte(0x00,lcd_dat);//开始
OLED_WR_Byte(0x00,lcd_dat);
OLED_WR_Byte(0xEF,lcd_dat);//结束
}
void LCD_initial_ST7512(void)
{
RES_PutVal(0);
delay_ms(10);
RES_PutVal(1);
delay_ms(10); //Hardware reset
OLED_WR_Byte(0x5E,lcd_cmd); // Software reset
OLED_WR_Byte(0xA5,lcd_dat);
delay_ms(10);
OLED_WR_Byte(0x11,lcd_cmd); // Display OFF
OLED_WR_Byte(0xA5,lcd_dat);
OLED_WR_Byte(0x25,lcd_cmd); //VCOM offset data
OLED_WR_Byte(0x00,lcd_dat); //设置00 1bpp,01 2bpp,10 4bpp
OLED_WR_Byte(0xa5,lcd_dat);
OLED_WR_Byte(0xa5,lcd_dat);
OLED_WR_Byte(0xa5,lcd_dat);
OLED_WR_Byte(0x49,lcd_cmd); //VCOM offset data
OLED_WR_Byte(0x0e,lcd_dat);
OLED_WR_Byte(0x00,lcd_dat);
OLED_WR_Byte(0x01,lcd_dat);
OLED_WR_Byte(0xa5,lcd_dat);
OLED_WR_Byte(0x61,lcd_cmd); //PWRCTL
OLED_WR_Byte(0x8f,lcd_dat);
OLED_WR_Byte(0x44,lcd_dat);
OLED_WR_Byte(0x02,lcd_dat);
OLED_WR_Byte(0xa5,lcd_dat);
OLED_WR_Byte(0x71,lcd_cmd); //Electronic Volume Set 1
OLED_WR_Byte(0x26,lcd_dat);
OLED_WR_Byte(0x10,lcd_dat);
OLED_WR_Byte(0x0b,lcd_dat);
OLED_WR_Byte(0xa5,lcd_dat);
OLED_WR_Byte(0x72,lcd_cmd); //Electronic Volume Set 2
OLED_WR_Byte(0x1F,lcd_dat);
OLED_WR_Byte(0x1F,lcd_dat);
OLED_WR_Byte(0xa5,lcd_dat);
OLED_WR_Byte(0xa5,lcd_dat);
OLED_WR_Byte(0x81,lcd_cmd); //GAMSET4P1
OLED_WR_Byte(0x00,lcd_dat);//PV0
OLED_WR_Byte(0x0D,lcd_dat);//PV1
OLED_WR_Byte(0x12,lcd_dat);//PV2
OLED_WR_Byte(0x15,lcd_dat);//PV3
OLED_WR_Byte(0x82,lcd_cmd); //GAMSET4P2
OLED_WR_Byte(0x17,lcd_dat);//PV4
OLED_WR_Byte(0x19,lcd_dat);//PV5
OLED_WR_Byte(0x1B,lcd_dat);//PV6
OLED_WR_Byte(0x1D,lcd_dat);//PV7
OLED_WR_Byte(0x83,lcd_cmd); //GAMSET4P3
OLED_WR_Byte(0x1E,lcd_dat);//PV8
OLED_WR_Byte(0x20,lcd_dat);//PV9
OLED_WR_Byte(0x22,lcd_dat);//PV10
OLED_WR_Byte(0x24,lcd_dat);//PV11
OLED_WR_Byte(0x84,lcd_cmd); //GAMSET4P4
OLED_WR_Byte(0x27,lcd_dat);//PV12
OLED_WR_Byte(0x2A,lcd_dat);//PV13
OLED_WR_Byte(0x2F,lcd_dat);//PV14
OLED_WR_Byte(0x3F,lcd_dat);//PV15
OLED_WR_Byte(0x89,lcd_cmd); //GAMSET4N1
OLED_WR_Byte(0x00,lcd_dat);//NV0
OLED_WR_Byte(0x0D,lcd_dat);//NV1
OLED_WR_Byte(0x12,lcd_dat);//NV2
OLED_WR_Byte(0x15,lcd_dat);//NV3
OLED_WR_Byte(0x8a,lcd_cmd); //GAMSET4N2
OLED_WR_Byte(0x17,lcd_dat);//NV4
OLED_WR_Byte(0x19,lcd_dat);//NV5
OLED_WR_Byte(0x1B,lcd_dat);//NV6
OLED_WR_Byte(0x1D,lcd_dat);//NV7
OLED_WR_Byte(0x8b,lcd_cmd); //GAMSET4N3
OLED_WR_Byte(0x1E,lcd_dat);//NV8
OLED_WR_Byte(0x20,lcd_dat);//NV9
OLED_WR_Byte(0x22,lcd_dat);//NV10
OLED_WR_Byte(0x24,lcd_dat);//NV11
OLED_WR_Byte(0x8c,lcd_cmd); //GAMSET4N4
OLED_WR_Byte(0x27,lcd_dat);//NV12
OLED_WR_Byte(0x2A,lcd_dat);//NV13
OLED_WR_Byte(0x2F,lcd_dat);//NV14
OLED_WR_Byte(0x3F,lcd_dat);//NV15
OLED_WR_Byte(0x21,lcd_cmd); //Display Data direction Memory Address Control
OLED_WR_Byte(0x01,lcd_dat); //设置显示方向,具体见附件
OLED_WR_Byte(0xa5,lcd_dat);
OLED_WR_Byte(0xa5,lcd_dat);
OLED_WR_Byte(0xa5,lcd_dat);
OLED_WR_Byte(0xA2,lcd_cmd); //GATE SET
OLED_WR_Byte(0x00,lcd_dat); //default (NOTE: the settings is same as Epson)
OLED_WR_Byte(0xA5,lcd_dat);
OLED_WR_Byte(0xA5,lcd_dat);
OLED_WR_Byte(0xA5,lcd_dat);
OLED_WR_Byte(0x13,lcd_cmd); //SLEEP OUT
OLED_WR_Byte(0xa5,lcd_dat);
LCD_PAGE_SET();
Lcd_BLOCK();
OLED_WR_Byte(0x12,lcd_cmd); //Display ON
OLED_WR_Byte(0xa5,lcd_dat);
}
六、画点
完成以上工作之后,只需要调用此函数,便可进行画点,当然,在哪个位置画点,是需要进行处理的。
void Gui_DrawPoint(uint16 x,uint16 y,uint8 t)
{
OLED_SetRegion(x,y,x+1,y+1);//需要根据显示原理特殊处理
OLED_WR_Byte(0x3A,lcd_cmd);
OLED_WR_Byte(0xA5,lcd_dat);
if(t)
OLED_WR_Byte(0x01,lcd_dat);
else
OLED_WR_Byte(0x00,lcd_dat);
}
显示原理下个博客讲解。