美文网首页树莓派
树莓派通过C语言和python操作LCD液晶屏

树莓派通过C语言和python操作LCD液晶屏

作者: 刘小白DOER | 来源:发表于2021-01-16 23:25 被阅读0次

        今天实验树莓派通过 I2C 驱动操作 LCD1602 液晶屏,屏幕带I2C 方式的驱动模块,可以极大的简化接线和驱动程序。本文利用C语言和python来实验操作LCD1602液晶屏,python程序方面分别显示字符串,IP地址,树莓派状态信息,功能更加丰富。特别是lcd_status.py程序设置为开机启动,那么树莓派的IP地址、状态都可以一目了然。作为可视化界面,当然也可以显示任何你需要的信息。

        今晚搞了一晚,主要有三个地方花了时间。

        一是模块上有一颗可调电阻,用于调节显示的对比度,如果你的屏幕无论怎么调试都不见显示,记得调节一下这里,这个问题纠结了我好久才发现!!!

        二是运行python程序时,没有把float浮点数转换成字符串str,LCD不能写入浮点数。

        三是树莓派要开启I2C功能。

    1、接线图

    GND --- GND       VCC --- 接树莓派 3.3V

    SDA --- I2C 数据   SCL --- I2C 时钟

    2、启用树莓派的I2C功能

    可以通过sudo raspi-config命令来开启,也可以VNC到树莓派来可视化开启。

    运行命令看一下是否识别到屏幕, 地址为0x27,这说明已经成功连接了 LCD1602 屏幕。

    sudo i2cdetect -y 1

    3、C语言操作LCD  lcd.c

    #include <wiringPi.h>

    #include <stdio.h>

    #include <sys/time.h>

    #include <wiringPiI2C.h>

    #include <string.h>

    int LCDAddr = 0x27;

    int BLEN = 1;

    int ad;

    void write_word(int data){

             inttemp = data;

             if(BLEN== 1)

                temp |= 0x08;

             else

                temp &= 0xF7;

             wiringPiI2CWrite(ad,temp);

    }

    void send_command(int comm){

             intbuf;

             buf= comm & 0xF0;

             buf|= 0x04;

             write_word(buf);

             delay(2);

             buf&= 0xFB;

             write_word(buf);

             buf= (comm & 0x0F) << 4;

             buf|= 0x04;

             write_word(buf);

             delay(2);

             buf&= 0xFB;

             write_word(buf);

    }

    void send_data(int data){

             intbuf;

             buf= data & 0xF0;

             buf|= 0x05;

             write_word(buf);

             delay(2);

             buf&= 0xFB;

             write_word(buf);

             buf= (data & 0x0F) << 4;

             buf|= 0x05;

             write_word(buf);

             delay(2);

             buf&= 0xFB;

             write_word(buf);

    }

    void init(){

             send_command(0x33);

             delay(5);

             send_command(0x32);

             delay(5);

             send_command(0x28);

             delay(5);

             send_command(0x0C);

             delay(5);

             send_command(0x01);

             wiringPiI2CWrite(ad,0x08);

    }

    void clear(){

             send_command(0x01);

    }

    void write(int x,int y, char data[]){

             intaddr,i;

             inttmp;

             if(x<0)  x=0;

             if(x>15)x=15;

             if(y<0)  y=0;

             if(y>1)  y=1;

             addr= 0x80 + 0x40 * y +x;

             send_command(addr);

             tmp= strlen(data);

             for(i= 0; i < tmp; i++){

                       send_data(data[i]);

             }

    }

    int main(void){

             ad= wiringPiI2CSetup(LCDAddr);

             init();

             write(0,0,"Hello");

             write(1,1,"pi");

             delay(2000);

    }

    write函数的第一二个参数的含义是列号和行号。

    编译C语言:gcc lcd.c -o lcd -lwiringPi

    运行程序:./lcd

    4、python操作LCD   

    4.1 LCD显示字符 lcd1602.py

    import time

    import smbus

    BUS = smbus.SMBus(1)

    LCD_ADDR = 0x27

    BLEN = 1 #turn on/off background light

    def turn_light(key):

        global BLEN

        BLEN = key

        if key ==1 :

            BUS.write_byte(LCD_ADDR ,0x08)

        else:

            BUS.write_byte(LCD_ADDR ,0x00)

    def write_word(addr, data):

        global BLEN

        temp = data

        if BLEN == 1:

            temp |= 0x08

        else:

            temp &= 0xF7

        BUS.write_byte(addr ,temp)

    def send_command(comm):

        # Send bit7-4 firstly

        buf = comm & 0xF0

        buf |= 0x04              # RS = 0, RW = 0, EN = 1

        write_word(LCD_ADDR ,buf)

        time.sleep(0.002)

        buf &= 0xFB              # Make EN = 0

        write_word(LCD_ADDR ,buf)

        # Send bit3-0 secondly

        buf = (comm & 0x0F) << 4

        buf |= 0x04              # RS = 0, RW = 0, EN = 1

        write_word(LCD_ADDR ,buf)

        time.sleep(0.002)

        buf &= 0xFB              # Make EN = 0

        write_word(LCD_ADDR ,buf)

    def send_data(data):

        # Send bit7-4 firstly

        buf = data & 0xF0

        buf |= 0x05              # RS = 1, RW = 0, EN = 1

        write_word(LCD_ADDR ,buf)

        time.sleep(0.002)

        buf &= 0xFB              # Make EN = 0

        write_word(LCD_ADDR ,buf)

        # Send bit3-0 secondly

        buf = (data & 0x0F) << 4

        buf |= 0x05              # RS = 1, RW = 0, EN = 1

        write_word(LCD_ADDR ,buf)

        time.sleep(0.002)

        buf &= 0xFB              # Make EN = 0

        write_word(LCD_ADDR ,buf)

    def init_lcd():

        try:

            send_command(0x33) # Must initialize to 8-line mode at first

            time.sleep(0.005)

            send_command(0x32) # Then initialize to 4-line mode

            time.sleep(0.005)

            send_command(0x28) # 2 Lines & 5*7 dots

            time.sleep(0.005)

            send_command(0x0C) # Enable display without cursor

            time.sleep(0.005)

            send_command(0x01) # Clear Screen

            BUS.write_byte(LCD_ADDR ,0x08)

        except:

            return False

        else:

            return True

    def clear_lcd():

        send_command(0x01) # Clear Screen

    def print_lcd(x, y, str):

        if x < 0:

            x = 0

        if x > 15:

            x = 15

        if y <0:

            y = 0

        if y > 1:

            y = 1

        # Move cursor

        addr = 0x80 + 0x40 * y + x

        send_command(addr)

        for chr in str:

            send_data(ord(chr))

    if __name__ == '__main__':

        init_lcd()

        print_lcd(0, 0, 'Hello, world!')

        print_lcd(0, 1, 'Hello, world!')

    运行程序:python lcd1602.py,print_lcd函数的前两个参数分别是列号和行号。

    4.2 LCD显示时间 lcd_time.py

    显示时间的python:lcd_time.py,需要使用到lcd1602.py的 print_lcd函数,所以调用lcd1602.py文件。

    #!/user/bin/env python

    import smbus

    import time

    import sys

    import lcd1602 as LCD

    if __name__ == '__main__':

        LCD.init_lcd()

        time.sleep(1)

        LCD.print_lcd(2, 0, 'Raspberry Pi')

        for x in xrange(1, 4):

            LCD.turn_light(0)

            LCD.print_lcd(4, 1, 'LIGHT OFF')

            time.sleep(0.5)

            LCD.turn_light(1)

            LCD.print_lcd(4, 1, 'LIGHT ON ')

            time.sleep(0.5)

        LCD.turn_light(1)

        while True:

            now = time.strftime('%m/%d %H:%M:%S', time.localtime(time.time()))

            LCD.print_lcd(1, 1, now)

            time.sleep(0.2)

    4.3 LCD显示IP地址 lcd_ip.py 

    和显示时间类似,显示树莓派的ip地址,这个程序可以设置为开机启动,这样就可以直观知道树莓派的IP地址了。

    #!/user/bin/env python

    import os

    import smbus

    import time

    import sys

    import socket

    import subprocess

    import lcd1602 as LCD

    def getLocalIP():

        ip = None

        try:

            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

            s.connect(('114.114.114.114', 0))

            ip = s.getsockname()[0]

        except:

            name = socket.gethostname()

            ip = socket.gethostbyname(name)

        if ip.startswith("127."):

            cmd = '''/sbin/ifconfig | grep "inet " | cut -d: -f2 | awk '{print $1}' | grep -v "^127."'''

            a = subprocess.Popen(

                cmd,

                shell=True,

                stdout=subprocess.PIPE,

                stderr=subprocess.PIPE)

            a.wait()

            out = a.communicate()

            ip = out[0].strip().split("\n")

            if len(ip) == 1 and ip[0] == "" or len(ip) == 0:

                return False

            ip = "over".join(ip)

        return ip

    if __name__ == '__main__':

        LCD.init_lcd()

        time.sleep(1)

        LCD.print_lcd(2, 0, 'Raspberry Pi')

        for x in xrange(1, 4):

            LCD.turn_light(0)

            LCD.print_lcd(4, 1, 'LIGHT OFF')

            time.sleep(0.5)

            LCD.turn_light(1)

            LCD.print_lcd(4, 1, 'LIGHT ON ')

            time.sleep(0.5)

        LCD.turn_light(1)

        while True:

            now = time.strftime('%m/%d %H:%M:%S', time.localtime(time.time()))

            ip=getLocalIP()

            LCD.print_lcd(1, 1, ip)

            time.sleep(0.2)

    4.4 LCD显示树莓派状态 lcd_status.py

        和显示IP地址类似,滚动显示树莓派温度,cpu使用率,内存信息和硬盘信息。

    #!/user/bin/env python

    import os

    import smbus

    import time

    import sys

    import socket

    import subprocess

    import lcd1602 as LCD

    def getLocalIP():

        ip = None

        try:

            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

            s.connect(('114.114.114.114', 0))

            ip = s.getsockname()[0]

        except:

            name = socket.gethostname()

            ip = socket.gethostbyname(name)

        if ip.startswith("127."):

            cmd = '''/sbin/ifconfig | grep "inet " | cut -d: -f2 | awk '{print $1}' | grep -v "^127."'''

            a = subprocess.Popen(

                cmd,

                shell=True,

                stdout=subprocess.PIPE,

                stderr=subprocess.PIPE)

            a.wait()

            out = a.communicate()

            ip = out[0].strip().split("\n")

            if len(ip) == 1 and ip[0] == "" or len(ip) == 0:

                return False

            ip = "over".join(ip)

        return ip

    # Return CPU temperature as a character string

    def getCPUtemperature():

        res = os.popen('vcgencmd measure_temp').readline()

        return(res.replace("temp=","").replace("'C\n",""))

    # Return RAM information (unit=kb) in a list

    # Index 0: total RAM

    # Index 1: used RAM

    # Index 2: free RAM

    def getRAMinfo():

        p = os.popen('free')

        i = 0

        while 1:

            i = i + 1

            line = p.readline()

            if i==2:

                return(line.split()[1:4])

    # Return % of CPU used by user as a character string

    def getCPUuse():

        return(str(os.popen("top -n1 | awk '/Cpu\(s\):/ {print $2}'").readline().strip()))

    # Return information about disk space as a list (unit included)

    # Index 0: total disk space

    # Index 1: used disk space

    # Index 2: remaining disk space

    # Index 3: percentage of disk used

    def getDiskSpace():

        p = os.popen("df -h /")

        i = 0

        while 1:

            i = i +1

            line = p.readline()

            if i==2:

                return(line.split()[1:5])

    if __name__ == '__main__':

        LCD.init_lcd()

        time.sleep(1)

        LCD.print_lcd(2, 0, 'Raspberry Pi')

        for x in xrange(1, 4):

            LCD.turn_light(0)

            LCD.print_lcd(4, 1, 'LIGHT OFF')

            time.sleep(0.5)

            LCD.turn_light(1)

            LCD.print_lcd(4, 1, 'LIGHT ON ')

            time.sleep(0.5)

            LCD.turn_light(1)

        while True:

            now = time.strftime('%m/%d %H:%M:%S', time.localtime(time.time()))

            ip=getLocalIP()

            # CPU informatiom

            CPU_temp = getCPUtemperature()

            CPU_usage = getCPUuse()

            # RAM information

            # Output is in kb, here I convert it in Mb for readability

            RAM_stats = getRAMinfo()

            RAM_total = round(int(RAM_stats[0]) / 1000,1)

            RAM_used = round(int(RAM_stats[1]) / 1000,1)

            RAM_free = round(int(RAM_stats[2]) / 1000,1)

            # Disk information

            DISK_stats = getDiskSpace()

            DISK_total = DISK_stats[0]

            DISK_used = DISK_stats[1]

            DISK_perc = DISK_stats[3]

            LCD.clear_lcd()

            LCD.print_lcd(0, 0, now)

            LCD.print_lcd(0, 1, ip)

            time.sleep(2)

            LCD.clear_lcd()

            LCD.print_lcd(0, 0, 'CPU Temperature='+CPU_temp)

            LCD.print_lcd(0, 1, 'CPU Use='+CPU_usage)

            time.sleep(2)

            LCD.clear_lcd()

            LCD.print_lcd(0, 0, 'RAM Total='+str(RAM_total)+'MB')

            LCD.print_lcd(0, 1, 'RAM Used='+str(RAM_used)+'MB')

            time.sleep(2)

            LCD.clear_lcd()

            LCD.print_lcd(0, 0, 'RAM Free='+str(RAM_free)+'MB')

            LCD.print_lcd(0, 1, 'DISK Total Space='+str(DISK_total)+'B')

            time.sleep(2)

            LCD.clear_lcd()

            LCD.print_lcd(0, 0, 'DISK Used Space='+str(DISK_used)+'B')

            LCD.print_lcd(0, 1, 'DISK Used Percentage='+str(DISK_perc))

            time.sleep(2)

    5、实际效果图

    6、设置开机启动

    修改 /etc/rc.local 文件,在 exit 0 前面增加一行后台运行lcd_status.py的代码:

    sudo  python  /home/pi/sensor/lcd_status.py &

    相关文章

      网友评论

        本文标题:树莓派通过C语言和python操作LCD液晶屏

        本文链接:https://www.haomeiwen.com/subject/gkkoaktx.html