前段时间入手了树莓派3B+,正好手里还有以前做项目留下的NOKIO 5110屏,于是想用树莓派搭配5110屏使用。
首先,确定raspberryPI与5110的连线:
1.1 NOKIA 5110的接口
5110接口如下图:
RST:LCD复位信号 SCE:SPI片选 低有效 D/C:数据/命令切换 0:命令,1:数据 SDIN:SPI MOSI 数据输入 SCLK:SPI 时钟 VCC:电源 3.3~5V LED:背光控制开头 GND:地 |
5110与raspberry的连线
因为树莓派自带SPI总线,具有2个片选信号,支持连接两个SPI设备,我们选择用CE0。
如下表:
打开raspberryPI的SPI接口功能
树莓派的SPI接口功能默认被禁用,需要手动使能,否则是普通的GPIO口。
在Raspbian系统中,选择【系统菜单--首选项--Raspberry Pi Configuration】,打开树莓派配置对话框,切换到【interfaces】,将SPI项选择“Enable”,即可打开SPI功能(需要重启):
python操作树莓派的SIP接口需要使用库“spidev”。
spidev库在pypi上的介绍如下:
安装:
pip install spidev
说明:
This project contains a python module for interfacing with SPI devices from user space via the spidev linux kernel driver.
用法:
import spidev
spi = spidev.SpiDev()
spi.open(bus, device)
to_send = [0x01, 0x02, 0x03]
spi.xfer(to_send)
因为之前使用AVR驱动5110,手中有相应的C代码,现在将对应的代码改写为python代码。
首先是字模代码:
AVR C代码的字模数据使用二维数组,存放为AVR的PROGMEM数据,如下:
而在树莓派中使用python驱动,使用字典则是更好的选择,使用字符作为key,需要字模数据作为value; 在打印字符时,使用待显示的字符即可方便地获取相应字模数据。
char_dict = {
" ": [0x00, 0x00, 0x00, 0x00, 0x00], # sp
"!": [0x00, 0x00, 0x2f, 0x00, 0x00], # !
"\"": [0x00, 0x07, 0x00, 0x07, 0x00], # "
"#": [0x14, 0x7f, 0x14, 0x7f, 0x14], # #
"$": [0x24, 0x2a, 0x7f, 0x2a, 0x12], # $
"%": [0x62, 0x64, 0x08, 0x13, 0x23], # %
"&": [0x36, 0x49, 0x55, 0x22, 0x50], # &
"'": [0x00, 0x05, 0x03, 0x00, 0x00], # '
"(": [0x00, 0x1c, 0x22, 0x41, 0x00], # (
")": [0x00, 0x41, 0x22, 0x1c, 0x00], # )
"*": [0x14, 0x08, 0x3E, 0x08, 0x14], # * - 10
"+": [0x08, 0x08, 0x3E, 0x08, 0x08], # +
",": [0x00, 0x00, 0xA0, 0x60, 0x00], # ,
"-": [0x08, 0x08, 0x08, 0x08, 0x08], # -
".": [0x00, 0x60, 0x60, 0x00, 0x00], # .
"/": [0x20, 0x10, 0x08, 0x04, 0x02], # /
"0": [0x3E, 0x51, 0x49, 0x45, 0x3E], # 0 - 16
"1": [0x00, 0x42, 0x7F, 0x40, 0x00], # 1
"2": [0x42, 0x61, 0x51, 0x49, 0x46], # 2
"3": [0x21, 0x41, 0x45, 0x4B, 0x31], # 3
"4": [0x18, 0x14, 0x12, 0x7F, 0x10], # 4 - 20
"5": [0x27, 0x45, 0x45, 0x45, 0x39], # 5
"6": [0x3C, 0x4A, 0x49, 0x49, 0x30], # 6
"7": [0x01, 0x71, 0x09, 0x05, 0x03], # 7
"8": [0x36, 0x49, 0x49, 0x49, 0x36], # 8
"9": [0x06, 0x49, 0x49, 0x29, 0x1E], # 9
":": [0x00, 0x36, 0x36, 0x00, 0x00], # :
";": [0x00, 0x56, 0x36, 0x00, 0x00], # ;
"<": [0x08, 0x14, 0x22, 0x41, 0x00], # <
"=": [0x14, 0x14, 0x14, 0x14, 0x14], # =
">": [0x00, 0x41, 0x22, 0x14, 0x08], # > -30
"?": [0x02, 0x01, 0x51, 0x09, 0x06], # ?
"@": [0x32, 0x49, 0x59, 0x51, 0x3E], # @
"A": [0x7C, 0x12, 0x11, 0x12, 0x7C], # A
"B": [0x7F, 0x49, 0x49, 0x49, 0x36], # B
"C": [0x3E, 0x41, 0x41, 0x41, 0x22], # C
"D": [0x7F, 0x41, 0x41, 0x22, 0x1C], # D
"E": [0x7F, 0x49, 0x49, 0x49, 0x41], # E
"F": [0x7F, 0x09, 0x09, 0x09, 0x01], # F
"G": [0x3E, 0x41, 0x49, 0x49, 0x7A], # G
"H": [0x7F, 0x08, 0x08, 0x08, 0x7F], # H - 40
"I": [0x00, 0x41, 0x7F, 0x41, 0x00], # I
"J": [0x20, 0x40, 0x41, 0x3F, 0x01], # J
"K": [0x7F, 0x08, 0x14, 0x22, 0x41], # K
"L": [0x7F, 0x40, 0x40, 0x40, 0x40], # L
"M": [0x7F, 0x02, 0x0C, 0x02, 0x7F], # M
"N": [0x7F, 0x04, 0x08, 0x10, 0x7F], # N
"O": [0x3E, 0x41, 0x41, 0x41, 0x3E], # O
"P": [0x7F, 0x09, 0x09, 0x09, 0x06], # P
"Q": [0x3E, 0x41, 0x51, 0x21, 0x5E], # Q
"R": [0x7F, 0x09, 0x19, 0x29, 0x46], # R - 50
"S": [0x46, 0x49, 0x49, 0x49, 0x31], # S
"T": [0x01, 0x01, 0x7F, 0x01, 0x01], # T
"U": [0x3F, 0x40, 0x40, 0x40, 0x3F], # U
"V": [0x1F, 0x20, 0x40, 0x20, 0x1F], # V
"W": [0x3F, 0x40, 0x38, 0x40, 0x3F], # W
"X": [0x63, 0x14, 0x08, 0x14, 0x63], # X
"Y": [0x07, 0x08, 0x70, 0x08, 0x07], # Y
"Z": [0x61, 0x51, 0x49, 0x45, 0x43], # Z
"[": [0x00, 0x7F, 0x41, 0x41, 0x00], # [
"\\": [0x55, 0x2A, 0x55, 0x2A, 0x55], # \55 - 60
"]": [0x00, 0x41, 0x41, 0x7F, 0x00], # ]
"^": [0x04, 0x02, 0x01, 0x02, 0x04], # ^
"_": [0x40, 0x40, 0x40, 0x40, 0x40], # _
"`": [0x00, 0x01, 0x02, 0x04, 0x00], # `
"a": [0x20, 0x54, 0x54, 0x54, 0x78], # a
"b": [0x7F, 0x48, 0x44, 0x44, 0x38], # b
"c": [0x38, 0x44, 0x44, 0x44, 0x20], # c
"d": [0x38, 0x44, 0x44, 0x48, 0x7F], # d
"e": [0x38, 0x54, 0x54, 0x54, 0x18], # e
"f": [0x08, 0x7E, 0x09, 0x01, 0x02], # f - 70
"g": [0x18, 0xA4, 0xA4, 0xA4, 0x7C], # g
"h": [0x7F, 0x08, 0x04, 0x04, 0x78], # h
"i": [0x00, 0x44, 0x7D, 0x40, 0x00], # i
"j": [0x40, 0x80, 0x84, 0x7D, 0x00], # j
"k": [0x7F, 0x10, 0x28, 0x44, 0x00], # k
"l": [0x00, 0x41, 0x7F, 0x40, 0x00], # l
"m": [0x7C, 0x04, 0x18, 0x04, 0x78], # m
"n": [0x7C, 0x08, 0x04, 0x04, 0x78], # n
"o": [0x38, 0x44, 0x44, 0x44, 0x38], # o
"p": [0xFC, 0x24, 0x24, 0x24, 0x18], # p - 80
"q": [0x18, 0x24, 0x24, 0x18, 0xFC], # q
"r": [0x7C, 0x08, 0x04, 0x04, 0x08], # r
"s": [0x48, 0x54, 0x54, 0x54, 0x20], # s
"t": [0x04, 0x3F, 0x44, 0x40, 0x20], # t
"u": [0x3C, 0x40, 0x40, 0x20, 0x7C], # u
"v": [0x1C, 0x20, 0x40, 0x20, 0x1C], # v
"w": [0x3C, 0x40, 0x30, 0x40, 0x3C], # w
"x": [0x44, 0x28, 0x10, 0x28, 0x44], # x
"y": [0x1C, 0xA0, 0xA0, 0xA0, 0x7C], # y
"z": [0x44, 0x64, 0x54, 0x4C, 0x44], # z - 90
"{": [0x00, 0x08, 0x36, 0x41, 0x00], # {
"|": [0x00, 0x00, 0x7F, 0x00, 0x00], # |
"}": [0x00, 0x41, 0x36, 0x08, 0x00], # }
"~": [0x08, 0x10, 0x08, 0x04, 0x08], # ~
}
5110操作代码:
pin_led = 32
pin_rst = 36
pin_sec = 38
pin_dc = 40
class LCD5110(object):
"""LCD 5110"""
def __init__(self, bus, device):
# init the pin mode
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
for pin in [pin_sec, pin_dc, pin_led, pin_rst]:
GPIO.setup(pin, GPIO.OUT)
# initinal the bus
self.spi = spidev.SpiDev()
self.spi.open(bus, device)
self.spi.max_speed_hz = 1000000
def lcd_init(self):
GPIO.output(pin_rst, 0)
time.sleep(0.05)
GPIO.output(pin_rst, 1)
self.lcd_write(0, [0x21]) # 使用扩展指令集
self.lcd_write(0, [0xC8]) # 设置Vop = 0x48
self.lcd_write(0, [0x06]) # 设置温度系数:0b10
self.lcd_write(0, [0x13]) # 设置偏置系数:3
self.lcd_write(0, [0x20]) # 使用基本指令集
self.lcd_write(0, [0x0C]) # 设置显示配置:D=1,E=0:普通模式
self.lcd_write(0, [0x40]) # 设置y地址:0
self.lcd_write(0, [0x80]) # 设置x地址:0
pass
def lcd_write(self, dc, data):
"""
write data/cmd to lcd5110
:param dc: D/C
:param data: data to be writed
:return:
"""
GPIO.output(pin_dc, dc)
time.sleep(0.00001)
self.spi.writebytes(data)
pass
def lcd_clear(self):
"""
clear the lcd5110
:return:
"""
self.lcd_write(0, [0x80])
self.lcd_write(0, [0x40])
for d in range(0, 505):
self.lcd_write(1, [0])
pass
def lcd_printc(self, char):
"""
show a chacter to lcd5110
:param char: chacter
:return:
"""
chr_codelist = char_dict[char]
for code in chr_codelist:
self.lcd_write(1, [code])
# time.sleep(0.0001)
# self.lcd_write(1, chr_codelist)
pass
def lcd_go_xy(self, x, y):
"""
光标定位,左上角为(0,0)
:param x: 列地址(0-83)
:param y: 行地址(0-5)
:return:
"""
self.lcd_write(0, [x+128])
self.lcd_write(0, [y+64])
def lcd_prints(self, s):
"""
print a string to lcd5110
:param s: string
:return:
"""
for c in s:
for code in c:
lcd.lcd_write(1, [code])
pass
显示示例:
lcd = LCD5110(0, 0)
lcd.lcd_init()
lcd.lcd_clear()
lcd.lcd_go_xy(0, 0)
time.sleep(0.001)
# 依次显示全部字符
for code in char_dict.values():
lcd.lcd_write(1, code)
time.sleep(0.1)
将编写的python代码传到raspberryPI中,使用PuTTY工具SSH连接,进入存放代码的目录并运行,即可在5110的屏幕上看到显示的全部字符。
后记:
最后,使用示例代码打算依次显示自定义字模中的字符,但显示的顺序和代码中定义的顺序并不一致?下一节将记录过程中的问题与解决方法。