当前位置: 代码迷 >> 综合 >> Orange Pi 通过I2C总线连接LCD1602
  详细解决方案

Orange Pi 通过I2C总线连接LCD1602

热度:48   发布时间:2024-01-04 12:25:14.0

Orange Pi 通过I2C总线连接LCD1602

前言

上一节通过Orange Pi gpio 直接控制1602,可以看出来缺点非常明显:Orange Pi IO 口占用过多
因为Orange Pi的GPIO口非常有限,所以这一章就来解决这个问题,采用 i2c转LCD1602的转接板( PCF85741)来减少Orange Pi 的GPIO占用

一、硬件及连线:

模块长这样子,网上找的图:
在这里插入图片描述
和1602连在一起是这样子,这个是焊接在一起的,也可以用杜邦线连接起来
在这里插入图片描述
有了这货之后,连接香橙派就只需要两根数据线就可以了,如果不算电源线的话,加上电源线一共也才四根线,清爽多了

连线也是so easy,下面奉上接线方式(物理接口):

:---PCF85741---:   :---Orange Pi---:GND-------------06 GROUNDVCC-------------04 5VSDA-------------03 SDA1SCL-------------05 SDA1

好了,完成上面的接线工作,就可以通电了。
连接电源打开树莓派,显示屏就会亮,同时在第一行显示一排黑方块。如果看不到黑方块或黑方块不明显,请调节i2c模块上的可调电阻,直到黑方块清晰显示。如果调节可调电阻还看不到方块,则可能你的连接有问题了,请检查连接,包括检查显示屏的引脚有没有虚焊。

二、使能I2C

由于我的系统是armbian的,比较方便,如果你装的是orangepi官网提供的ubuntu,建议你不要折腾了,换回armbian会让你省很多事。这是我含泪踩过的坑啊,内核都重新编译过了,心酸

废话不多说,先看看默认有没有使能i2c:

ls /dev | grep i2c

什么都没有,看来是没有使能i2c啊
接下来开启i2c,armbian有一个非常好用的工具,类似树莓派的raspi-config,它就是armbian-config

sudo armbian-config

忘了截图了,依次进入:system>>HardWare>>[ ]i2c0 ,按空格键选中i2c0,变成[* ]i2c0这样子,
然后选中save,reboot即可
在这里插入图片描述
再执行:


ls /dev | grep i2c

打印出 i2c-0 了,说明开启成功,接下来看一下i2c设备地址:

root@orangepi:~# sudo apt install i2c-toolsroot@orangepi:~# i2cdetect -y 00  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- 27 -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --  

可以看到我的i2c设备地址是0x27
这说明 已经成功连接了 LCD1602 。接下来就可以用 Python 控制 LCD1602 显示信息了。

三、驱动程序:

python驱动i2c需要python-smbus,先安装一下:

sudo apt-get install python3-smbus

接下来我们熟悉的套路,上代码,如下:

vim i2c_1602_test.py
#!/usr/bin/python
# coding:utf-8
''' BIT D7 D6 D5 D4 D3 D2 D1 D0| | | | | | | | LCD D7 D6 D5 D4 BackLight En Rw Rs'''
import time
import smbus
import sysBl = 0B00001000  # backlight 0:off 1:on
En = 0B00000100  # Enable bit
Rw = 0B00000010  # Read/Write bit 0:write 1:read
Rs = 0B00000001  # Register select bit 0:cmd 1:dataLCD_WIDTH = 16    # Maximum characters per line
LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd linedebug = 0#创建一个smbus实例
BUS = smbus.SMBus(0)        # 0 代表 /dev/i2c-0, 1 代表 /dev/i2c-1 ,具体看使用的树莓派那个I2C来决定
LCD_ADDR = 0x27             #sudo i2cdetect -y -a 0def main():global debugif len(sys.argv)>1:debug = 1print("turn on debug,welcom!")else:debug = 0init_lcd()while True:show_on_lcd(LCD_LINE_1, 0, '1234567890123456')show_on_lcd(LCD_LINE_2, 0, 'abcdefghijklmnop')time.sleep(3) # 3 second delayshow_on_lcd(LCD_LINE_1, 0, 'blog.csdn.net')show_on_lcd(LCD_LINE_2, 0, 'Running_free')time.sleep(3) # 3 second delaydef send_command(comm):if debug:print("****************now send sommand******************")print("now send command >>>>>>>>>>>>>>>>>",hex(comm),"---",bin(comm))# Send bit7-4 firstlybuf = comm & 0xF0 | Bl | Enif debug:print(" high: ",bin(buf)),
# buf |= (Bl | En) # BL = 1, EN = 1, RW = 0, RS = 0BUS.write_byte(LCD_ADDR ,buf)time.sleep(0.002)buf &= 0xFB                                             # EN = 0if debug:print(" high_en: ",bin(buf)),BUS.write_byte(LCD_ADDR ,buf)# Send bit3-0 secondlybuf = ((comm & 0x0F) << 4)| Bl | Enif debug:print(" low: ",bin(buf)),
# buf |= (Bl | En) # BL = 1, EN = 1, RW = 0, RS = 0BUS.write_byte(LCD_ADDR ,buf)time.sleep(0.002)buf &= 0xFB                                             # EN = 0if debug:print(" low_en: ",bin(buf),"end<<<<<<<<<<<<<<<<<<<<<<")BUS.write_byte(LCD_ADDR ,buf)def send_data(data):if debug:print("****************now send data******************")print("now send data --------------",hex(data),"---",bin(data))# Send bit7-4 firstlybuf = data & 0xF0 | Bl | En | Rsif debug:print(" high: ",bin(buf)),
# buf |= (Bl | En | Rs) # BL = 1, EN = 1, RW = 0, RS = 1BUS.write_byte(LCD_ADDR ,buf)time.sleep(0.002)buf &= 0xFB                                             # EN = 0if debug:print(" high_en: ",bin(buf)),BUS.write_byte(LCD_ADDR ,buf)# Send bit3-0 secondlybuf = ((data & 0x0F) << 4)| Bl | En | Rsif debug:print(" low: ",bin(buf)),
# buf |= (Bl | En | Rs) # BL = 1, EN = 1, RW = 0, RS = 1BUS.write_byte(LCD_ADDR ,buf)time.sleep(0.002)buf &= 0xFB                                             # EN = 0if debug:print(" low_en: ",bin(buf),"end------------------")BUS.write_byte(LCD_ADDR ,buf)def init_lcd():if debug:print("****************now init******************")send_command(0x33) # Must initialize to 8-line mode at firsttime.sleep(0.005)send_command(0x32) # Then initialize to 4-line modetime.sleep(0.005)send_command(0x06) # Cursor move directiontime.sleep(0.005)send_command(0x0C) # Enable display without cursortime.sleep(0.005)send_command(0x28) # 2 Lines & 5*7 dotstime.sleep(0.005)send_command(0x01) # Clear Screentime.sleep(0.005)def clear_lcd():if debug:print("****************now clear******************")send_command(0x01) # Clear Screendef show_on_lcd(line,table,message):if debug:print("****************now show on lcd******************")# Send string to displaymessage = message.ljust(LCD_WIDTH," ")send_command(line)for i in range(LCD_WIDTH):send_data(ord(message[i]))if __name__ == '__main__':try:main()#except KeyboardInterrupt:except:passfinally:clear_lcd()show_on_lcd(LCD_LINE_1, 0, 'Goodbye!')BUS.close()

加了debug方便调试,运行python3 i2c_1602_test.py 后面不跟参数不打印debug信息,如果想打印debug信息,只需要后面跟一个参数即可,任何参数都ok,例:python3 i2c_1602_test.py 1 或者 python3 i2c_1602_test.py debug

#仅运行
python3 i2c_1602_test.py
#运行并打印debug信息
python3 i2c_1602_test.py debug

在这里插入图片描述

总结

如果1602没有显示,请检查线路是否有故障,杜邦线容易松动导致接触不良,传输数据就会出现问题,含着泪踩过的坑啊

  相关解决方案