st7920学习记录
本帖最后由 durongze 于 2024-9-12 07:04 编辑指令表 1
指 令 名 称 RS R/W D7D6 D5 D4 D3 D2 D1 D0 执 行时 间
清除显示 0 0 0 0 0 0 0 0 0 1 1.6 ms
地址归0 0 0 0 0 0 0 0 0 1 X 72us
进入设定点 0 0 0 0 0 0 0 1 I/D S 72us
显示开关设置 0 0 0 0 0 0 1 D C B 72us
移位控制 0 0 0 0 0 1 S/C R/L X X 72us
功能设定 0 0 0 0 1 DL X /RE X X 72us
设定 CGRAM 地址 0 0 0 1 A5 A4 A3 A2 A1 A0 72us
设定 DDRAM 地址 0 0 1 0 A5 A4 A3 A2 A1 A0 72us
读忙标志和地址 0 1 BF A6 A5 A4 A3 A2 A1 A0 72us
写显示数据 1 0 显 示 数 据 72us
读显示数据 1 1 显 示 数 据 72us
本帖最后由 durongze 于 2024-9-12 08:33 编辑
指 令 名 称 RS R/W D7 D6 D5 D4 D3 D2 D1 D0 执行时间
待命模式 0 0 0 0 0 0 0 0 0 1 72us
卷动RAM地址 0 0 0 0 0 0 0 0 1 SR 72us
反白显示 0 0 0 0 0 0 0 1 R1 R0 72us
睡眠模式 0 0 0 0 0 0 1 SL X X 72us
扩充功能设定 0 0 0 0 1 DL X 1/RE G 0 72us
IRAM 卷动地址 0 0 0 1 A5 A4 A3 A2 A1 A0 72us
0 0 0 A3 A2 A1 A0
设定绘图 RAM 地址 0 0 1 A6 A5 A4 A3 A2 A1 A0 72us 楼1是基本指令,总共11条, 楼2是扩展指令,总共7条。 本帖最后由 durongze 于 2024-9-12 09:18 编辑
先看管脚的连接方式:
#define LCD_Data P2 这个是数据传输的管脚,是p2端口,也就是p2的8个引脚。本例子不一定用的到,但是接上没坏处。对应8位并口模式下的db0-db7.其实4位并口模式也会用到,只是用了一半,比如db0-db3,具体怎么使用,我还不是特别理解。我们先有个印象吧。
sbit LCD_RS = P0^1; 这个是寄存器选择配置。 这个是分两种情况的,一种是并口模式,一种是串口模式。并口模式下拉高,是指准备往db0-db7写数据,拉低是准备写命令。串口模式下拉低,代表有效
sbit LCD_RW = P0^2; 也是分模式的,并口模式拉高是读,拉低是写。串口模式是数据线。
sbit LCD_E= P0^3; 并口模式是使能。 串口模式是时钟线。
sbit PSB = P0^4; //PSB 接高时选择并口,接低时选择串口。 这个其实放在第一个位置比较好,它控制着其他所有管脚存在的意义。
sbit LCD_RESET = P4^5; //17---RESETL-->Enable 复位信号,
#define LCD12864_SID LCD_RW // 见上面
#define LCD12864_SCLKLCD_E // 见上面
然后看st7920 的初始化:
P2 = 0; //数据管脚p2端口的7个脚
LCD_RS = 1; //并口模式下拉高,是指准备往db0-db7写数据,拉低是准备写命令。串口模式下拉低,代表有效
PSB = 0; //PSB 接高时选择并口,接低时选择串口。 这个其实放在第一个位置比较好,它控制着其他所有管脚存在的意义。
LCD_RESET = 1;
Delay_x10ms(4);
LCD12864_Write(Write_Command,Setting_Basic_Instruction_Set);// 0x30 这个可能是功能设定,在基本指令里有功能设定,在扩展指令里也有功能设定。这个取决于当前的模式。
Delay_x10us(10);
LCD12864_Write(Write_Command,Setting_Basic_Instruction_Set);// 0x30
Delay_x10us(4);
LCD12864_Write(Write_Command,Clear_Display); // 0x01 这个对应的指令名称应该是清除显示
Delay_x10us(10);
LCD12864_Write(Write_Command,Clear_Display); // 0x01同上
Delay_x10ms(1);
LCD12864_Write(Write_Command,Entry_Mode_Cursor_Right); // 0x06 基本命令模式下,是进入设定点,扩展模式下,是反白模式
Delay_x10us(10);
LCD12864_Write(Write_Command,Display_On_Cursor_Off_Inverse_Off); // 0x0c 基本命令模式下,是显示开关设置
Delay_x10us(10);
Clear_GDRAM();
Delay_x10us(10); 本帖最后由 durongze 于 2024-9-12 11:17 编辑
GDRAM 提供 64×32 个字节的空间(由扩充指令设定绘图 RAM 地址),最多可以控制
256×64 点阵的二维绘图缓冲空间,在更改绘图 RAM 是,由扩充指令设置 GDRAM
地址先垂直地址后水平地址(连续 2 个字节的数据来定义垂直和水平地址,其实就是先行后列),再
2 个字节的数据给绘图 RAM(先高 8 位后低 8 位)。 优秀!! 这个屏还是很好用的,自带16x16汉字库、支持CGRAM自定义字符、支持反白和绘图指令 本帖最后由 durongze 于 2024-9-12 11:38 编辑
void Clear_GDRAM(void)
{
unsigned char i,j,k;
LCD12864_Write(Write_Command,Setting_Extended_Instruction_Set_Drawing_Off); // 0x34 功能设定。 高4bit是3都是功能设定。前面第一条指令是0x30,这里是0x34,注意区别。后面详细分析。
k=0x80;
for(i=0; i<32; i++) {
LCD12864_Write(Write_Command,k++);//从0x80开始循环,循环32次,也就是小于0xA0, 其实就是垂直地址,也就是行。
LCD12864_Write(Write_Command,0x80);//其实就是水平地址,也就是列
for(j=0; j<16; j++) {
LCD12864_Write(Write_Data,0x00); // 8个 2 字节的数据给绘图 RAM(先高 8 位后低 8 位),也就是总共16字节, 但是为啥写的都是0x00, 算是清屏?
}
}
k=0x80;
for(i=0; i<32; i++) {
LCD12864_Write(Write_Command,k++);//从0x80开始循环,循环32次,也就是小于0xA0, 其实就是垂直地址,也就是行。
LCD12864_Write(Write_Command,0x88);// 其实就是水平地址,也就是列,这里为什么是0x88? 第一回写用的是0x80, 写了16字节,这里0x88 不会被覆盖吗,因为清屏不影响?
for(j=0; j<16; j++) {
LCD12864_Write(Write_Data,0x00); // 为啥写的都是0x00?
}
}
LCD12864_Write(Write_Command,Setting_Extended_Instruction_Set_Drawing_On); // 0x36 功能设定。 高4bit是3都是功能设定。前面第一条指令是0x30,这里是0x36,注意区别。后面详细分析。
} 其实上面初始化命令下发完成后,就可以直接显示数据了。现在我们来看下显示文本的流程:
void Display_Text(unsigned char code *addr) // 这个addr其实名称不太恰当,准确的说是str_addr. 不管长度,直接按屏幕长度遍历。
{
unsigned char i;
LCD12864_Write(Write_Command,Setting_Basic_Instruction_Set); //0x30 功能设定, 注意:前面初始化的时候,刚开始也是0x30,但是初始化的最后做了清屏操作,清屏操作应该做了两次功能设定 一次0x34,一次0x36,这里算是切换回基本模式了。
LCD12864_Write(Write_Command,0x80); //设定 DDRAM 地址0x80,注意:在初始化时的清屏操作中,也有这个操作,不过当时是遍历了所有垂直地址,也就是所有行,即0x80-0xA0,
Delay_10us();
for(i=0; i<16; i++) {
LCD12864_Write(Write_Data,*addr);
addr++;
}
LCD12864_Write(Write_Command,0x90); //设定 DDRAM 地址0x90 , 算是第2行。
Delay_10us();
for(i=0; i<16; i++) {
LCD12864_Write(Write_Data,*addr);
addr++;
}
LCD12864_Write(Write_Command,0x88); //设定 DDRAM 地址0x88, 第一行后一半
Delay_10us();
for(i=0; i<16; i++) {
LCD12864_Write(Write_Data,*addr);
addr++;
}
LCD12864_Write(Write_Command,0x98); //设定 DDRAM 地址0x98, 第二行后一半
Delay_10us();
for(i=0; i<16; i++) {
LCD12864_Write(Write_Data,*addr);
addr++;
}
} 通过上面的清屏和写字功能,可以看出地址的规律。写字时垂直地址(也就是行地址)就4个,第一行是0x80和0x88,第二行是0x90和0x98。而水平操作就是直接写16字节的数据。
不过就是很奇怪0x80-0x88按道理来说是8的字节的空间,却写了16字节数据,很有可能内部做了转换。把两个字节的字符合并成了一个字节的ascii码值?这个是我猜的,不一定对。
页:
[1]
2