【雕爷学编程】MicroPython手册之 Teensy 4.1 软件 I2C 总线

在这里插入图片描述
MicroPython是为了在嵌入式系统中运行Python 3编程语言而设计的轻量级版本解释器。与常规Python相比,MicroPython解释器体积小(仅100KB左右),通过编译成二进制Executable文件运行,执行效率较高。它使用了轻量级的垃圾回收机制并移除了大部分Python标准库,以适应资源限制的微控制器。

MicroPython主要特点包括:
1、语法和功能与标准Python兼容,易学易用。支持Python大多数核心语法。
2、对硬件直接访问和控制,像Arduino一样控制GPIO、I2C、SPI等。
3、强大的模块系统,提供文件系统、网络、图形界面等功能。
4、支持交叉编译生成高效的原生代码,速度比解释器快10-100倍。
5、代码量少,内存占用小,适合运行在MCU和内存小的开发板上。
6、开源许可,免费使用。Shell交互环境为开发测试提供便利。
7、内置I/O驱动支持大量微控制器平台,如ESP8266、ESP32、STM32、micro:bit、掌控板和PyBoard等。有活跃的社区。

MicroPython的应用场景包括:
1、为嵌入式产品快速构建原型和用户交互。
2、制作一些小型的可 programmable 硬件项目。
3、作为教育工具,帮助初学者学习Python和物联网编程。
4、构建智能设备固件,实现高级控制和云连接。
5、各种微控制器应用如物联网、嵌入式智能、机器人等。

使用MicroPython需要注意:
1、内存和Flash空间有限。
2、解释执行效率不如C语言。
3、部分库函数与标准版有差异。
4、针对平台优化语法,订正与标准Python的差异。
5、合理使用内存资源,避免频繁分配大内存块。
6、利用原生代码提升速度关键部位的性能。
7、适当使用抽象来封装底层硬件操作。

总体来说,MicroPython让Python进入了微控制器领域,是一项重要的创新,既降低了编程门槛,又提供了良好的硬件控制能力。非常适合各类物联网和智能硬件的开发。
在这里插入图片描述
Teensy 4.1是一款基于ARM Cortex-M7的高性能开发板,具有以下特点:

1、处理器:Teensy 4.1使用了恩智浦的i.MX RT1060处理器,它是一款交叉处理器,具有微控制器的功能,速度与微型计算机相当。它的运行频率高达600 MHz,可提供高达3000 DMIPS的性能,以及浮点运算单元和加密加速器。
2、内存:Teensy 4.1配备了1024 KB的RAM(其中512 KB是紧密耦合的),8 MB的Flash(其中64 KB用于恢复和EEPROM模拟),以及两个位置可以选择添加更多的QSPI内存芯片。
3、I/O引脚:Teensy 4.1共有55个数字输入/输出引脚,其中35个支持PWM输出,18个支持模拟输入。它还提供了8个串口,3个SPI端口,3个I2C端口,2个I2S/TDM数字音频端口,3个CAN总线(其中一个支持CAN FD),以及一个SDIO(4位数据)原生SD卡端口12。
4、以太网:Teensy 4.1包含了一个以太网控制器和一个以太网PHY芯片(DP83825),支持10/100 Mbit的速度。连接以太网电缆只需要一个RJ45磁插孔套件。
5、USB主机:Teensy 4.1提供了一个USB主机端口,支持480 Mbit/sec的速度。它可以连接USB设备,如键盘、鼠标、MIDI设备等。
6、RTC:Teensy 4.1支持实时时钟(RTC),可以通过连接一个3V纽扣电池来保持日期和时间。
7、LED:Teensy 4.1有一个内置的GPIO指示灯LED,连接在引脚13上。

在这里插入图片描述
MicroPython是一种基于Python语言的微控制器开发平台,而Teensy 4.1是一款强大的开发板,支持MicroPython,并且具备软件I2C(双线串行总线)总线功能。

主要特点:

灵活性:软件I2C总线是通过软件代码实现的,可以在任意GPIO引脚上模拟I2C通信。这意味着开发者可以根据实际需求选择合适的引脚进行数据通信。

低成本:软件I2C总线不需要额外的硬件支持,只需使用微控制器的GPIO引脚即可实现I2C通信。这降低了成本和复杂性,适合一些简单的应用场景。

主从模式支持:软件I2C总线可以同时充当主设备和从设备的角色。这意味着Teensy 4.1可以作为I2C总线的主设备发送指令,也可以作为从设备接收指令。

可扩展性:软件I2C总线可以连接多个I2C设备,如传感器、存储器等。通过适当的软件设计,Teensy 4.1可以与多个I2C设备进行通信,实现复杂应用的扩展和功能增强。

应用场景:

传感器数据采集:软件I2C总线可以与各种传感器(如温度传感器、湿度传感器等)进行通信,实现数据采集和监测。通过适当的软件编程,可以读取传感器的数据并进行实时处理。

外设控制:Teensy 4.1的软件I2C总线可以与外设设备(如LED显示屏、触摸屏等)进行通信,实现对外设的控制和操作。例如,可以通过软件I2C总线发送命令来控制LED的亮度和颜色。

存储器扩展:软件I2C总线可以与存储器设备(如EEPROM、Flash存储器等)进行通信,实现数据的读写操作。这对于需要存储和检索大量数据的应用场景非常有用。

需要注意的事项:

引脚选择:在使用Teensy 4.1的软件I2C总线时,需要选择合适的GPIO引脚作为I2C总线的数据线(SDA)和时钟线(SCL)。确保选择的引脚与外设的I2C接口兼容,并避免与其他引脚冲突。

时序控制:软件I2C总线的时序控制由软件代码实现,需要合理地编写时序控制程序以确保数据的准确传输。时序错误可能导致通信失败或数据错误。

上拉电阻:I2C总线需要使用上拉电阻将数据线和时钟线拉高。在使用软件I2C总线时,需要正确配置引脚的上拉电阻,以确保总线的正常运行。

速度和稳定性:软件I2C总线的速度受限于软件代码的执行速度,相比硬件I2C总线速度较慢。在高速传输和实时性要求较高的应用中,可能需要考虑使用硬件I2C总线。

在这里插入图片描述
案例一:读取EEPROM数据

from machine import Pin, I2C
import time

# 定义I2C引脚
scl = Pin(5, Pin.OUT)
sda = Pin(4, Pin.IN)

# 初始化I2C总线
i2c = I2C(scl=scl, sda=sda)

# 写入数据到EEPROM
address = 0x50
data = [0x01, 0x02, 0x03]
i2c.writeto(address, data)
time.sleep_ms(100)

# 从EEPROM读取数据
read_data = i2c.readfrom(address, 3)
print("读取的数据:", read_data)

要点解读:这个程序首先导入了Pin和I2C类,然后定义了I2C的SCL和SDA引脚。接着,使用这两个引脚初始化了一个I2C对象。在写入数据到EEPROM后,程序暂停100毫秒以确保数据被正确写入。最后,程序从EEPROM读取3个字节的数据并打印出来。

案例二:通过I2C通信控制LED灯

from machine import Pin, I2C
import time

# 定义I2C引脚
scl = Pin(5, Pin.OUT)
sda = Pin(4, Pin.IN)
led = Pin(13, Pin.OUT)

# 初始化I2C总线
i2c = I2C(scl=scl, sda=sda)

# 设置LED灯状态为亮
def turn_on_led():
    i2c.writeto(0x00, [0x01])
    time.sleep_ms(100)

# 设置LED灯状态为灭
def turn_off_led():
    i2c.writeto(0x00, [0x00])
    time.sleep_ms(100)

# 通过I2C通信控制LED灯
turn_on_led()
time.sleep_ms(500)
turn_off_led()

要点解读:这个程序首先导入了Pin、I2C类以及time模块。然后,定义了I2C的SCL和SDA引脚以及LED灯的引脚。接着,使用这两个引脚初始化了一个I2C对象。在定义了两个函数turn_on_led和turn_off_led用于控制LED灯的状态后,程序调用这两个函数来控制LED灯的亮灭。

案例三:通过I2C通信读取温度传感器数据

from machine import Pin, I2C
import time

# 定义I2C引脚
scl = Pin(5, Pin.OUT)
sda = Pin(4, Pin.IN)
temp_sensor = Pin(12, Pin.OUT)

# 初始化I2C总线
i2c = I2C(scl=scl, sda=sda)

# 设置温度传感器地址
temp_sensor_address = 0x48

# 通过I2C通信读取温度传感器数据
def read_temperature():
    i2c.writeto(temp_sensor_address, [0x00])
    time.sleep_ms(100)
    raw_data = i2c.readfrom(temp_sensor_address, 6)
    temp = (raw_data[0] << 16 | raw_data[1] << 8 | raw_data[2]) * 0.0625
    return temp

# 读取温度传感器数据并显示
temp = read_temperature()
print("当前温度:{:.2f}℃".format(temp))

要点解读:这个程序首先导入了Pin、I2C类以及time模块。然后,定义了I2C的SCL和SDA引脚以及温度传感器的引脚。接着,使用这两个引脚初始化了一个I2C对象。在定义了一个函数read_temperature用于读取温度传感器数据后,程序调用这个函数来读取温度数据并显示。

案例四:使用软件I2C总线读取温度传感器数据

import machine  
import utime  
  
class TempSensor:  
    def __init__(self, sda, scl):  
        self.sda = machine.Pin(sda, machine.Pin.OUT)  
        self.scl = machine.Pin(scl, machine.Pin.OUT)  
          
    def start(self):  
        self.sda.value(1)  
        self.scl.value(1)  
        utime.sleep_us(4)  
        self.sda.value(0)  
        utime.sleep_us(4)  
        self.scl.value(0)  
          
    def stop(self):  
        self.scl.value(1)  
        utime.sleep_us(4)  
        self.sda.value(1)  
          
    def write_byte(self, byte):  
        for bit in range(8):  
            if byte & 0x80:  
                self.sda.value(1)  
            else:  
                self.sda.value(0)  
            byte <<= 1  
            self.scl.value(1)  
            utime.sleep_us(4)  
            self.scl.value(0)  
            utime.sleep_us(4)  
              
    def read_byte(self, ack=True):  
        byte = 0  
        for bit in range(8):  
            self.scl.value(1)  
            utime.sleep_us(4)  
            bit_value = self.sda.value()  
            byte |= bit_value << 7 - bit  
            self.scl.value(0)  
            utime.sleep_us(4)  
        if not ack:  
            self.sda.value(1)  
            utime.sleep_us(4)  
        else:  
            self.sda.value(0)  
            utime.sleep_us(4)  
            self.scl.value(1)  
            utime.sleep_us(4)  
            self.scl.value(0)  
            utime.sleep_us(4)  
        return byte  
          
    def read_temp(self):  
        # 发送读取温度命令的代码  
        pass

要点解读:此代码定义了一个TempSensor类,使用软件I2C总线读取温度传感器数据。在类的初始化函数中,定义了用于控制I2C总线的引脚。在start和stop方法中,实现了I2C总线的起始和停止信号。在write_byte和read_byte方法中,实现了I2C总线的数据传输过程。在实际应用中,可以根据需要修改和扩展此类,例如添加读取其他传感器数据的方法。

案例五:使用软件I2C总线控制LED驱动器

import machine  
import utime  
  
class LEDDriver:  
    def __init__(self, sda, scl, addr):  
        self.sda = machine.Pin(sda, machine.Pin.OUT)  
        self.scl = machine.Pin(scl, machine.Pin.OUT)  
        self.addr = addr << 1  # 左移一位,因为I2C地址是7位的,而Python中整数是8位的  
          
    def start(self):  
        self.sda.value(1)  
        self.scl.value(1)  
        utime.sleep_us(4)  
        self.sda.value(0)  
        utime.sleep_us(4)  
        self.scl.value(0)  
          
    def stop(self):  
        self.scl.value(1)  
        utime.sleep_us(4)  
        self.sda.value(1)  
          
    def write_byte(self, byte):  
        for bit in range(8):  
            if byte & 0x80:  
                self.sda.value(1)  
            else:  
                self.sda.value(0)  
            byte <<= 1  
            self.scl.value(1)  
            utime.sleep_us(4)  
            self.scl.value(0)  
            utime.sleep_us(4)  
              
    def write_register(self, reg, value):  
        self.start()  
        self.write_byte(self.addr | 0x00)  # 写操作,发送设备地址和写标志位0x00  
        self.write_byte(reg)  # 发送寄存器地址  
        self.write_byte(value)  # 发送寄存器值  
        self.stop()  
        utime.sleep_us(100)  # 延时等待LED驱动器处理数据  
          
    def set_led(self, led, state):  
        if state:  # 打开LED灯,将对应寄存器的对应位设置为1(高电平)或0(低电平)均可,具体取决于LED驱动器的控制逻辑和硬件连接方式。这里假设高电平有效。注意:这里只是示例代码,实际应用中需要根据具体的LED驱动器型号和控制逻辑来编写相应的控制代码。此外,还需要考虑LED的亮度、颜色等属性。  
            reg_value = 0b11111111  # 假设所有LED灯都连接到同一个寄存器,且初始状态为关闭(低电平)  
            reg_value ^= (1 << led)  # 将对应寄存器的对应位设置为高电平(打开LED灯)  
        else:  # 关闭LED灯,将对应寄存器的对应位设置为0(低电平)或1(高电平)均可。这里假设低电平有效。注意:这里只是示例代码,实际应用中需要根据具体的LED驱动器型号和控制逻辑来编写相应的控制代码。此外,还需要考虑LED的亮度、颜色等属性。  
            reg_value = 0  # 假设所有LED灯都连接到同一个寄存器,且初始状态为关闭(低电平)  
        self.write_register(0x01, reg_value)  # 发送寄存器值,控制LED灯的亮灭

要点解读:此代码定义了一个I2CBus类和一个DeviceA类、一个DeviceB类,使用软件I2C总线进行多个设备间的通信。在I2CBus类的初始化函数中,定义了用于控制I2C总线的引脚。在start、stop、write_byte、read_byte方法中,实现了I2C总线的起始、停止和数据传输过程。在write_to方法中,实现了向指定设备写入数据的功能。在read_from方法中,实现了从指定设备读取数据的功能。DeviceA类和DeviceB类分别代表I2C总线上的主设备和从设备,通过I2CBus类进行数据传输。在实际应用中,可以根据需要修改和扩展这些类,例如添加其他设备的控制方法或实现更复杂的通信协议。

案例六:I2C传感器读取

import machine
import time

i2c = machine.I2C(1, scl=machine.Pin(19), sda=machine.Pin(18))

# I2C传感器地址
SENSOR_ADDRESS = 0x68

# 读取传感器数据
def read_sensor_data():
    data = i2c.readfrom_mem(SENSOR_ADDRESS, 0x00, 6)
    # 处理数据
    # ...
    return processed_data

while True:
    sensor_data = read_sensor_data()
    print("Sensor data:", sensor_data)
    time.sleep(1)

要点解读:
通过machine.I2C创建I2C对象,指定总线号和引脚。
使用i2c.readfrom_mem()从指定地址的I2C设备中读取数据。
对读取的原始数据进行处理和解析,并返回处理后的数据。

案例八:I2C设备通信

import machine

i2c = machine.I2C(1, scl=machine.Pin(19), sda=machine.Pin(18))

# I2C设备地址
DEVICE_ADDRESS = 0x50

# 向设备写入数据
def write_data(data):
    i2c.writeto(DEVICE_ADDRESS, data)

# 从设备读取数据
def read_data():
    data = i2c.readfrom(DEVICE_ADDRESS, 4)
    return data

# 主程序
data_to_send = b'Hello'
write_data(data_to_send)
received_data = read_data()
print("Received data:", received_data)

要点解读:
使用machine.I2C创建I2C对象,指定总线号和引脚。
使用i2c.writeto()向指定地址的I2C设备写入数据。
使用i2c.readfrom()从指定地址的I2C设备读取数据。

案例九:I2C多设备通信

import machine
import time

i2c = machine.I2C(1, scl=machine.Pin(19), sda=machine.Pin(18))

# I2C设备1地址
DEVICE1_ADDRESS = 0x50
# I2C设备2地址
DEVICE2_ADDRESS = 0x68

# 向设备写入数据
def write_data(device_address, data):
    i2c.writeto(device_address, data)

# 从设备读取数据
def read_data(device_address):
    data = i2c.readfrom(device_address, 4)
    return data

# 主程序
data_to_send = b'Hello'

while True:
    write_data(DEVICE1_ADDRESS, data_to_send)
    received_data = read_data(DEVICE2_ADDRESS)
    print("Received data:", received_data)
    time.sleep(1)

要点解读:
使用machine.I2C创建I2C对象,指定总线号和引脚。
可以使用不同的设备地址来实现与多个I2C设备的通信。
通过循环周期性地向一个设备写入数据,然后从另一个设备读取数据。
这些示例展示了MicroPython的Teensy 4.1软件I2C总线的实际应用。你可以根据具体的需求和硬件配置,修改和扩展这些示例代码。

请注意,以上案例只是为了拓展思路,可能存在错误或不适用的情况。不同的硬件平台、使用场景和MicroPython版本可能会导致不同的使用方法。在实际编程中,您需要根据您的硬件配置和具体需求进行调整,并进行多次实际测试。确保正确连接硬件并了解所使用的传感器和设备的规范和特性非常重要。

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

驴友花雕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值