|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
LCD1602 液晶显示器是广泛使用的一种字符型液晶显示模块。
很多单片机、开发板等都有它的踪影,语言中无论是 C/C++、Python、Arduino 等都已经有许多大佬帮它写了初始化、SDK、头文件、模块... 只需下载直接就能调用,不用理解显示器内部运作方式。
在这里我想试试自己写
以下代码(未完成),因为怕忘记,所以先笔记。
- from machine import Pin, PWM
- from micropython import const
- from time import sleep_us
- LOW = const(0)
- HIGH = const(1)
- # 将数据 (二进制) 写入八位引脚
- def setting(D: "引脚", data: "二进制数据") -> None:
- res = list()
- i = 8
- while i:
- i -= 1
- res.append(data & 1)
- data >>= 1
- for i, d in res[::-1]:
- D[i].high() if d else D[i].low()
- class LCD1602:
- def __init__(self, GND, VCC, VO, RS, RW, EN, A, K, *D):
- # 电源控制引脚
- self.GND = GND
- self.VCC = VCC
- self.GND.value(LOW)
- self.VCC.value(HIGH)
-
- # 液晶显示控制引脚
- self.VO = VO # LCD 对比度 - 脉冲引脚
- self.A = A # LCD 背光 - Anode
- self.K = K # LCD 背光 - Cathode
- self.A.value(HIGH)
- self.K.value(LOW)
-
- self.VO.duty_16(65535 >> 1) # 将占空比设为 50%
- self.VO.init(freq = 5000, duty_ns = 5000) # 重新初始化,周期为 200us,占空比为 5us
- self.VO.duty_ns(3000) # 设置脉冲宽度为 3us
-
- # 数据控制引脚
- self.RS = RS # 寄存器选择
- self.RW = RW # 读 / 写数据
- self.EN = EN # enable 启用
- self.D = D # 8 bits (0000 0000)
-
- def __del__(self):
- self.VO.deinit() # 结束脉冲信号
-
- # 清屏指令 (clear display) # RS RW 0 0 0 0 0 0 0 1
- def Clear(self):
- """
- 清除液晶显示器,即将 DDRAM 中的内容全部填入 20H (空白字符)
- 光标撤回显示屏左上方
- 将地址计数器 (AC) 设为 0
- 光标移动方向为从左向右,并且 DDRAM 的自增量为 1 (ID = 1)
- """
- self.RS.low()
- self.RW.low()
- setting(self.D, 0x01) # 8bits 0000 0001
-
- # 光标归位指令 (Return Home) # RS RW 0 0 0 0 0 0 1 X
- def Home(self):
- """
- 将地址计数器 (AC) 设为 00H
- DDRAM 内容保持不变
- 光标移至左上脚
-
- ** DB0: X (未知逻辑电平)
- """
- self.RS.low()
- self.RW.low()
- pin.value(LOW) for pin in self.D[2:]
- self.D[1].value(HIGH)
-
- # 进入模式设置指令 (Entry Mode Set) RS RW 0 0 0 0 0 1 ID SH
- def Entry(self, ID = LOW, SH = HIGH):
- """ 设定每次定入 1 位数据后,光标移位方向并且设定次写入一个字符是否移动
- ID = 0 光标左移,DDRAM 地址自增 1
- ID = 1 光标右移,DDRAM 地址自增 1 (当从 CGRAM 中读取或写入数据时,CGRAM 操作与 DDRAM 相同)
- SH = 0 且 DDRAM是读操作(CGRAM读或写),整个屏幕不移动
- SH = 1 且 DDRAM 是写操作,整个屏幕移动,移动方向由I/D决定
-
- ** ID: Increment / decrement of DDRAM address (cursor or blink)
- ** SH: Shift of entire display
- """
- self.RS.low()
- self.RW.low()
- setting(self.D, 0b100 | ID << 1 | SH)
-
- # 显示开关控制 (Display ON/OFF Control)
- def OnOff(self, D = HIGH, C = HIGH, B = LOW): # RS RW 0 0 0 0 1 D C B
- """
- D = 1 显示功能开
- D = 0 显示功能关,但是 DDRAM 中的数据依然保留
- C = 1 有光标
- C = 0 没有光标
- B = 1 光标闪烁
- B = 0 光标不闪烁
-
- ** D: Display ON/OFF control bit
- ** C: Cursor ON/OFF control bit
- ** B: Cursor Blink ON/OFF control bit
- """
- self.RS.low()
- self.RW.low()
- setting(self.D, 0b1000 | D << 2 | C << 1 | B)
-
- # 设置显示屏或光标移动方向的指令 RS RW 0 0 0 1 SC RL X X
- def Shift(self, SC = HIGH, RL = HIGH):
- """ 整屏的移动或光标移动
- S/C = 0 R/L = 0 光标左移,地址计数器减 1 (即显示内容和光标一起左移)
- S/C = 0 R/L = 1 光标右移,地址计数器加 1 (即显示内容和光标一起右移)
- S/C = 1 R/L = 0 显示内容左移,光标不移动
- S/C = 1 R/L = 1 显示内容右移,光标不移动
-
- ** S/C: Screen / Cursor
- ** R/L: Right / Left
- """
- self.RS.low()
- self.RW.low()
- self.D[pin].value(state) for pin, state in enumerate([RL, SC, HIGH, LOW, LOW, LOW], start = 2)
-
- # 功能设定指令 RS RW 0 0 1 DL N F XX
- def Set(self, DL = HIGH, N = HIGH, F = HIGH):
- """ 设定数据总线位数、显示的行数及字形
- DL = 1 数据总线是 8 位
- DL = 0 数据总线是 4 位
- N = 0 显示一行
- N = 1 显示两行
- F = 0 5x8 点阵/字符
- F = 1 5x11 点阵/字符
-
- ** DL: Interface data length control bit
- ** N: Display line number control bit
- ** F: Display font type control bit
- """
- self.RS.low()
- self.RW.low()
- self.D[pin].value(state) for pin, state in enumerate([F, N, DL, HIGH, LOW, LOW], start = 2)
-
- # 设定 DDRAM 地址指令 RS RW 1 AC6 AC5 AC4 AC3 AC2 AC1 AC0
- # 设定 CGRAM 地址指令 RS RW 0 1 AC5 AC4 AC3 AC2 AC1 AC0
- def Write(self, data):
- """ 设定下一个要存入数据的 CGRAM 地址
- DB5 DB4 DB3 为字符号,即将显示该字符用到的字符地址 8 bits
- DB2 DB1 DB0 为行号 111 / 000
-
- ** CGRAM: Character generate RAM 自定义的字符或图形,存储在 CGRAM 中
- ** CGROM: Character generate ROM 常用字符原本就已经存储在 CGROM 中,可以直接调用
- ** DDRAM: Display Data Random Access Memory 显示用的地址
-
- DDRAM 地址与显示位置对应关系如下:
- 00H 01H 02H 03H 04H 05H 06H 07H 08H 09H 10H 11H 12H 13H 14H 15H
- 40H 41H 42H 43H 44H 45H 46H 47H 48H 49H 4AH 4BH 4CH 4DH 4EH 4FH
- -----------------------------------------------------------------------------------
- | command | | running |
- | function | instruction encoding | time |
- -----------------------------------------------------------------------------------
- | set | RS | RW | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 | |
- | DDRAM |----------------------------------------------------------- 40us |
- | address | 0 | 0 | 1 | CGRAM address (7 bits) | |
- -----------------------------------------------------------------------------------
- ###################################################################################
- -----------------------------------------------------------------------------------
- | command | | running |
- | function | instruction encoding | time |
- -----------------------------------------------------------------------------------
- | set | RS | RW | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 | |
- | CGRAM |----------------------------------------------------------- 40us |
- | address | 0 | 0 | 0 | 1 | CGRAM address (6 bits) | |
- -----------------------------------------------------------------------------------
-
- """
- self.RS.low()
- self.RW.low()
- setting(self.D, address)
- sleep_us(100) # 延迟 100毫秒,以确保数据接受完毕 (数据接收至少需要 40us)
-
- "编写中..."
- pass
-
- def Read(self, data):
- "编写中..."
- pass
-
- if __name__ == "__main__":
-
- # 引脚 GPIO 0 ~ 15
- GND = Pin(0, Pin.OUT)
- VCC = Pin(1, Pin.OUT)
- VO = PWM(2)
- RS = Pin(3, Pin.OUT)
- RW = Pin(4, Pin.OUT)
- EN = Pin(5, Pin.OUT)
- D = Pin(i, Pin.OUT) for i in range(6, 14)
- A = Pin(14, Pin.OUT)
- K = Pin(15, Pin.OUT)
- lcd = LCD1602(GND, VCC, VO, RS, RW, EN, A, K, D)
复制代码 |
|