|
LCD1602多引脚面对Raspberry Pi 引脚有限的情况,就显得由为重要。
先来来Python 的实现方法,主要是利用python-smbus
方案方法
sudo apt-get install python-smbus
sudo apt-get install i2c-tools
MCP8574 的代码如下Qtgz_PCF8574.py
- from Qtgz_I2C import Qtgz_I2C
- import smbus
- import time
- class Qtgz_MCP8574(object):
- OUTPUT = 0
- INPUT = 1
- def __init__(self, address, num_gpios, busnum=-1):
- assert num_gpios >= 0 and num_gpios <= 8, "Number of GPIOs must be between 0 and 16"
- self.i2c = Qtgz_I2C(address=address, busnum=busnum)
- self.address = address
- self.num_gpios = num_gpios
- def _changebit(self, bitmap, bit, value):
- assert value == 1 or value == 0, "Value is %s must be 1 or 0" % value
- if value == 0:
- return bitmap & ~(1 << bit)
- elif value == 1:
- return bitmap | (1 << bit)
- def _readandchangepin(self, pin, value, currvalue = None):
- assert pin >= 0 and pin < self.num_gpios, "in number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios)
- #assert self.direction & (1 << pin) == 0, "in %s not set to output" % pin
- if not currvalue:
- currvalue = self.i2c.readRaw8()
- newvalue = self._changebit(currvalue, pin, value)
- self.i2c.writeRaw8(newvalue)
- return newvalue
- def config(self, pin, mode):
- if self.num_gpios <= 8:
- self.direction = self._readandchangepin(pin, mode)
- return self.direction
- def output(self, pin, value):
- if self.num_gpios <= 8:
- self.outputvalue = self._readandchangepin(pin, value, self.i2c.readRaw8())
- return self.outputvalue
- def input(self, pin):
- assert pin >= 0 and pin < self.num_gpios, "in number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios)
- assert self.direction & (1 << pin) != 0, "in %s not set to input" % pin
- if self.num_gpios <= 8:
- value = self.i2c.readRaw8()
- return value & (1 << pin)
- def readU8(self):
- result = self.i2c.readRaw8()
- return(result)
- def readS8(self):
- result = self.i2c.readRaw8()
- if (result > 127): result -= 256
- return result
- def write8(self, value):
- self.i2c.writeRaw8(value)
- class PCF8574_GPIO(object):
- OUT = 0
- IN = 1
- BCM = 0
- BOARD = 0
- def __init__(self, busnum, address, num_gpios):
- self.chip = Qtgz_MCP8574(address, num_gpios, busnum)
- def setmode(self, mode):
- # do nothing
- pass
- def setup(self, pin, mode):
- self.chip.config(pin, mode)
- def input(self, pin):
- return self.chip.input(pin)
- def output(self, pin, value):
- self.chip.output(pin, value)
- if __name__ == '__main__':
- # ***************************************************
- # Set num_gpios to 8 for MCP8574
- # ***************************************************
- mcp = Qtgz_MCP8574(address = 0x27, num_gpios = 8) # MCP8574
- mcp.config(3, mcp.OUTPUT)
- # Set pin 3 to input with the pullup resistor enabled
- #mcp.config(3, mcp.INPUT)
- # Read input pin and display the results
- #print "in 3 = %d" % (mcp.input(3) >> 3)
- # Python speed test on output 3 toggling at max speed
- print "Starting blinky on pin 3 (CTRL+C to quit)"
- while (True):
- mcp.output(3, 1) # Pin 0 High
- time.sleep(1);
- mcp.output(3, 0) # Pin 0 Low
- time.sleep(1);
复制代码
LCD1602 的代码
- from time import sleep
- class Adafruit_CharLCD(object):
- # commands
- LCD_CLEARDISPLAY = 0x01
- LCD_RETURNHOME = 0x02
- LCD_ENTRYMODESET = 0x04
- LCD_DISPLAYCONTROL = 0x08
- LCD_CURSORSHIFT = 0x10
- LCD_FUNCTIONSET = 0x20
- LCD_SETCGRAMADDR = 0x40
- LCD_SETDDRAMADDR = 0x80
- # flags for display entry mode
- LCD_ENTRYRIGHT = 0x00
- LCD_ENTRYLEFT = 0x02
- LCD_ENTRYSHIFTINCREMENT = 0x01
- LCD_ENTRYSHIFTDECREMENT = 0x00
- # flags for display on/off control
- LCD_DISPLAYON = 0x04
- LCD_DISPLAYOFF = 0x00
- LCD_CURSORON = 0x02
- LCD_CURSOROFF = 0x00
- LCD_BLINKON = 0x01
- LCD_BLINKOFF = 0x00
- # flags for display/cursor shift
- LCD_DISPLAYMOVE = 0x08
- LCD_CURSORMOVE = 0x00
- # flags for display/cursor shift
- LCD_DISPLAYMOVE = 0x08
- LCD_CURSORMOVE = 0x00
- LCD_MOVERIGHT = 0x04
- LCD_MOVELEFT = 0x00
- # flags for function set
- LCD_8BITMODE = 0x10
- LCD_4BITMODE = 0x00
- LCD_2LINE = 0x08
- LCD_1LINE = 0x00
- LCD_5x10DOTS = 0x04
- LCD_5x8DOTS = 0x00
- def __init__(self, pin_rs=25, pin_e=24, pins_db=[23, 17, 21, 22], GPIO=None):
- # Emulate the old behavior of using RPi.GPIO if we haven't been given
- # an explicit GPIO interface to use
- if not GPIO:
- import RPi.GPIO as GPIO
- GPIO.setwarnings(False)
- self.GPIO = GPIO
- self.pin_rs = pin_rs
- self.pin_e = pin_e
- self.pins_db = pins_db
- self.GPIO.setmode(GPIO.BCM) #GPIO=None use Raspi PIN in BCM mode
- self.GPIO.setup(self.pin_e, GPIO.OUT)
- self.GPIO.setup(self.pin_rs, GPIO.OUT)
- for pin in self.pins_db:
- self.GPIO.setup(pin, GPIO.OUT)
- self.write4bits(0x33) # initialization
- self.write4bits(0x32) # initialization
- self.write4bits(0x28) # 2 line 5x7 matrix
- self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor
- self.write4bits(0x06) # shift cursor right
- self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF
- self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS
- self.displayfunction |= self.LCD_2LINE
- # Initialize to default text direction (for romance languages)
- self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT
- self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) # set the entry mode
- self.clear()
- def begin(self, cols, lines):
- if (lines > 1):
- self.numlines = lines
- self.displayfunction |= self.LCD_2LINE
- def home(self):
- self.write4bits(self.LCD_RETURNHOME) # set cursor position to zero
- self.delayMicroseconds(3000) # this command takes a long time!
- def clear(self):
- self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display
- self.delayMicroseconds(3000) # 3000 microsecond sleep, clearing the display takes a long time
- def setCursor(self, col, row):
- self.row_offsets = [0x00, 0x40, 0x14, 0x54]
- if row > self.numlines:
- row = self.numlines - 1 # we count rows starting w/0
- self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row]))
- def noDisplay(self):
- """ Turn the display off (quickly) """
- self.displaycontrol &= ~self.LCD_DISPLAYON
- self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
- def display(self):
- """ Turn the display on (quickly) """
- self.displaycontrol |= self.LCD_DISPLAYON
- self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
- def noCursor(self):
- """ Turns the underline cursor off """
- self.displaycontrol &= ~self.LCD_CURSORON
- self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
- def cursor(self):
- """ Turns the underline cursor on """
- self.displaycontrol |= self.LCD_CURSORON
- self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
- def noBlink(self):
- """ Turn the blinking cursor off """
- self.displaycontrol &= ~self.LCD_BLINKON
- self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
- def blink(self):
- """ Turn the blinking cursor on """
- self.displaycontrol |= self.LCD_BLINKON
- self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
- def DisplayLeft(self):
- """ These commands scroll the display without changing the RAM """
- self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT)
- def scrollDisplayRight(self):
- """ These commands scroll the display without changing the RAM """
- self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT)
- def leftToRight(self):
- """ This is for text that flows Left to Right """
- self.displaymode |= self.LCD_ENTRYLEFT
- self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)
- def rightToLeft(self):
- """ This is for text that flows Right to Left """
- self.displaymode &= ~self.LCD_ENTRYLEFT
- self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)
- def autoscroll(self):
- """ This will 'right justify' text from the cursor """
- self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT
- self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)
- def noAutoscroll(self):
- """ This will 'left justify' text from the cursor """
- self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT
- self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)
- def write4bits(self, bits, char_mode=False):
- """ Send command to LCD """
- self.delayMicroseconds(1000) # 1000 microsecond sleep
- bits = bin(bits)[2:].zfill(8)
- self.GPIO.output(self.pin_rs, char_mode)
- for pin in self.pins_db:
- self.GPIO.output(pin, False)
- for i in range(4):
- if bits == "1":
- self.GPIO.output(self.pins_db[::-1], True)
- self.pulseEnable()
- for pin in self.pins_db:
- self.GPIO.output(pin, False)
- for i in range(4, 8):
- if bits == "1":
- self.GPIO.output(self.pins_db[::-1][i-4], True)
- self.pulseEnable()
- def delayMicroseconds(self, microseconds):
- seconds = microseconds / float(1000000) # divide microseconds by 1 million for seconds
- sleep(seconds)
- def pulseEnable(self):
- self.GPIO.output(self.pin_e, False)
- self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns
- self.GPIO.output(self.pin_e, True)
- self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns
- self.GPIO.output(self.pin_e, False)
- self.delayMicroseconds(1) # commands need > 37us to settle
- def message(self, text):
- """ Send string to LCD. Newline wraps to second line"""
- for char in text:
- if char == '\n':
- self.write4bits(0xC0) # next line
- else:
- self.write4bits(ord(char), True)
- if __name__ == '__main__':
- lcd = Adafruit_CharLCD()
- lcd.clear()
- lcd.message(" Adafruit 16x2\n Standard LCD")
复制代码
实现代码如下,打印内部温度,内存使用情况
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- from Adafruit_CharLCD import Adafruit_CharLCD
- from Qtgz_PCF8574 import PCF8574_GPIO
- from subprocess import *
- from time import sleep, strftime
- from datetime import datetime
- import commands
- def get_cpu_temp():
- tmp = open('/sys/class/thermal/thermal_zone0/temp')
- cpu = tmp.read()
- tmp.close()
- return '{:.2f}'.format( float(cpu)/1000 ) + ' C'
- def get_gpu_temp():
- tmp = commands.getoutput('vcgencmd measure_temp|awk -F= \'{print $2}\'').replace('\'C','')
- gpu = float(tmp)
- return '{:.2f}'.format( gpu ) + ' C'
- def get_time_now():
- return datetime.now().strftime(' %H:%M:%S\n %Y-%m-%d')
- def get_ip_info():
- return commands.getoutput('ifconfig wlan0|grep inet|awk -Faddr: \'{print $2}\'|awk \'{print $1}\'')
- def get_mem_info():
- total= commands.getoutput('free -m|grep Mem:|awk \'{print $2}\'')
- free = commands.getoutput('free -m|grep cache:|awk \'{print $4}\'')
- return 'MEM:\n ' + free +' / '+ total +' M'
- bus = 1 # Note you need to change the bus number to 0 if running on a revision 1 Raspberry Pi.
- address = 0x27 # I2C address of the PCF8574 chip.
- gpio_count = 8 # Number of GPIOs exposed by the PCF8574 chip, should be 8 or 16 depending on chip.
- # Create PCF8574 GPIO adapter.
- mcp = PCF8574_GPIO(bus, address, gpio_count)
- # Create LCD, passing in MCP GPIO adapter.
- lcd = Adafruit_CharLCD(pin_rs=0, pin_e=2, pins_db=[4,5,6,7], GPIO=mcp)
- if __name__ == '__main__':
- while(1):
- lcd.clear()
- lcd.message( get_ip_info() )
- sleep(1)
- lcd.clear()
- lcd.message( get_time_now() )
- sleep(1)
- lcd.clear()
- lcd.message( get_mem_info() )
- sleep(1)
- lcd.clear()
- lcd.message( 'CPU: ' + get_cpu_temp()+'\n' )
- lcd.message( 'GPU: ' + get_gpu_temp() )
- sleep(1)
复制代码
效果如下
热门推荐:
树莓派经验分享全攻略 |
|