如何用python做软件开发,用python开发软件的步骤

大家好,给大家分享一下如何用python做软件开发,很多人还不知道这一点。下面详细解释一下。现在让我们来看看!

Source code download: 本文相关源码

目录

前言

主要介绍linux系统下python应用开发。本文提供一些基本的使用方法,具体可以去看Python源码,或者可到 github 或 pypi 查找python画心的代码演示


一、python环境搭建

首先嵌入式系统得是Ubuntu

1.1 用APT安装python

sudo apt update #第一次使用apt需要更新
sudo apt -y install python3 #安装python3
sudo apt -y install python3-pip #安装pip工具

安装好可以用以下命令测试

python3 --version  	#查看 python 版本
pip3 --version		# 查看 pip3 版本

1.2 设置 python 和 pip 的默认版本

sudo ln -s /usr/bin/python3 /usr/bin/python #设置软链接,python默认使用python3
sudo ln -s /usr/bin/pip3 /usr/bin/pip #设置软链接,pip默认使用pip3

注意:使用 pip 工具安装软件包时,通常是在本机中进行编译的,通常由于性能不够导致编译时间非常长,还可能因为缺少某些库文件而安装失败。议先直接搜索一下是否能使用 apt 工具安装,它会从软件库中下载预先编译好的软件包,安装时间基本只取决于网络速度。需要安装更新版本或者 apt 找不到的包时才使用 pip 安装。

1.3 用 setuptools 工具安装软件包

  由于一些原因,我们只获取到了这些Python库包的源码。那么我们用 pip 工具或者 apt 工具就没有办法去安装了。这时我们可以使用 python 的 setuptools 工具,来通过库包源码进行 Python 库包的安装。

sudo apt -y install python3-setuptools	#setuptools 工具安装
sudo python3 setup.py install			#使用 setuptools 工具通过源码安装库

1.4 Python语法基础使用

有关Python的语法,参考以下文章:
python语法入门_python语法c for c in childs if c.type == 'axes-CSDN博客

代码编写好之后,在终端用如下命令运行:

python3 hello.py

二、GPIO输入输出

2.1 安装控制接口包

• python3-libgpiod:标准GPIO libgpiod 库的 python版本,只支持控制 IO 输入输出。
• python-periphery:支持GPIO、PWM、I2C、SPI、UART等多种接口的基础控制。
• Adafruit Blinka:支持GPIO、PWM、I2C、SPI、UART等,还带有一些常用传感器、OLED屏的应用示例。

2.2 libgpiod基本概念

2.2.1 实验准备

  GPIO 主要用来对外输出高低电平,控制 GPIO 时,基本都会涉及到 libgpiod 的控制,我们主要需要知道板卡引脚的命名方式即可。
  CPU 的 GPIO 引脚使用 (chip, line) 的方式命名,使用以下命令可以查看:

#在板卡上执行以下命令
gpioinfo
#若提示找不到命令,使用如下方式安装
sudo apt -y install gpiod libgpiod-dev

注意
1)部分GPIO可能会被系统占用,在使用前请根据需要修改 /boot/uEnv.txt 文件,在对应资源中加上#注释,可以取消加载
在这里插入图片描述
2)如出现 Permission denied 或类似字样,请注意用户权限,大部分操作硬件外设的功能,几乎都需要 root 用户权限,简单的解决方案是在执行语句前加入 sudo 或以 root 用户运行程序。

2.2.2 使用python3-libgpiod

①安装python3-libgpiod

# 在板卡使用如下命令安装
sudo apt -y install python3-libgpiod

# 测试及查看帮助
python3
import gpiod
help(gpiod)

②libgpiod 输出blink.py

import time
import gpiod

# 根据具体板卡的 LED 灯连接修改使用的 Chip 和 Line
LED_LINE_OFFSET = 19
#创建了一个 chip ID 为 3 的 gpiod.Chip 对象 chip3
chip3 = gpiod.Chip("3", gpiod.Chip.OPEN_BY_NUMBER)
#设置使用 chip3 对象的 line19 作为 led
led = chip3.get_line(LED_LINE_OFFSET)
#设置 LED 的 GPIO 控制方向为输出
led.request(consumer="LED", type=gpiod.LINE_REQ_DIR_OUT, default_vals=[0])

print(led.consumer())
try:
	while True:
		led.set_value(1)
		time.sleep(0.5)
		led.set_value(0)
		time.sleep(0.5)
finally:
	led.set_value(1)
	led.release()

2.3 使用python-periphery

①安装 python-periphery

sudo pip3 install python-periphery

②periphery 输入输出

"""Digital IO (Input/Output) using periphery"""
from periphery import GPIO

# 根据具体板卡的LED灯和按键连接修改使用的Chip和Line
LED_CHIP = "/dev/gpiochip3"
LED_LINE_OFFSET = 19

BUTTON_CHIP = "/dev/gpiochip4"
BUTTON_LINE_OFFSET = 1
#分别创建了 led 和 button 的 GPIO 输出、输入对象
led = GPIO(LED_CHIP, LED_LINE_OFFSET, "out")
button = GPIO(BUTTON_CHIP, BUTTON_LINE_OFFSET, "in")

try:
    while True:
    #直接使用按键的输入值控制 LED
        led.write(button.read())
finally:
    led.write(True)
    led.close()
    button.close()

2.4 使用 Adafruit Blinka

①安装 Adafruit Blinka

sudo apt -y install python3-libgpiod # 注:如在方法一中已安装,忽略此步
sudo pip3 install Adafruit-Blinka

②Adafruit-Blinka 输入输出

"""Digital IO (Input/Output) using Blinka"""
import board
import digitalio

# 根据具体板卡的LED灯和按键连接修改使用的GPIO
# LubanCat i.MX6ULL board, GPIO_PC32 = Pin 115
# 定义了 LED 使用的引脚 GPIO_PC32,并设置为输出方向
led = digitalio.DigitalInOut(board.GPIO_PC32)
led.direction = digitalio.Direction.OUTPUT

# LubanCat i.MX6ULL board, GPIO_PD17 = Pin 129
#定义了按键使用的引脚 GPIO_PD17,并设置为输入方向
button = digitalio.DigitalInOut(board.GPIO_PD17)
button.direction = digitalio.Direction.INPUT

try:
    while True:
    #直接使用按键的输入值控制 LED
        led.value = button.value
finally:
    led.value = True
    led.deinit()
    button.deinit()

三、PWM 输出

3.1 实验准备

  在板卡上的部分资源可能默认未被开启,在使用前请根据需要修改 /boot/uEnv.txt 文件,可添加对应设备树插件的加载,重启系统,以在系统中添加对应资源。
  如本节实验中,可能在系统中默认没有使能 PWM 的功能,所以要将 PWM 的功能开启。同时本例中使用 PWM 功能进行演示时,部分板卡会利用到 LED 灯占用的引脚,所以还要将对应的 LED 设备树插件取消加载,否则被占的引脚无法使用 libgpiod 等的方式进行控制。
在这里插入图片描述

# 在终端中输入如下命令,可以查看到 PWM 资源:
ls /sys/class/pwm/

3.2 使用 python-periphery

①为方便观察实验现象,建议先将其他两个 LDE 灯调整为常灭状态,复制如下命令

echo 0 > /sys/class/pwm/pwmchip7/export
echo 1000000 > /sys/class/pwm/pwmchip7/pwm0/period
echo "inversed" > /sys/class/pwm/pwmchip7/pwm0/polarity
echo 1 > /sys/class/pwm/pwmchip7/pwm0/enable
echo 0 > /sys/class/pwm/pwmchip7/unexport

②使用 python-periphery 库进行 PWM 输出

"""periphery库 PWM测试."""
import time
from periphery import PWM

# 打开 PWM 3, channel 0 ,对应开发板上PWM3外设

try:
    pwm = PWM(2, 0)
    # 设置PWM输出频率为 1 kHz
    pwm.frequency = 1e3
    # 设置占空比为 50%
    pwm.duty_cycle = 0.50
    # 开启PWM输出
    pwm.enable()
    while True:
        for i in range(0, 9):
            time.sleep(0.1)
            pwm.duty_cycle += 0.05
        for i in range(0, 9):
            time.sleep(0.1)
            pwm.duty_cycle -= 0.05
        if pwm.duty_cycle == 0.0:
            time.sleep(1)
finally:
    pwm.close()

3.3 使用 Adafruit Blinka

import time
import board
import pulseio
#定义了 LED 使用的引脚为板上的 PWM 资源:PWM1,并设置输出的 PWM 频率为 5000,占空比为 0
led = pulseio.PWMOut(board.PWM1, frequency=5000, duty_cycle=0)
#通过 for 循环语句,调整 PWM 输出的占空比,实现 LED 灯的呼吸效果
while True:
    for i in range(100):
        # PWM LED up and down
        if i < 50:
            led.duty_cycle = int(i * 2 * 65535 / 100)  # Up
        else:
            led.duty_cycle = 65535 - int((i - 50) * 2 * 65535 / 100)  # Down
        time.sleep(0.01)

四、UART 通讯

4.1 添加UART资源

  在板卡上的部分资源可能默认未被开启,在使用前请根据需要修改 /boot/uEnv.txt 文件,可添加对应设备树插件的加载,重启系统,以在系统中添加对应资源。
在这里插入图片描述

# 在终端中输入如下命令,可以查看到 UART 资源:
ls /dev/ttymxc*

4.2 使用 pyserial

①安装 pyserial

sudo pip3 install pyserial

②示例代码

""" pyserial uart 测试 """
import serial


# 打开uart3,设置串口波特率为115200,数据位为8,无校验位,停止位为1,不使用流控制,以非阻塞模式打开串口,等待时间为1s
with serial.Serial(
    "/dev/ttymxc2",
    baudrate=115200,
    bytesize=serial.EIGHTBITS,
    stopbits=serial.STOPBITS_ONE,
    parity=serial.PARITY_NONE,
    timeout=1,
) as uart3:
    # 使用申请的串口发送字节流数据 "Hello World!\n"
    uart3.write(b"Hello World!\n")

    # 以非阻塞的方式打开的串口,在读取串口接收的数据时,该函数返回条件二者满足其一,一、读取到128个字节,二、读取时间超过1秒
    buf = uart3.read(128)

    # 注:Python读取出来的数据类型为:bytes
    # 打印原始数据
    print("原始数据:\n", buf)
    # 转码为gbk字符串,可以显示中文
    data_strings = buf.decode("gbk")
    # 打印读取的数据量及数据内容
    print("读取到 {:d} 个字节 , 以字符串形式打印:\n {:s}".format(len(buf), data_strings))

4.3 使用 python-periphery

""" periphery uart 测试 """
from periphery import Serial

try:
    # 申请串口资源/dev/ttymxc2,设置串口波特率为115200,数据位为8,无校验位,停止位为1,不使用流控制
    serial = Serial(
        "/dev/ttymxc2",
        baudrate=115200,
        databits=8,
        parity="none",
        stopbits=1,
        xonxoff=False,
        rtscts=False,
    )
    # 使用申请的串口发送字节流数据 "Hello World!\n"
    serial.write(b"Hello World!\n")

    # 读取串口接收的数据,该函数返回条件二者满足其一,一、读取到128个字节,二、读取时间超过1秒
    buf = serial.read(128, 1)

    # 注:Python读取出来的数据类型为:bytes
    # 打印原始数据
    print("原始数据:\n", buf)
    # 转码为gbk字符串,可以显示中文
    data_strings = buf.decode("gbk")
    # 打印读取的数据量及数据内容
    print("读取到 {:d} 个字节 , 以字符串形式打印:\n {:s}".format(len(buf), data_strings))
finally:
    # 释放申请的串口资源
    serial.close()

五、I2C通讯

5.1 添加I2C资源

  在使用前请根据需要修改 /boot/uEnv.txt 文件,可添加对应设备树插件的加载,重启系统,以在系统中添加对应资源。

  屏蔽内容如下

# 以具体板卡 I2C 设备树插件内容为例:
dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-i2c1.dtbo
dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-i2c2.dtbo
# 在终端中输入如下命令,可以查看到 I2C 资源:
ls /sys/bus/i2c/devices

5.2 使用 python-periphery

""" periphery i2c 测试 使用0.96寸OLED模块 """
import time
from periphery import I2C

# 打开 i2c-1 控制器
i2c = I2C("/dev/i2c-1")

# 设备从机地址0x3c,即OLED模块地址
I2CSLAVEADDR = 0x3C

# 使用periphery i2c库读取功能测试
def i2c_read_reg(devregaddr):
    """
    使用periphery i2c库读取功能测试
    """
    # 构造数据结构
    # 第一个Message为要读取的设备地址
    # 第二个Message用于存放读取回来的消息,注意其中添加的read=True
    msgs = [I2C.Message([devregaddr]), I2C.Message([0x00], read=True)]
    # 发送消息,发送到i2cSlaveAddr
    i2c.transfer(I2CSLAVEADDR, msgs)
    print("从寄存器 0x{:02x} 读取出: 0x{:02x}".format(devregaddr, msgs[1].data[0]))


def oled_write_cmd(cmd):
    """
    使用periphery i2c库发送功能测试
    """
    msgs = [I2C.Message([0x00, cmd])]
    i2c.transfer(I2CSLAVEADDR, msgs)


def oled_write_data(data):
    """
    使用periphery i2c库发送功能测试
    """
    msgs = [I2C.Message([0x40, data])]
    i2c.transfer(I2CSLAVEADDR, msgs)


def oled_init():
    """
    使用OLED模块进行代码功能测试 0.96寸OLED模块初始化
    """
    time.sleep(1)
    oled_write_cmd(0xAE)
    oled_write_cmd(0x20)
    oled_write_cmd(0x10)
    oled_write_cmd(0xB0)
    oled_write_cmd(0xC8)
    oled_write_cmd(0x00)
    oled_write_cmd(0x10)
    oled_write_cmd(0x40)
    oled_write_cmd(0x81)
    oled_write_cmd(0xFF)
    oled_write_cmd(0xA1)
    oled_write_cmd(0xA6)
    oled_write_cmd(0xA8)
    oled_write_cmd(0x3F)
    oled_write_cmd(0xA4)
    oled_write_cmd(0xD3)
    oled_write_cmd(0x00)
    oled_write_cmd(0xD5)
    oled_write_cmd(0xF0)
    oled_write_cmd(0xD9)
    oled_write_cmd(0x22)
    oled_write_cmd(0xDA)
    oled_write_cmd(0x12)
    oled_write_cmd(0xDB)
    oled_write_cmd(0x20)
    oled_write_cmd(0x8D)
    oled_write_cmd(0x14)
    oled_write_cmd(0xAF)


def oled_fill(filldata):
    """
    清空OLED屏幕
    """
    for i in range(8):
        oled_write_cmd(0xB0 + i)
        # page0-page1
        oled_write_cmd(0x00)
        # low column start address
        oled_write_cmd(0x10)
        # high column start address
        for _ in range(128):
            oled_write_data(filldata)


# 代码测试
try:
    # 初始化OLED屏幕,SSD1306必要
    oled_init()
    # 清空OLED屏幕
    oled_fill(0xFF)
    # 读取寄存器测试
    i2c_read_reg(0x10)
finally:
    print("测试正常结束")
    # 释放资源
    i2c.close()

5.3 使用Adafruit Blinka

""" blinka i2c 测试 使用0.96寸OLED模块 """
# pylint: disable=W0401
from board import *
import busio

# 初始化OLED命令字节数组
OledInitBuf = bytes(
    [
        0xAE,
        0x20,
        0x10,
        0xB0,
        0xC8,
        0x00,
        0x10,
        0x40,
        0x81,
        0xFF,
        0xA1,
        0xA6,
        0xA8,
        0x3F,
        0xA4,
        0xD3,
        0x00,
        0xD5,
        0xF0,
        0xD9,
        0x22,
        0xDA,
        0x12,
        0xDB,
        0x20,
        0x8D,
        0x14,
        0xAF,
    ]
)

# 数据发送、接受缓冲区
OutBuffer = bytearray(1)
InBuffer = bytearray(1)

try:
    # 申请i2c资源
    # pylint: disable=E0602
    i2c = busio.I2C(SCL, SDA)
    # 扫描I2C设备地址,测试
    print("挂载I2C总线上的I2C设备地址有")
    for i in i2c.scan():
        print("0x%02x " % i)

    # IIC发送命令测试(writeto),初始化OLED
    # 初始化OLED,初始命令存放于字节数组oledInitBuf中
    i2c.writeto(0x3C, OledInitBuf)

    # IIC读取命令测试(writeto_then_readfrom),读取OLED的0x10寄存器
    # 发送数据,发送数据完成后不产生停止信号,并重新生产起始信号进行读取。

    # 发送数据内容存放在字节数组outBuffer中,内容为OLED寄存器地址:0x10
    OutBuffer[0] = 0x10
    # 发送,发送寄存器地址0x10,并将寄存器地址0x10下的内容读取到inBuffer中
    i2c.writeto_then_readfrom(0x3C, OutBuffer, InBuffer)
    # 打印数据信息
    print("(writeto_then_readfrom)读取到的内容为:0x%02x" % InBuffer[0])

    # IIC读取测试(readfrom_into),从设备内部的地址读,则不需要指定读取的地址
    i2c.readfrom_into(0x3C, InBuffer)
    # 打印数据信息
    print("(readfrom_into)读取到的内容为:0x%02x" % InBuffer[0])

    # OLED清屏
    for i in range(8):
        i2c.writeto(0x3C, bytearray([0x00, 0xB0 + i]))  # page0-page1
        i2c.writeto(0x3C, bytearray([0x00, 0x00]))  # low column start address
        i2c.writeto(0x3C, bytearray([0x00, 0x10]))  # high column start address
        for j in range(128):
            i2c.writeto(0x3C, bytearray([0x40, 0xFF]))

finally:
    # 释放i2c总线资源
    i2c.deinit()

六、SPI 通讯

6.1 添加 SPI 资源

# 以板卡 SPI 设备树插件内容为例
dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-ecspi3.dtbo
# 在终端中输入如下命令,可以查看到 SPI 资源:
ls /dev/spi*

6.2 使用 python-periphery

""" periphery spi 测试 """
from periphery import SPI

# 待发送数据列表
data_out = [0xAA, 0xBB, 0xCC, 0xDD]

try:
    # 申请SPI资源,打开 spidev2.0 控制器,配置SPI主机为工作模式0、工作速率为1MHz
    spi = SPI("/dev/spidev2.0", 0, 1000000)

    # 发送数据,同时接收数据到data_in列表中
    data_in = spi.transfer(data_out)

    # 打印发送的数据内容
    print("发送的数据: [0x{:02x}, 0x{:02x}, 0x{:02x}, 0x{:02x}]".format(*data_out))
    print("接收到的数据: [0x{:02x}, 0x{:02x}, 0x{:02x}, 0x{:02x}]".format(*data_in))
finally:
    # 关闭申请的SPI资源
    spi.close()

6.3 使用Adafruit Blinka

""" blinka spi 测试 """
import busio

# pylint: disable=W0401
from board import *

# 数据发送、接受缓冲区
OutBuffer = [0xAA, 0xBB, 0xCC, 0xDD]
InBuffer = bytearray(4)

try:
    # 申请spi资源
    # pylint: disable=E0602
    spi = busio.SPI(SCLK, MOSI, MISO)

    # 配置时先锁定SPI
    spi.try_lock()
    # 配置SPI主机工作速率为1MHz、时钟极性为0、时钟相位为0、单个数据位数为8位
    spi.configure(1000000, 0, 0, 8)
    # 配置操作完成解锁
    spi.unlock()

    # SPI通讯,发送的同时也进行读取,发送的数据存放在OutBuffer,读取的数据存放在InBuffer
    spi.write_readinto(OutBuffer, InBuffer)

    print(
        "(write_readinto)接收到的数据: [0x{:02x}, 0x{:02x}, 0x{:02x}, 0x{:02x}]".format(
            *InBuffer
        )
    )

    # SPI通讯,只写使用方法演示
    spi.write(OutBuffer)
    print(
        "(OutBuffer)发送的数据: [0x{:02x}, 0x{:02x}, 0x{:02x}, 0x{:02x}]".format(*OutBuffer)
    )

    InBuffer = [0, 0, 0, 0]
    # SPI通讯,只读使用方法演示
    spi.readinto(InBuffer)
    print(
        "(readinto)接收到的数据: [0x{:02x}, 0x{:02x}, 0x{:02x}, 0x{:02x}]".format(*InBuffer)
    )
finally:
    # 释放spi资源
    spi.deinit()

七、LCD 显示

7.1 环境搭建

  Pygame 是 Python 库中用于开发游戏的一种工具,或许这么说有点限制 Pygame 的用法。Pygame不仅可以用于游戏开发,还可以用于显示处理,多媒体设备处理等等方面,该库提供了许多多媒体、显示设备的操作功能。

7.1.1 添加 LCD 资源

  屏蔽以下文件

# 以鲁班猫 i.MX6ULL MINI 板卡 LCD 设备树插件及触摸设备树插件内容为例:
dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-lcd.dtbo,clock-frequency_0=9000000,hactive_0=480,vactive_0=272,hfront-porch_0=8,hback-porch_0=2,hsync-len_0=41,vback-porch_0=4,vfront-porch_0=4,vsync-len_0=10,bits-per-pixel_0=24 
dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-touch-capacitive-goodix.dtbo
# 在终端中输入如下命令,可以查看到显示设备资源:
ls /dev/fb*
7.1.2 安装Pygame库:

①使用 apt 工具安装

# 在终端中输入如下命令,安装 Pygame 库:
sudo apt -y install python3-pygame

②Pygame 库使用
  可以使用以下命令不断地往 /dev/fb0写入随机数据,使得屏幕花屏

# 在终端中输入如下命令测试:
cat /dev/urandom > /dev/fb0

  也可以通过 fbset 工具,在用户空间查看显示设备相关参数:

# 安装 fbset 工具
sudo apt update
sudo apt -y install fbset
7.1.2 安装 fbset 工具
sudo apt update
sudo apt -y install fbset

2)调用

import os
import time
import pygame

7.2 示例代码

""" 使用pygame进行屏幕测试 """
import os
import sys
import time
import pygame


class PyScope:
    """ 定义一个PyScope类,进行屏幕测试 """

    screen = None

    def __init__(self):
        "PyScope类的初始化方法,使用framebuffer构造pygame会使用到的图像缓冲区"
        # Based on "Python GUI in Linux frame buffer"
        # http://www.karoltomala.com/blog/?p=679
        # 尝试获取环境目录下定义的显示设备
        disp_no = os.getenv("DISPLAY")
        if disp_no:
            print("I'm running under X display = {0}".format(disp_no))

        # 检查何种驱动方式可用
        # 从fbcon开始,因为directfb会挂起复合输出
        drivers = ["fbcon", "directfb", "svgalib"]
        # 设置系统环境为无鼠标模式
        os.environ["SDL_NOMOUSE"] = "1"
        found = False
        # 根据枚举的framebuffer设备类型适配驱动
        for driver in drivers:
            # 确保环境变量SDL_VIDEODRIVER被设置
            if not os.getenv("SDL_VIDEODRIVER"):
                os.putenv("SDL_VIDEODRIVER", driver)
            try:
                print("Driver: {0} is checking now...".format(driver))
                # 尝试初始化显示设备功能
                pygame.display.init()
            except pygame.error:
                # 出错,打印提示
                print("Driver: {0} failed.".format(driver))
                continue
            print("Driver: {0} is suitable.".format(driver))
            found = True
            break

        if not found:
            raise Exception("No suitable video driver found!")

        # 获取显示设备的大小
        size = (pygame.display.Info().current_w, pygame.display.Info().current_h)
        # 打印显示设备的大小
        print("Framebuffer size: %d x %d" % (size[0], size[1]))
        # 设置pygame使用的窗口显示为全屏幕
        self.screen = pygame.display.set_mode(size, pygame.FULLSCREEN)
        # 清屏
        self.screen.fill((0, 0, 0))
        # 初始化字体库
        pygame.font.init()
        # 更新屏幕,以显示写入缓冲区的内容
        pygame.display.update()

    def __del__(self):
        "退出pygame库的时候会调用该方法,可以在此添加资源释放操作"

    def test(self):
        "PyScope类的测试方法,使屏幕填充为红色"
        # 填充屏幕为红色,其rgb值为(255, 0, 0)
        red = (255, 0, 0)
        # 填充
        self.screen.fill(red)
        # 更新屏幕,以显示写入缓冲区的内容
        pygame.display.update()


# 创建一个测试实例,开始测试
scope = PyScope()
# 调用scope类的测试方法
scope.test()
time.sleep(3)
sys.exit()

  以上代码值得一提的是 init 方法中,会检查系统当前设备所处平台,并根据设备情况匹配驱动方式,最终该代码会在对应设备上全屏填充红色像素

八、CAN 总线通讯

8.1 python-can 库

  python-can 是 Python 库下的一个库包,它实现了 CAN 总线通讯中许多的通讯操作,它对不同的硬件设备提供了通用的抽象接口,方便 Python 开发人员使用该库进行 CAN 通讯中的数据收发。

①添加CAN资源

# 以鲁班猫 i.MX6ULL Pro 板卡 CAN 设备树插件内容为例:
dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-can1.dtbo

在这里插入图片描述
②查看设备是否已经正常添加

# 在终端中输入如下命令,可以查看到 CAN 设备资源:
ifconfig -a

在这里插入图片描述

8.2 python-can库安装

  使用 apt 工具安装

sudo apt -y install python3-can

8.3 python-can 库使用

""" python can 测试 """
import sys
import time
import threading
import can


def msg_recv(device_x):
    "接收消息功能"
    print("success: msg_recv Thread is running!")
    # 将can_mask转换为二进制形式,can_mask中为1的位,用于过滤接收到的帧
    # 举例                     id: 0 0
    #                        mask: 1 0 则接收到消息的ID中,mask为1对应id中的位,必须与id一致,为0
    # 如接收到了四个id的消息  id1: 0 0 此条消息被放行
    #                         id2: 0 1 此条消息被放行
    #                         id3: 1 0 此条消息被过滤
    #                         id4: 1 1 此条消息被过滤
    # 过滤器配置示例如下。第一条规则,接收所有标准帧,第二条规则,接收拓展帧中id为0x300的消息。
    can_filters = [
        {"can_id": 1, "can_mask": 0x0, "extended": False},
        {"can_id": 0x300, "can_mask": 0x1FFFFFFF, "extended": True},
    ]
    # 应用过滤器配置
    device_x.set_filters(can_filters)
    # 查询退出线程是否退出,如果为真,则说明用户期望程序退出,退出本线程循环,线程结束
    while tasks_quitThread.is_alive():
        try:
            # 接收can消息
            msg = device_x.recv(1)
            if msg is not None:
                print("success: ", msg)
        except can.CanError:
            print("error: 接收消息时出错,请检查设备是否启用及状态正常")


def msg_send(device_x):
    "发送消息功能"
    print("success: msg_send Thread is running!")
    # 构造发送的CAN消息结构,ID为0xC0FFEE,数据内容包含在data中,is_extended_id为拓展ID标识
    msg = can.Message(
        arbitration_id=0xC0FFEE, data=[0, 25, 0, 1, 3, 1, 4, 1], is_extended_id=True
    )
    # 查询退出线程是否退出,如果为真,则说明用户期望程序退出,退出本线程循环,线程结束
    while tasks_quitThread.is_alive():
        try:
            # 发送构造的CAN消息
            device_x.send(msg)
            # 打印发送提示
            print(f"success: 消息已发送至 {device_x.channel_info}")
        except can.CanError:
            print("error: 消息发送出错,请检查设备是否启用及状态正常!")
        # 两秒后再次发送
        time.sleep(2)


def tasks_quit():
    "程序退出功能"
    print("success: tasks_quit Thread is running!")
    exitright = "e"
    while exitright not in ["q", "Q"]:
        # 获取用户输入,如果为q则退出程序
        exitright = input(
            """
***********************************
**输入字母q后,按下回车以退出程序**
***********************************
"""
        )
        # 线程退出


# 打印运行程序前提示信息
print(
    "information: 执行本程序前,请先启用can设备。命令如下:\
    \nsudo ip link set can0 type can bitrate 1000000\nsudo ip link set can0 up"
)
# 打开CAN设备,CAN设备类型为socketcan,channel为can0,可使用ifconfig -a命令查看。
with can.interface.Bus(
    bustype="socketcan", channel="can0", bitrate=1000000
) as device_can0:
    # 创建线程:监听程序退出线程、发送can消息线程、接收can消息线程
    try:
        print("information: 开始创建 tasks_quitThread 线程!")
        tasks_quitThread = threading.Thread(target=tasks_quit, daemon=True)
        print("information: 开始创建 msg_sendThread 线程!")
        msg_sendThread = threading.Thread(
            target=msg_send, daemon=True, args=(device_can0,)
        )
        print("information: 开始创建 msg_recvThread 线程!")
        msg_recvThread = threading.Thread(
            target=msg_recv, daemon=True, args=(device_can0,)
        )
        # 开启线程
        print("information: 开始启动 tasks_quitThread 线程!")
        tasks_quitThread.start()
        print("information: 开始启动 msg_sendThread 线程!")
        msg_sendThread.start()
        print("information: 开始启动 msg_recvThread 线程!")
        msg_recvThread.start()
    # pylint: disable=W0702
    except:
        print("error: 创建或启动线程中出错!")
        sys.exit()

    # 等待线程结束
    tasks_quitThread.join()
    print("information: tasks_quitThread结束")
    msg_sendThread.join()
    print("information: msg_sendThread结束")
    msg_recvThread.join()
    print("information: msg_recvThread结束")
    # 所有正常线程结束,退出程序
    sys.exit()

8.4 实验步骤

①输入如下命令来启用 CAN 总线设备

# 在终端中输入如下命令,可以启用 CAN 总线设备:
sudo ip link set can0 type can bitrate 1000000;sudo ip link set can0 up

启动后如下图所示:
在这里插入图片描述
②运行代码来查看一下现象

# 在终端中输入如下命令:
python3 canbus_test.py

九、web开发

9.1 Web 库 - Flask

  Flask 是一个 Python 实现的 Web 开发微框架,我们可以在鲁班猫板卡上安装 Python-flask 库,并通过编写一些测试代码来使用该库。在我们的板卡上部署一个简单的 web 页面。

9.1.1 Flask 库安装
# 在终端中输入如下命令,安装 flask 库:
sudo apt -y install python3-flask
9.1.2 Flask库使用

①新建工程目录

# 新建一个目录,用于存放我们的 web 项目,并进入目录
mkdir webapp
cd webapp
# 创建我们 webapp 的目录
mkdir app
mkdir app/static
mkdir app/templates
mkdir tmp

②在app目录下,创建__init__.py文件,建一个简单的初始化脚本,内容如下:

from flask import Flask

app = Flask(__name__)
# pylint: disable=C0413
from app import views

③在app目录下,创建视图函数 views.py,
  在 Flask 中,视图被编写成 Python 函数。每一个视图函数映射到一个或多个请求的 URL,让我们编写第一个视图函数 views.py

from app import app


@app.route("/")
@app.route("/index")
def index():
    return "Hello, Lubancat!"

④在 webapp 目录下,创建run.py脚本,用于启动我们的应用程序的 Web 服务器

#!/usr/bin/python3
from app import app

app.run(debug=True, host="192.168.7.2")

⑤run.py 创建完成之后需要赋予一些权限

# 添加权限
chmod a+x run.py
9.1.3 运行webapp

①运行

# 运行 app
./run.py

在这里插入图片描述

②访问网址
  app 已经正常启动,终端也已打印出了服务信息。信息中提示 web 已经映射到了我们在前面代码中设置的主机 192.168.7.2 端口号为 5000,故我们可以通过此网址访问 http://192.168.7.2:5000/ 我们部署好的网页
在这里插入图片描述

9.2 Web 库 - Django

  Django 是 Python 编程语言驱动的一个开源模型-视图-控制器(MVC)风格的 Web 应用程序框架。也是 Web 开发的中主流的框架

9.2.1 Django 库安装
# 在终端中输入如下命令,安装 Django 库:
sudo apt -y install python3-django
9.2.2 Django库使用

①新建工程目录

# 新建一个目录,用于存放我们的 web 项目,并进入目录
mkdir webapp
cd webapp

②添加代码文件及配置
  使用 Django 自带的管理器 django-admin,我们可以快速新建一个工程模板。

# 在终端中输入如下命令:
django-admin startproject Lubancat
# 待指令执行完毕后,当前目录下会自动生成项目文件夹:Lubancat,进入文件夹
cd ./Lubancat/

在这里插入图片描述
③接下来我们需要修改一下项目中的配置文件,以允许外部主机访问我们的鲁班猫板卡。进入到项目文件夹 Lubancat 中的 Lubancat 目录中,并修改 settings.py 文件。

# 在终端中输入如下命令:
cd ./Lubancat/
# 修改配置文件
nano settings.py
# 找到 ALLOWED_HOSTS 配置,并修改为如下内容,保存退出:
ALLOWED_HOSTS = ['*']
9.2.3 启动 webapp

①回到项目文件夹 Lubancat 中,运行其目录下的 manage.py 文件,启动服务器

# 在终端中输入如下命令:
python3 manage.py runserver 192.168.7.2:5001

在这里插入图片描述
webapp 已经正常启动,终端也已打印出了服务信息。信息中提示 web 已经映射到了我们在前面代码中设置的主机 192.168.7.2 端口号为 5001,故我们可以通过此网址访问 http://192.168.7.2:5001/我们部署好的网页。
在这里插入图片描述

  • 11
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值