原理
之前没有操作过12864这种类型的屏,但是,操作过其他类型的,原理都是相通的。12864是拥有128x64像素点这类屏幕的称号吧。屏幕有64行,128列;每个汉字是16x16,所以一个这样的屏,最多可以显示4x8的汉字或者8x16的字符。
我使用的是不带字库的I2C接口的屏幕,主芯片是ST7656。这样的屏,只能写,不能读。先配置屏幕,然后通过字模制作软件制作出待显示内容的像素数字,最后,通过数据线传送给屏幕显示。了解了原理后,接下来就根据主芯片的数据手册进行配置屏幕就好了。
硬件连线
- CS:片选
- RST: 复位
- RS:数据或命令选择
- SDA:I2C数据线
- SCL:I2C时钟线
I2C采用的是软件模拟的
底层写操作
#define IO_ST7565_CS_0 GPIO_WriteBit(GPIOB, GPIO_Pin_5, RESET)
#define IO_ST7565_CS_1 GPIO_WriteBit(GPIOB, GPIO_Pin_5, SET)
#define IO_ST7565_SDA_0 GPIO_WriteBit(GPIOB, GPIO_Pin_1, RESET)
#define IO_ST7565_SDA_1 GPIO_WriteBit(GPIOB, GPIO_Pin_1, SET)
#define IO_ST7565_SCK_0 GPIO_WriteBit(GPIOB, GPIO_Pin_2, RESET)
#define IO_ST7565_SCK_1 GPIO_WriteBit(GPIOB, GPIO_Pin_2, SET)
#define IO_ST7565_RST_0 GPIO_WriteBit(GPIOB, GPIO_Pin_4, RESET)
#define IO_ST7565_RST_1 GPIO_WriteBit(GPIOB, GPIO_Pin_4, SET)
#define IO_ST7565_RS_0 GPIO_WriteBit(GPIOB, GPIO_Pin_3, RESET)
#define IO_ST7565_RS_1 GPIO_WriteBit(GPIOB, GPIO_Pin_3, SET)
static void io_delay(uint16_t nCount)
{
while (nCount--);
}
/* rs == 1 data rs==0 cmd */
void ST7565_Write(uint8_t dat,uint8_t rs)
{
uint8_t i;
IO_ST7565_SCK_0;
IO_ST7565_CS_0;
if(!rs)
{
IO_ST7565_RS_0; //Command
}else{
IO_ST7565_RS_1;
}
io_delay(5);
for(i = 0; i < 8; i++)
{
if( dat & 0x80){
IO_ST7565_SDA_1;
}else{
IO_ST7565_SDA_0;
}
dat <<= 1;
IO_ST7565_SCK_1;
io_delay(5);
IO_ST7565_SCK_0;
io_delay(5);
}
io_delay(5);
IO_ST7565_CS_1;
IO_ST7565_RS_1;
io_delay(5);
}
/* write cmd */
void writec(uint8_t com)
{
ST7565_Write(com,0);
}
/* write data */
void writed(uint8_t dat)
{
ST7565_Write(dat,1);
}
初始化
void LcmClear(uint8_t FillData)
{
uint8_t i,j;
for(i=0;i<8;i++)
{
writec(0xB0|i); //Set Page Address
writec(0x10); //Set Column Address = 0
writec(0x00); //Colum from S1 -> S128 auto add
for(j=0;j<132;j++)
{
writed( FillData );
}
}
}
void LcmInit(void)
{
IO_ST7565_CS_1;
IO_ST7565_RST_0;
delay_ms(10); //hard reset for 10ms
IO_ST7565_RST_1;
delay_ms(10);
writec(0xAE); //Display OFF
writec(0xA2); //1/64 Duty 1/9 Bias
writec(0xA0); //ADC select S0->S131(玻璃设计用S1-S128)
writec(0xC0); //com1 --> com64
writec(0x24); //对某些模块没用,用的外部Rb/Ra
writec(0x81); //Sets V0
writec(48); //内部电位器调节对比度
writec(0x2F); //voltage follower ON regulator ON booster ON
writec(0xA6); //Normal Display (not reverse dispplay)
writec(0xA4); //Entire Display Disable
writec(0x40); //Set Display Start Line = com0
writec(0xB0); //Set Page Address = 0
writec(0x10); //Set Column Address 4 higher bits = 0
writec(0x00); //Set Column Address 4 lower bits = 1 , from IC SEG1 -> SEG128
LcmClear(0);
writec(0xAF); //Display ON
}
上面的这些命令代表什么含义,输入的命令值具体代表什么,都可以在ST7656的官方数据手册中找到答案。
应用
使用字模软件制作字模:
uint8_t hzk[] = {
/*-- 文字: 请 0 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x00,0x00,0xFE,0x04,0x08,0x00,0xFF,0xA8,0xA8,0xA8,0xAA,0xA9,0xFE,0x00,0x00,0x00,
0x02,0x42,0x33,0x00,0x00,0x22,0x2A,0x2A,0x2A,0xFE,0x2A,0x2A,0x2A,0x22,0x02,0x00,
}
uint8_t num[] = {
/*-- 文字: 0 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x07,0x08,0x10,0x10,0x08,0x07,0x00,0x00,0xF0,0x08,0x04,0x04,0x08,0xF0,0x00,
}
/* page: 0 - 7; col: 0 - 128 */
void show_char(uint8_t page, uint8_t col, uint8_t *data)
{
uint8_t i;
/* set page address */
writec(0xB0 | page);
/* set column address */
writec(0x10 | col >> 4);
writec(col & 0xf);
for(i = 8; i < 16; i++) {
writed(data[i]);
}
page++;
/* set page address */
writec(0xB0 | page);
/* set column address */
writec((0x10 | (col >> 4)));
writec(col & 0xf);
for(i = 0; i < 8; i++)
{
writed(data[i]);
}
}
/* page: 0/2/4/6; col: 0 - 128 */
void show_chinese(uint8_t page, uint8_t col, uint8_t *data)
{
uint8_t i;
/* set page address */
writec(0xB0 | page);
/* set column address */
writec(0x10 | col >> 4);
writec(col & 0xf);
for(i = 0; i < 16; i++) {
writed(data[i]);
}
page++;
/* set page address */
writec(0xB0 | page);
/* set column address */
writec((0x10 | (col >> 4)));
writec(col & 0xf);
for(i = 16; i < 32; i++)
{
writed(data[i]);
}
}
show_chinese(4, 0x20, hzk);
show_char(2, 0x30, num);
资料
字模软件: https://download.csdn.net/download/donglicaiju76152/10805852
ST7656数据手册: https://download.csdn.net/download/donglicaiju76152/10805849