LCD12864使用(驱动芯片UC1701x,四线模式)
1. 控制说明
CS | 芯片使能 |
---|---|
RST | 复位信号,低电平有效 |
A0 | 1:数据。0:命令 |
SCLK | 串口时钟输入 |
SDA | 串口数据输入 |
1.1UC1701x 四线模式通讯时序
从引脚配置和时序图可以看出,与LCD屏幕通讯分为两种通讯模式,一、命令。二、数据。发送数据。通过SCLK时钟线和SDA数据线发送。发送数据依据高位(MSB)在前,SCLK上升沿发送。只发不读。
代码实现。
/**
* value要发送的数据
*/
void writeToLcd(uint8_t value)
{
uint8_t i;
for(i=0; i < 8; i++)
{
SCLK_Switch(0); // 拉低SCLK
if(value&0x80) // 稳定数据,确保上升沿前数据有效
SDA_Switch(1);
else
SDA_Switch(0);
SCLK_Switch(1); // 发送数据
value<<=1;
}
}
/**
* type 命令字节选择
* value 要发送的数据
*/
void lcdWrite(LCD_WRITE_TYPE type, uint8_t value)
{
CS_Switch(0);
A0_Switch(type); // 选择命令、数据模式
writeToLcd(value); // 发送数据
CS_Switch(1);
}
// 模式
typedef enum
{
LCD_WRITE_TYPE_COMMAND = 0,
LCD_WRITE_TYPE_DATA,
}LCD_WRITE_TYPE;
2. 命令
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AazA01kR-
2.1 屏幕映射地址
从屏幕地址映射表中可以看出,LCD屏幕整个被分为8个page,每页又被分为八行,实际还是64行。列数根据屏幕大小而定,最大132列。要想在屏幕上面显示内容,我们需要根据地址映射进行配置。我们简单的根据表中的Page0分析。
屏幕区域显示分为3个步骤:
一、设置页地址
命令表第七条
7.Set Page Address 命令
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|
1 | 0 | 1 | 1 | # | # | # | # |
D7 - D4:高四位固定位0xB0
D3 - D0:为页面地址 Page0 为 0000,
即设置页地址时,需要向UC1701发送命令0xB0
二、设置列地址
根据命令表看出设置列地址时需要分为设置列高地址、列低地址
设置高地址的高四位为0x00,低地址高四位为0x10,第四位为列起始地址
设置多列数据时,只需要设置首列地址的命令,然后循环填充数据即可
即设置第0,1列的数据时只需要写入指令0x00,0x10,然后写入两次数据即可。
三、发送数据
这里的数据起始只的是行数据,LCD屏幕只有开关两种模式,每页分为八行,每行对应发送的数据的一位。
示例中第一行数据为 00011111(0x1F)
第二行数据为:11001100(0xCC)
代码实现
void lcdSetAddress(uint8_t page,uint8_t column)
{
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0xb0 + page);
// 设置页地址。每页是8行。一个画面的64行被分成8个页。我们平常所说的第1页,在LCD驱动IC里是第0页,所以在这里减去1*/
lcdWrite(LCD_WRITE_TYPE_COMMAND, ((column>>4)&0x0f) + 0x10);
// 设置列地址的高4位
lcdWrite(LCD_WRITE_TYPE_COMMAND, column&0x0f);
// 设置列地址的低4位
}
void test(void)
{
lcdSetAddress(0,0); // 0页,0列
lcdWrite(LCD_WRITE_TYPE_DATA, 0x1F);
lcdWrite(LCD_WRITE_TYPE_DATA, 0xCC);
}
只显示两列效果不明显,我们可以修改一下测试函数显示全部页面
void test(void)
{
for(uint8_t i = 0; i < 8; i++)
{
lcdSetAddress(i,0); // 0页,0列
for(uint8_t j = 0; j < 132; j += 2)
{
lcdWrite(LCD_WRITE_TYPE_DATA, 0x1F);
lcdWrite(LCD_WRITE_TYPE_DATA, 0xCC);
}
}
}
验证效果好像并不是太明显,大概意思是这。。。
3.初始化
不想细究了直接配置吧
void LCD_Init(void)
{
GPIO_InitTypeDef GPIO_Init;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_Init.Pin = LCD_CS_PIN | LCD_RST_PIN;
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_PULLUP;
GPIO_Init.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(LCD_CS_PORT, &GPIO_Init);
GPIO_Init.Pin = LCD_A0_PIN;
HAL_GPIO_Init(LCD_A0_PORT, &GPIO_Init);
GPIO_Init.Pin = LCD_SCLK_PIN | LCD_SDA_PIN | LCD_BACKLIGHT_PIN;
HAL_GPIO_Init(LCD_SCLK_PORT, &GPIO_Init);
HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN | LCD_RST_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LCD_A0_PORT, LCD_A0_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LCD_SCLK_PORT, LCD_SCLK_PIN | LCD_SDA_PIN | LCD_BACKLIGHT_PIN, GPIO_PIN_RESET);
RST_Switch(0); // 重置RESET
bsp_delay_ms(10);
RST_Switch(1); // 恢复重置RESET
bsp_delay_ms(10);
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0xe2);// System Reset
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0x2c);// Power Rise Step1
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0x2e);// Power Rise Step2
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0x2f);// Power Rise Step3
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0x23);
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0xa2);// Bias 1/9
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0xc0);// Set COM(row) Direction
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0xa1);// Set SEG(column) Direction
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0x40);// Set Scroll Line: the first line
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0xaf);// Display Enable
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0xa4);// Display Enable
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0x81);
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0x1f);
LEDA_Switch(0); // 关闭背光
clearScreen(); // 清屏
}
/*全屏清屏*/
void clearScreen(void)
{
uint8_t i,j;
for(i = 0; i < 8; i++)
{
lcdSetAddress(i,0);
for(j = 0;j < 132;j++)
{
lcdWrite(LCD_WRITE_TYPE_DATA, 0x00);
}
}
}
4.字库
下面是以 PCtolLCD2002完美版-字符模式软件为基础,制作宋体、16x16、汉字字库为例
4.1实现在指定区域显示汉字
代码
void DisplayChinese16x16(uint8_t page,uint8_t column,uint8_t reverse,uint8_t *dp)
{
uint8_t i,j,*data_temp;
data_temp = dp;
for(j = 0; j < 2;j++)
{
lcdSetAddress(page+j,column);
for (i=0;i < 16;i++)
{
reverse == 1? *data_temp = ~*data_temp : *data_temp;
lcdWrite(LCD_WRITE_TYPE_DATA, *data_temp);
data_temp++;
}
}
}
4.2PCtolLCD2002生成字库
重点关注红框内的设置
生成字模、保存
可以根据单个字符组合成单个字符的字模的,也可以生成字库
单个字符字模刷新
/**
* 显示16x16汉字字符
* page 页地址
* column 列地址
* reverse 反显
* *dp 字模数组
*/
void DisplayChinese16(uint8_t page,uint8_t column,uint8_t reverse,uint8_t *dp)
{
uint8_t i,j,*data_temp;
data_temp = dp;
for(j = 0; j < 2;j++)
{
lcdSetAddress(page+j,column);
for (i=0;i < 16;i++)
{
reverse == 1? *data_temp = ~*data_temp : *data_temp;
lcdWrite(LCD_WRITE_TYPE_DATA, *data_temp);
data_temp++;
}
}
}
生成字库
分为两个部分,一是、font_16_list[]字库列表。二、font_16_point[]。字模数组
char font_16_list[] =
{
"风急天高猿啸哀渚清沙白鸟飞回无边落木萧下不尽长江滚来" // 26字符 52 字节
};
uint8_t font_16_point[] =
{
0x00,0x00,0xFE,0x02,0x12,0x22,0xC2,0x02,0xC2,0x32,0x02,0xFE,0x00,0x00,0x00,0x00,
0x80,0x60,0x1F,0x00,0x20,0x10,0x0C,0x03,0x0C,0x30,0x00,0x0F,0x30,0x40,0xF8,0x00,/*"风",0*/
0x00,0x10,0x08,0x94,0x93,0x92,0x92,0x92,0x92,0x9A,0x96,0x90,0xF0,0x00,0x00,0x00,
0x40,0x30,0x04,0x74,0x84,0x84,0x8C,0xB4,0x84,0x84,0x84,0xE4,0x07,0x10,0x60,0x00,/*"急",1*/
0x40,0x40,0x42,0x42,0x42,0x42,0x42,0xFE,0x42,0x42,0x42,0x42,0x42,0x40,0x40,0x00,
0x80,0x80,0x40,0x20,0x10,0x0C,0x03,0x00,0x03,0x0C,0x10,0x20,0x40,0x80,0x80,0x00,/*"天",2*/
0x04,0x04,0x04,0x04,0xF4,0x94,0x95,0x96,0x94,0x94,0xF4,0x04,0x04,0x04,0x04,0x00,
0x00,0xFE,0x02,0x02,0x7A,0x4A,0x4A,0x4A,0x4A,0x4A,0x7A,0x02,0x82,0xFE,0x00,0x00,/*"高",3*/
0x22,0x14,0x08,0xF6,0x00,0x10,0xD4,0x54,0x54,0x5F,0x54,0x54,0xD4,0x10,0x10,0x00,
0x44,0x82,0x41,0x3F,0x20,0x20,0x13,0xFA,0x46,0x22,0x0E,0x12,0x2B,0x44,0x40,0x00,/*"猿",4*/
0x00,0xFC,0x04,0x04,0xFC,0x10,0x54,0x54,0x54,0xFF,0x54,0x54,0x7C,0x10,0x10,0x00,
0x00,0x0F,0x04,0x04,0x8F,0x40,0x3F,0x08,0x04,0xFF,0x04,0x08,0xFF,0x00,0x00,0x00,/*"啸",5*/
0x04,0x04,0x04,0xE4,0x24,0x24,0x25,0x26,0x24,0x24,0x24,0xE4,0x04,0x04,0x04,0x00,
0x20,0x20,0x10,0x11,0x09,0xFD,0x43,0x21,0x03,0x05,0x09,0x11,0x28,0x44,0x40,0x00,/*"哀",6*/
0x10,0x60,0x02,0x8C,0x20,0x24,0x24,0xA4,0x7F,0x24,0x34,0x28,0x26,0x20,0x20,0x00,
0x04,0x04,0x7E,0x01,0x04,0x02,0xFF,0x49,0x49,0x49,0x49,0x49,0xFF,0x00,0x00,0x00,/*"渚",7*/
0x10,0x60,0x02,0x8C,0x00,0x44,0x54,0x54,0x54,0x7F,0x54,0x54,0x54,0x44,0x40,0x00,
0x04,0x04,0x7E,0x01,0x00,0x00,0xFF,0x15,0x15,0x15,0x55,0x95,0x7F,0x00,0x00,0x00,/*"清",8*/
0x10,0x60,0x02,0x8C,0x00,0x80,0x60,0x18,0x00,0xFF,0x00,0x00,0x88,0x10,0x60,0x00,
0x04,0x04,0x7E,0x01,0x00,0x80,0x80,0x40,0x40,0x23,0x10,0x0C,0x03,0x00,0x00,0x00,/*"沙",9*/
0x00,0x00,0xF8,0x08,0x08,0x0C,0x0A,0x09,0x08,0x08,0x08,0x08,0xF8,0x00,0x00,0x00,
0x00,0x00,0xFF,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0xFF,0x00,0x00,0x00,/*"白",10*/
0x00,0x00,0x00,0xFC,0x04,0x04,0x16,0x65,0x04,0x44,0x84,0x7C,0x00,0x00,0x00,0x00,
0x00,0x10,0x10,0x13,0x12,0x12,0x12,0x12,0x12,0x12,0x52,0x82,0x42,0x3E,0x00,0x00,/*"鸟",11*/
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x40,0xA0,0x10,0x08,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0C,0x10,0x21,0x42,0xF0,0x00,/*"飞",12*/
0x00,0x00,0xFE,0x02,0x02,0xF2,0x12,0x12,0x12,0xF2,0x02,0x02,0xFE,0x00,0x00,0x00,
0x00,0x00,0x7F,0x20,0x20,0x27,0x24,0x24,0x24,0x27,0x20,0x20,0x7F,0x00,0x00,0x00,/*"回",13*/
0x00,0x40,0x42,0x42,0x42,0xC2,0x7E,0x42,0xC2,0x42,0x42,0x42,0x40,0x40,0x00,0x00,
0x80,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x3F,0x40,0x40,0x40,0x40,0x70,0x00,0x00,/*"无",14*/
0x40,0x40,0x42,0xCC,0x00,0x00,0x08,0x08,0x88,0x7F,0x08,0x08,0x08,0xF8,0x00,0x00,
0x00,0x40,0x20,0x1F,0x20,0x50,0x48,0x46,0x41,0x40,0x48,0x50,0x48,0x47,0x40,0x00,/*"边",15*/
0x84,0x04,0x14,0x64,0x0F,0x04,0x84,0x44,0xB4,0x24,0x2F,0xA4,0x64,0x04,0x04,0x00,
0x08,0x0B,0xF8,0x04,0x03,0x04,0x04,0xFA,0x4A,0x49,0x49,0x4A,0xFA,0x04,0x04,0x00,/*"落",16*/
0x00,0x10,0x10,0x10,0x10,0xD0,0x30,0xFF,0x30,0xD0,0x10,0x10,0x10,0x10,0x00,0x00,
0x10,0x08,0x04,0x02,0x01,0x00,0x00,0xFF,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x00,/*"木",17*/
0x84,0x84,0xA4,0xA4,0xAF,0xA4,0xA4,0xF4,0xA4,0xA4,0xAF,0xA4,0xE4,0x84,0x84,0x00,
0x80,0x40,0x3A,0x02,0x22,0x1A,0x02,0xFF,0x02,0x0A,0x32,0x02,0xFB,0x00,0x00,0x00,/*"萧",18*/
0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x02,0x02,0x42,0x82,0x02,0x02,0x02,0x02,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x01,0x06,0x00,0x00,0x00,/*"下",20*/
0x00,0x02,0x02,0x02,0x02,0x82,0x42,0xF2,0x0E,0x42,0x82,0x02,0x02,0x02,0x00,0x00,
0x10,0x08,0x04,0x02,0x01,0x00,0x00,0xFF,0x00,0x00,0x00,0x01,0x02,0x0C,0x00,0x00,/*"不",21*/
0x00,0x00,0x00,0xFE,0x22,0x22,0x22,0x22,0x22,0xE2,0x22,0x22,0x7E,0x00,0x00,0x00,
0x10,0x08,0x06,0x01,0x10,0x10,0x22,0x22,0x44,0x80,0x01,0x02,0x04,0x08,0x08,0x00,/*"尽",22*/
0x80,0x80,0x80,0x80,0xFF,0x80,0x80,0xA0,0x90,0x88,0x84,0x82,0x80,0x80,0x80,0x00,
0x00,0x00,0x00,0x00,0xFF,0x40,0x21,0x12,0x04,0x08,0x10,0x20,0x20,0x40,0x40,0x00,/*"长",23*/
0x10,0x60,0x02,0x0C,0xC0,0x04,0x04,0x04,0x04,0xFC,0x04,0x04,0x04,0x04,0x00,0x00,
0x04,0x04,0x7C,0x03,0x20,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x20,0x20,0x20,0x00,/*"江",24*/
0x10,0x60,0x02,0x8C,0x00,0x24,0x94,0xCC,0xA5,0x96,0xC4,0x8C,0x14,0x24,0x00,0x00,
0x04,0x04,0x7E,0x01,0x20,0x10,0x08,0xFC,0x42,0x24,0x08,0x15,0x22,0x40,0x40,0x00,/*"滚",25*/
0x00,0x08,0x08,0x28,0xC8,0x08,0x08,0xFF,0x08,0x08,0x88,0x68,0x08,0x08,0x00,0x00,
0x21,0x21,0x11,0x11,0x09,0x05,0x03,0xFF,0x03,0x05,0x09,0x11,0x11,0x21,0x21,0x00,/*"来",27*/
};
根据字符列表查询对应的字模数组
uint8_t * fontGetPoint(const char *str)
{
if(*str > 0x7F)
{
/* 一个汉字字符占两个字节 */
for(uint8_t i = 0, j = 0; i < sizeof(font_16_list); i+= 2, j++)
{
if(*str == font_16_list[i]) // 两个字节都相同
{
if(*(str+1) == font_16_list[i+1])
return (uint8_t*)(&font_16_point[j * 32]);
}
}
}
else // 可能是英文字符
{
// 根据需要填充就行,比汉字简单
}
return 0;
}
字库使用
/**
* 显示多个16x16汉字字模
* page 页地址
* column 列地址
* reverse 反显
* *str 字符串
*/
void DisplayManyChinese16(uint8_t page,uint8_t column,uint8_t reverse, const char *str)
{
char strl[20]; // 一个汉字占2个字节,一行最多有8个16x16的字符
memcpy(strl, str, strlen(str));
for(uint8_t len = 0, i = 0; len < strlen(strl); len += 2, i++)
// strlen(strl)获取str1的字节数,假设有7个汉字字符,那么就有14个字节,i计算当前列地址
{
DisplayChinese16(page, column+(i*16), reverse, fontGetPoint(&strl[len]));
}
}
// 测试
void test(void)
{
DisplayManyChinese16(0, 4, 0, "风急天高猿啸哀");
DisplayManyChinese16(2, 4, 0, "渚清沙白鸟飞回");
DisplayManyChinese16(4, 4, 0, "无边落木萧萧下");
DisplayManyChinese16(6, 4, 0, "不尽长江滚滚来");
}
代码区
1. lcd.c文件
#include "../HARDWARE/LCD/lcd.h"
#include "../HARDWARE/Font/font16/font16.h"
#include "main.h"
#include "stdio.h"
#include "string.h"
// LCD_CS1 PC4
// LCD_RES PC5
// LCD_A0 PB11
// LCD_SCL PA5
// LCD_SDA PA7
// LCD_BACKLIGHT PA6
// CS 使能(低电平)
#define LCD_CS_PORT GPIOC
#define LCD_CS_PIN GPIO_PIN_4
// RES 复位(低电平)
#define LCD_RST_PORT GPIOC
#define LCD_RST_PIN GPIO_PIN_5
// A0 数据(1)/命令(0)
#define LCD_A0_PORT GPIOB
#define LCD_A0_PIN GPIO_PIN_11
// SCL 串口时钟输入
#define LCD_SCLK_PORT GPIOA
#define LCD_SCLK_PIN GPIO_PIN_5
// SDA 串口数据输入
#define LCD_SDA_PORT GPIOA
#define LCD_SDA_PIN GPIO_PIN_7
// BACKLIGHT 背光正极
#define LCD_BACKLIGHT_PORT GPIOA
#define LCD_BACKLIGHT_PIN GPIO_PIN_6
#define CS_Switch(x) HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, (GPIO_PinState)x)
#define RST_Switch(x) HAL_GPIO_WritePin(LCD_RST_PORT, LCD_RST_PIN, (GPIO_PinState)x)
#define A0_Switch(x) HAL_GPIO_WritePin(LCD_A0_PORT, LCD_A0_PIN, (GPIO_PinState)x)
#define SCLK_Switch(x) HAL_GPIO_WritePin(LCD_SCLK_PORT, LCD_SCLK_PIN, (GPIO_PinState)x)
#define SDA_Switch(x) HAL_GPIO_WritePin(LCD_SDA_PORT, LCD_SDA_PIN, (GPIO_PinState)x)
#define LEDA_Switch(x) HAL_GPIO_WritePin(LCD_BACKLIGHT_PORT,LCD_BACKLIGHT_PIN, (GPIO_PinState)x)
void writeToLcd(uint8_t value)
{
uint8_t i;
for(i=0; i < 8; i++)
{
SCLK_Switch(0); // 拉低SCLK
if(value&0x80) // 稳定数据
SDA_Switch(1);
else
SDA_Switch(0);
SCLK_Switch(1); // 发送数据
value<<=1;
}
}
void lcdWrite(LCD_WRITE_TYPE type, uint8_t value)
{
CS_Switch(0);
A0_Switch(type);
writeToLcd(value);
CS_Switch(1);
}
void LCD_Init(void)
{
GPIO_InitTypeDef GPIO_Init;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_Init.Pin = LCD_CS_PIN | LCD_RST_PIN;
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_PULLUP;
GPIO_Init.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(LCD_CS_PORT, &GPIO_Init);
GPIO_Init.Pin = LCD_A0_PIN;
HAL_GPIO_Init(LCD_A0_PORT, &GPIO_Init);
GPIO_Init.Pin = LCD_SCLK_PIN | LCD_SDA_PIN | LCD_BACKLIGHT_PIN;
HAL_GPIO_Init(LCD_SCLK_PORT, &GPIO_Init);
HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN | LCD_RST_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LCD_A0_PORT, LCD_A0_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LCD_SCLK_PORT, LCD_SCLK_PIN | LCD_SDA_PIN | LCD_BACKLIGHT_PIN, GPIO_PIN_RESET);
RST_Switch(0); // 重置RESET
bsp_delay_ms(10);
RST_Switch(1); // 恢复重置RESET
bsp_delay_ms(10);
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0xe2);// System Reset
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0x2c);// Power Rise Step1
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0x2e);// Power Rise Step2
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0x2f);// Power Rise Step3
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0x23);
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0xa2);// Bias 1/9
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0xc0);// Set COM(row) Direction
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0xa1);// Set SEG(column) Direction
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0x40);// Set Scroll Line: the first line
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0xaf);// Display Enable
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0xa4);// Display Enable
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0x81);
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0x1f);
LEDA_Switch(1); // 关闭背光
clearScreen(); // 清屏
}
/**
* 设置地址
* page 页地址
* column 列地址
*/
void lcdSetAddress(uint8_t page,uint8_t column)
{
lcdWrite(LCD_WRITE_TYPE_COMMAND, 0xb0 + page); // 设置页地址。每页是8行。一个画面的64行被分成8个页。我们平常所说的第1页,在LCD驱动IC里是第0页,所以在这里减去1*/
lcdWrite(LCD_WRITE_TYPE_COMMAND, ((column>>4)&0x0f) + 0x10); // 设置列地址的高4位
lcdWrite(LCD_WRITE_TYPE_COMMAND, column&0x0f); // 设置列地址的低4位
}
/*全屏清屏*/
void clearScreen(void)
{
uint8_t i,j;
for(i = 0; i < 8; i++)
{
lcdSetAddress(i,0);
for(j = 0;j < 132;j++)
{
lcdWrite(LCD_WRITE_TYPE_DATA, 0x00);
}
}
}
/**
* 显示16x16汉字字符
* page 页地址
* column 列地址
* reverse 反显
* *dp 字模数组
*/
void DisplayChinese16(uint8_t page,uint8_t column,uint8_t reverse,uint8_t *dp)
{
uint8_t i,j,*data_temp;
data_temp = dp;
for(j = 0; j < 2;j++)
{
lcdSetAddress(page+j,column);
for (i=0;i < 16;i++)
{
reverse == 1? *data_temp = ~*data_temp : *data_temp;
lcdWrite(LCD_WRITE_TYPE_DATA, *data_temp);
data_temp++;
}
}
}
/**
* 显示多个16x16汉字字模
* page 页地址
* column 列地址
* reverse 反显
* *str 字符串
*/
void DisplayManyChinese16(uint8_t page,uint8_t column,uint8_t reverse, const char *str)
{
char strl[20]; // 一个汉字占2个字节,一行最多有8个16x16的字符
memcpy(strl, str, strlen(str));
for(uint8_t len = 0, i = 0; len < strlen(strl); len += 2, i++) // strlen(strl)获取str1的字节数,假设有7个汉字字符,那么就有14个字节,i计算当前列地址
{
DisplayChinese16(page, column+(i*16), reverse, fontGetPoint(&strl[len]));
}
}
void test(void)
{
DisplayManyChinese16(0, 4, 0, "风急天高猿啸哀");
DisplayManyChinese16(2, 4, 0, "渚清沙白鸟飞回");
DisplayManyChinese16(4, 4, 0, "无边落木萧萧下");
DisplayManyChinese16(6, 4, 0, "不尽长江滚滚来");
}
lcd.h文件
#ifndef _LCD_H
#define _LCD_H
#include "stdint.h"
void LCD_Init(void);
void clearScreen(void);
void test(void);
void testValue(uint8_t value);
typedef enum
{
LCD_WRITE_TYPE_COMMAND = 0,
LCD_WRITE_TYPE_DATA,
}LCD_WRITE_TYPE;
#endif
#ifndef _FONT16_H_
#define _FONT16_H_
#include "stdint.h"
uint8_t * fontGetPoint(const char *str);
#endif