代码还有问题。发命令是没问题,但是发数据还有问题。。。

这篇也是2月份就TODO了,但是一直没写。没动工的原因也是一直忙,有限的时间内不知道如何下手,最后搞定了micropython之后,这些内容才算能推进。
所有的步骤还是继续上一篇:
只是把实现I2C改成直接操作GPIO。其实核心功能就是那么几个,start,stop,write,read。
START
先看第一个吧。(所有的图都是上面是SDA,下面是SCL)

SDA拉低,SCL维持高位。
def start(self):
self.sda.value(0)
time.sleep_us(5)
self.scl.value(0)
time.sleep_us(5)
STOP

主设备在 SCL 保持高电平的情况下,将 SDA 线从低电平拉高。
def stop(self):
self.scl.value(0)
self.sda.value(0)
time.sleep_us(WAITTIME)
self.scl.value(1)
time.sleep_us(WAITTIME)
self.sda.value(1)
time.sleep_us(WAITTIME)
DATA

这个最麻烦
def write_byte(self, byte):
for i in range(8):
self.sda.value((byte >> (7 - i)) & 1)
time.sleep_us(WAITTIME)
self.scl.value(1)
time.sleep_us(WAITTIME)
self.scl.value(0)
time.sleep_us(WAITTIME)
self.sda.init(Pin.IN, Pin.PULL_UP)
time.sleep_us(WAITTIME)
self.scl.value(1)
ack = self.sda.value()
time.sleep_us(WAITTIME)
self.scl.value(0)
self.sda.init(Pin.OUT, Pin.PULL_UP)
return ack
READ
这个暂时没有图
def read_byte(self, ack):
byte = 0
self.sda.init(Pin.IN, Pin.PULL_UP)
for i in range(8):
self.scl.value(1)
time.sleep_us(WAITTIME)
byte = (byte << 1) | self.sda.value()
self.scl.value(0)
time.sleep_us(WAITTIME)
self.sda.init(Pin.OUT, Pin.PULL_UP)
self.sda.value(ack)
time.sleep_us(WAITTIME)
self.scl.value(1)
time.sleep_us(WAITTIME)
self.scl.value(0)
time.sleep_us(WAITTIME)
return byte
最后是仿照I2C的接口,还有两个封装。
def writeto(self, addr, write_list):
self.start()
ack = self.write_byte(addr << 1)
if ack != 0:
print("NACK received")
self.stop()
return
for data in write_list:
ack = self.write_byte(data << 1)
if ack != 0:
print("NACK received")
self.stop()
return
self.stop()
def writevto(self, addr, vectors):
self.start()
ack = self.write_byte(addr << 1)
if ack:
print("writevto NACK received")
self.stop()
return False
for vector in vectors:
for byte in vector:
ack = self.write_byte(byte)
if ack:
print("writevto NACK received")
self.stop()
return False
self.stop()
return True
最后是完整代码:
import time
from machine import Pin
WAITTIME = 2
class SoftI2C:
def __init__(self, scl_pin, sda_pin):
self.scl = Pin(scl_pin, Pin.OUT, Pin.PULL_UP)
self.sda = Pin(sda_pin, Pin.OUT, Pin.PULL_UP)
self.scl.value(1)
self.sda.value(1)
def start(self):
self.sda.value(0)
#time.sleep_us(5)
time.sleep_us(WAITTIME)
self.scl.value(0)
time.sleep_us(WAITTIME)
def stop(self):
self.scl.value(0)
self.sda.value(0)
time.sleep_us(WAITTIME)
self.scl.value(1)
time.sleep_us(WAITTIME)
self.sda.value(1)
time.sleep_us(WAITTIME)
def write_byte(self, byte):
for i in range(8):
self.sda.value((byte >> (7 - i)) & 1)
time.sleep_us(WAITTIME)
self.scl.value(1)
time.sleep_us(WAITTIME)
self.scl.value(0)
time.sleep_us(WAITTIME)
self.sda.init(Pin.IN, Pin.PULL_UP)
time.sleep_us(WAITTIME)
self.scl.value(1)
ack = self.sda.value()
time.sleep_us(WAITTIME)
self.scl.value(0)
self.sda.init(Pin.OUT, Pin.PULL_UP)
return ack
def read_byte(self, ack):
byte = 0
self.sda.init(Pin.IN, Pin.PULL_UP)
for i in range(8):
self.scl.value(1)
time.sleep_us(WAITTIME)
byte = (byte << 1) | self.sda.value()
self.scl.value(0)
time.sleep_us(WAITTIME)
self.sda.init(Pin.OUT, Pin.PULL_UP)
self.sda.value(ack)
time.sleep_us(WAITTIME)
self.scl.value(1)
time.sleep_us(WAITTIME)
self.scl.value(0)
time.sleep_us(WAITTIME)
return byte
def writeto(self, addr, write_list):
self.start()
ack = self.write_byte(addr << 1)
if ack != 0:
print("NACK received")
self.stop()
return
for data in write_list:
ack = self.write_byte(data << 1)
if ack != 0:
print("NACK received")
self.stop()
return
self.stop()
def writevto(self, addr, vectors):
self.start()
ack = self.write_byte(addr << 1)
if ack:
print("writevto NACK received")
self.stop()
return False
for vector in vectors:
for byte in vector:
ack = self.write_byte(byte)
if ack:
print("writevto NACK received")
self.stop()
return False
self.stop()
return True
'''
# 示例使用
scl_pin = 17 # SCL引脚编号
sda_pin = 16 # SDA引脚编号
i2c = SoftI2C(scl_pin, sda_pin)
# 向从设备地址0x3C写入一个字节0x01
i2c.start()
ack = i2c.write_byte(0x3C << 1) # 写操作
if ack == 0:
print("ACK received")
else:
print("NACK received")
i2c.write_byte(0x01)
i2c.stop()
# 从从设备地址0x3C读取一个字节
i2c.start()
i2c.write_byte((0x3C << 1) | 1) # 读操作
data = i2c.read_byte(1) # 发送ACK
i2c.stop()
print(f"Read data: {data}")'''
本文介绍了一种使用GPIO模拟I2C总线通信的方法。通过直接控制GPIO引脚来实现I2C的基本操作,如启动、停止、写入和读取数据等。文章提供了详细的代码示例,并说明了每个函数的功能。
739

被折叠的 条评论
为什么被折叠?



