20 Star 82 Fork 22

黑胡桃实验室 BlackWalnut Labs. / Waffle NanoV1 Python API Doc

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
README.md 10.79 KB
一键复制 编辑 原始数据 按行查看 历史
HerculesHu 提交于 2021-08-23 08:51 . !48修改IO9IO10相关内容

I2C总线接口

概要

​ 本节简要介绍I²C总线协议,并以一个简单的例程介绍如何在通过 Python 使用 OpenHarmony 的 I²C 接口

什么是I2C

  • I²C(Inter-integrated Circuit)最早是飞利浦在1982年开发设计的一种简单、双向二线制同步串行总线协议。
  • I²C总线支持设备之间的短距离通信,用于处理器和一些外围设备之间的接口,它只需要两根信号线来完成信息交换。

通信原理

物理接线

​ I²C最少只需要两根线,和异步串口类似,但可以支持多个从(slave)设备,和SPI不同的是,I²C可以支持多主机(mul-master)系统,允许有多个master并且每个master都可以与所有的slaves通信(master之间不可通过I²C通信,并且每个master只能轮流使用I²C总线)。master是指启动数据传输的设备并在总线上生成时钟信号以驱动该传输,而被寻址的通信设备都作为slaves。

​ I²C通讯只需要2条双向总线:

功能编号 含义
SDA(serial data:串行数据线) 传输数据,SDA线传输数据是大端传输,每次传输一个字节
SCL(serial clock:串行时钟线) 同步数据收发

​ 一个主设备和两个从设备的连接示意图如下图所示:

​ I²C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址,当主设备需要和某一个从设备通信时,通过广播的方式,将从设备地址写到总线上,如果某个从设备符合此地址,将会发出应答信号,建立传输。

数据有效性

​ SDA 线上的数据必须在时钟的高电平周期保持稳定,数据线的高或低电平状态只有在 SCL 线的时钟信号是低电平时才能改变。

​ 换言之,SCL为高电平时表示有效数据,SDA为高电平表示“1”,低电平表示“0”;SCL为低电平时表示无效数据,此时SDA会进行电平切换,为下次数据表示做准备。如图为数据有效性的时序图。

起始条件和停止条件

​ 起始条件S:当SCL高电平时,SDA由高电平向低电平转换;

​ 停止条件P:当SCL高电平时,SDA由低电平向高电平转换。

​ 起始和停止条件一般由主机产生。总线在起始条件后处于busy的状态,在停止条件的某段时间后,总线才再次处于空闲状态。如下图为起始和停止条件的信号产生时序图。

数据格式

​ I²C数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。

​ I²C传输的数据以字节为单位,每个字节必须为8位,可以传输任意多个字节,上图中以一个字节的数据为例进行分析,I2C的数据格式具有以下特点:

  • 每个字节后必须跟一个响应位 ACK(如上图中的SCL上ACK),因此实际上传输一个字节(8位)的数据需要花费9位的时间。
  • SDA上首先传输字节的最高位,从上图中我们可以看出,位数编号的发送顺序从左至右 是 Bit7-Bit0
响应ACK

​ 数据接收方收到传输的一个字节数据后,需要给出响应,此时处在第九个时钟,发送端释放SDA线控制权 ,将SDA电平拉高,由接收方控制。

​ 接收方表示成功的接收到了8位一个字节的数据,便将SDA拉低为低电平,即ACK信号,表示应答

PDU

​ I²C的PDU(Protocol Data Unit:协议数据单元,即数据格式):

I2C传输通用方法集合

  • I²C接口定义了完成I²C传输的通用方法集合,包括:
  • I²C控制器管理: 打开或关闭I2C控制器
  • I²C消息传输:通过消息传输结构体数组进行自定义传输

I2C引脚定义

waffle nano 共有7个引脚可以用作 I²C 的通讯引脚。拥有 2 个 I²C 总线端口,根据用户的配置,总线端口可以用作 I²C 主机。

其中板载内置传感器连接到引脚:Pin9,Pin10。所以在操作板载传感器时需配置 0 号端口 I²C 总线对象,比如 i2c = I2C(0, sda=Pin(9), scl=Pin(10)

I²C 端口号 SDA SCL
I2C 1 pin 0 pin 1
I2C 0 pin 9 pin 10
I2C 0 pin 13 pin 14

machine.I2C API详解

  使用from machine import I2C导入machine模块的I2C总线接口类I2C

  再使用TAB 按键来查看I2C中所包含的内容:

>>>from machine import I2C
>>>I2C.
read            write           readfrom_mem    scan
writeto_mem

class I2C(id, scl, sda, freq=400000)

  • id — I²C设备组号,可以为0或1
  • scl — I²C设备时钟引脚对象
  • sda — I²C设备数据线引脚对象
  • freq — SCL时钟频率 0 <freq≤ 500000(Hz)

构造I2C

  用I2C对象的构造器函数

  示例:

>>> from machine import I2C, Pin
>>> i2c = I2C(0, sda=Pin(9), scl=Pin(10),freq=100000)#构建I2C0,时钟频率100000(时钟屏幕根据具体传感器而定,一般使用100000或400000)
>>> i2c = I2C(1, sda=Pin(0), scl=Pin(1),freq=100000)##用pin1引脚当I2C1的scl功能成功

  使用ID直接构造

  I2C的id只能取01,可以通过id来直接构造这两组接口。无法直接使用第1组I2C资源,默认I2C的SCL功能是由pin4引脚实现,会报invalid scl pin(4)错误,因为IO3IO4被编程串口所占用。

  示例:

>>> from machine import I2C, Pin
>>> i2c0=I2C(0)#构建I2C0
>>> i2c0
I2C(0, scl=10, sda=9, freq=400000)
>>> i2c1=I2C(1)#构建I2C1会报ValueError
Traceback (most recent call last):
  File "<stdin>", in <module>
ValueError: invalid scl pin(4)
>>> i2c1
I2C(1, scl=4, sda=3, freq=400000)

函数

  在接下来的示例中, 构造id=0I2C对象来列举I2C对象的函数。

>>>from machine import I2C
>>>i2c = I2C(0)#构建I2C0
扫描I2C地址

  i2c.scan()

  函数说明:扫描I²C地址,并返回设备列表

>>>from machine import I2C
>>>i2c = I2C(0)#构建I2C0
>>> i2c.scan()#扫描I²C地址
[104, 118]

  waffle nano本身有104和118两个地址的I²C总线,104是陀螺仪传感器,118是温湿度传感器。

  I²C读写数据需要先扫描I²C地址,在相应的地址上读写数据

写数据

  i2c.write(addr,data)

  函数说明:向I2C写入(发送)数据,返回True或False表示是否写入成功.

  addrI²C设备地址,可由scan函数读取出来

  data: 需要写入(发送)的数据

  示例:

>>>from machine import I2C
>>>i2c = I2C(0)#构建I2C0
>>>i2c.write(104,b'\x01\x00\x09\x08')#向I2C0的104地址写入数据`\x01\x00\x09\x08`
True

  注意:

  一般的IIC传感器都有寄存器的概念。视不同传感器而言,一般发送的数据前一位为寄存器地址,也就是\x01\x00\x09\x080x01为其寄存器地址,向0x01寄存器(含)往后将x00\x09\x08数据依次写入寄存器中去。也有些传感器使用的寄存器比较多,需要用两个字节表示寄存器地址,那么此时\x01\x00\x09\x08\x01\x00表示其寄存器地址。向0x01\x00寄存器(含)往后将x09\x08数据依次写入寄存器中去。

读数据

  i2c.read(addr,length)

  函数说明:从指定地址设备读取数据,返回读取对象,这个对象与I²C设备有关

  addr: I²C设备地址,可由scan函数读取出来

  length: 读入的字节数

  from machine import I2C
  i2c = I2C(0)#构建I2C0
  i2c.write(118,b'\x08')#从第0x08寄存器开始读取
  print(i2c.read(118,10))#读取118地址上0x08寄存器往后的10个字节的数据
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
从寄存器中读取数据

  i2c.readfrom_mem(addr,register,length)

  函数说明:从指定地址设备的指定寄存器开始往后连续读取各寄存器数据。

  addr:从机设备IIC地址。register:操作的起始寄存器地址。length: 读入的字节数。

  注意:此方法仅仅适用于寄存器用一个字节描述的IIC元器件

向寄存器写入数据

  i2c.writeto_mem(addr,register,data)

  函数说明:向指定地址设备的指定寄存器开始往后连续将数据写入各寄存器中。

  addr:从机设备IIC地址。register:操作的起始寄存器地址,data: 需要写入(发送)的数据。

  注意:此方法仅仅适用于寄存器用一个字节描述的IIC元器件

示例

  将waffle nano的一些GPIO引脚构造成I2C总线,读写相应数据(需要连接相应的传感器)。

from machine import I2C, Pin
i2c = I2C(1, sda=Pin(0), scl=Pin(1),freq=100000) #构造IIC对象,将1号引脚设置为scl,将0号引脚设置为sda
print(i2c.scan()) #扫描IIC总线上的传感器,返回传感器ID

i2c.write(74,b'\x03') #向74号ID的传感器发送0x03数据

print(i2c.read(74,10)) #从74号ID的传感器读取10个字节数据

i2c.writeto_mem(105,0x03,b'\x01\x02') #向105号ID的传感器的0x03寄存器(含)以及其往后的寄存器中依次填入数据`0x01`、`0x02,每个寄存器分到1个字节。

print(i2c.readfrom_mem(105,0x80,128)) #从105号ID的传感器的0x80寄存器开始(含)依次读取128个寄存器的数据,并返回。
Python
1
https://gitee.com/blackwalnutlabs/waffle_nano_v1_python_api_document.git
git@gitee.com:blackwalnutlabs/waffle_nano_v1_python_api_document.git
blackwalnutlabs
waffle_nano_v1_python_api_document
Waffle NanoV1 Python API Doc
master

搜索帮助