【ESP32】【micropython】I2C相关函数介绍及用esp32读取mpu6050数据

  • I2C接口介绍
  • micropython相关函数
  • i2c类实例化
  • i2c类中的函数介绍
  • I2C.init(scl, sda, freq)
  • I2C.scan()
  • I2C.start()
  • I2C.stop()
  • I2C.write(buf)
  • I2C.readinto(buf, nack=True)
  • I2C.readfrom(addr, nbytes)
  • I2C.readfrom_into(addr, buf)
  • I2C.writeto(addr, buf)
  • I2C.readfrom_mem(addr, memaddr, nbytes, addrsize=8)
  • I2C.readfrom_mem_into(addr, memaddr, buf, addrsize=8)
  • I2C.writeto_mem(addr, memaddr, buf, addrsize=8)
  • 【例子】用esp32读取mpu6050数据


I2C接口介绍

micropython相关函数

i2c类实例化

I2C是设备之间的两线通信协议。在物理层它只需要两个信号线:SCL 和 SDA,分别是时钟和数据线。I2C 对象关联到总线,它可以在创建时初始化,也可以稍后初始化。
与I2C有关的类定义在machine中,我们可以通过

class machine.I2C(scl, sda, freq)

实例化一个I2C的类
其中
scl为i2c设备时钟引脚对象;sda为i2c设备数据线引脚对象;freq为SCL时钟频率(0 < freq ≤ 500000(Hz))。

i2c类中的函数介绍

I2C.init(scl, sda, freq)

函数说明:初始化i2c总线。

scl:SCL信号线的I/O口
sda:SDA信号线的I/O口
freq:SCL时钟频率
示例:

i2c.init(scl=Pin(22),sda=Pin(21))

I2C.scan()

函数说明:扫描0x08到0x77之间的I2C地址,并返回设备列表。
示例:

i2c.scan()

I2C.start()

函数说明:在总线上触发START状态(SCL为高电平时,SDA转为低电平)。
示例:

i2c.start()

I2C.stop()

函数说明:在总线上触发STOP状态 (SCL为高电平时,SDA转为高电平)。
示例:

i2c.stop()

I2C.write(buf)

函数说明:buf中的数据写入到总线,并返回写入的字节数。

buf:存储数据的缓冲区
注意:
使用write()函数时要与start函数一起使用,否则无法返回写入的字节数。
示例:

buf = b'123'
i2c.start()
i2c.write(buf)

I2C.readinto(buf, nack=True)

函数说明:从总线上读取数据并存放到buf,无返回值。

buf:存储数据的缓冲区
注意:
读取的字节数是buf的长度。在接收到最后一个字节之前,总线将发送ACK信号。在接收到最后一个字节后,如果nack为True,那么将发送一个NACK信号,否则将发送一个ACK信号。 示例:

buf=bytearray(3)
i2c.readinto(buf)

I2C.readfrom(addr, nbytes)

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

addr:i2c设备地址(可由scan函数读取出来)
nbytes:要读取数据的大小
示例:

data = i2c.readfrom(24, 8)
 print(data)

运行结果:
b’\x00\x02\x00\x00\xe8\x03\xe8\x03’

I2C.readfrom_into(addr, buf)

函数说明:从指定地址设备读取buf.len()个数据到buf。

addr:i2c设备地址(可由scan函数读取出来)
buf:存储数据的缓冲区
示例:

buf = bytearray(8)
i2c.readfrom_into(24, buf)
print(buf)

运行结果:
bytearray(b’\x00\x02\x00\x00\xe8\x03\xe8\x03’)

I2C.writeto(addr, buf)

函数说明:将buf中的数据写入设备,并返回写入数据的大小。

addr:i2c设备地址(可由scan函数读取出来)
buf:存储数据的缓冲区
示例:

b = bytearray(3)
 b[0] = 24
b[1] = 111
b[2] = 107
 i = i2c.writeto(24,b)

I2C.readfrom_mem(addr, memaddr, nbytes, addrsize=8)

函数说明:从I2C设备的寄存器中读取并返回数据。

addr:i2c设备地址(可由scan函数读取出来)
memaddr:寄存器地址
nbytes:要读取的字节大小
addrsize:指定地址大小,默认为8位(在ESP8266上这个参数无效,地址大小总是8位)
示例:

b = i2c. readfrom_mem(24,  0x58, 3)
print(b)

运行结果:
b’\x00\x02\x01’

I2C.readfrom_mem_into(addr, memaddr, buf, addrsize=8)

函数说明:从I2C设备的寄存器中读取buf.len()个数据到buf,无返回值。

addr:i2c设备地址(可由scan函数读取出来)
memaddr:寄存器地址
buf:存储数据的缓冲区
addrsize:指定地址大小,默认为8位(在ESP8266上这个参数无效,地址大小总是8位),读取数据数量是buf的长度。
示例:

buf=bytearray(8)
i2c.readfrom_mem_into(24, 0x58, buf)

I2C.writeto_mem(addr, memaddr, buf, addrsize=8)

函数说明: 将buf 中的数据全部写入到从设备 addr 的内存 memaddr。

addr:i2c设备地址(可由scan函数读取出来)
memaddr:寄存器地址
buf:存储数据的缓冲区
addrsize:指定地址大小,默认为8位(在ESP8266上这个参数无效,地址大小总是8位),读取数据数量是buf的长度。
示例:

buf = b'123'
i2c.writeto_mem(24, 0x58, buf)

【例子】用esp32读取mpu6050数据

MPU6050.py

import utime
from machine import Pin, I2C

MPU_SELF_TESTX_REG = 0X0D	
MPU_SELF_TESTY_REG = 0X0E
MPU_SELF_TESTZ_REG = 0X0F
MPU_SELF_TESTA_REG = 0X10
MPU_SAMPLE_RATE_REG = 0X19
MPU_CFG_REG = 0X1A
MPU_GYRO_CFG_REG = 0X1B
MPU_ACCEL_CFG_REG = 0X1C
MPU_MOTION_DET_REG = 0X1F
MPU_FIFO_EN_REG = 0X23
MPU_I2CMST_CTRL_REG = 0X24
MPU_I2CSLV0_ADDR_REG = 0X25
MPU_I2CSLV0_REG = 0X26
MPU_I2CSLV0_CTRL_REG = 0X27
MPU_I2CSLV1_ADDR_REG = 0X28
MPU_I2CSLV1_REG = 0X29
MPU_I2CSLV1_CTRL_REG = 0X2A
MPU_I2CSLV2_ADDR_REG = 0X2B
MPU_I2CSLV2_REG	= 0X2C
MPU_I2CSLV2_CTRL_REG = 0X2D
MPU_I2CSLV3_ADDR_REG = 0X2E
MPU_I2CSLV3_REG	= 0X2F
MPU_I2CSLV3_CTRL_REG = 0X30
MPU_I2CSLV4_ADDR_REG = 0X31
MPU_I2CSLV4_REG	= 0X32
MPU_I2CSLV4_DO_REG = 0X33
MPU_I2CSLV4_CTRL_REG = 0X34
MPU_I2CSLV4_DI_REG = 0X35

MPU_I2CMST_STA_REG = 0X36
MPU_INTBP_CFG_REG = 0X37
MPU_INT_EN_REG = 0X38
MPU_INT_STA_REG = 0X3A

MPU_ACCEL_XOUTH_REG	= 0X3B
MPU_ACCEL_XOUTL_REG	= 0X3C
MPU_ACCEL_YOUTH_REG	= 0X3D
MPU_ACCEL_YOUTL_REG	= 0X3E
MPU_ACCEL_ZOUTH_REG	= 0X3F
MPU_ACCEL_ZOUTL_REG	= 0X40

MPU_TEMP_OUTH_REG = 0X41
MPU_TEMP_OUTL_REG = 0X42

MPU_GYRO_XOUTH_REG = 0X43
MPU_GYRO_XOUTL_REG = 0X44
MPU_GYRO_YOUTH_REG = 0X45
MPU_GYRO_YOUTL_REG = 0X46
MPU_GYRO_ZOUTH_REG = 0X47
MPU_GYRO_ZOUTL_REG = 0X48

MPU_I2CSLV0_DO_REG = 0X63
MPU_I2CSLV1_DO_REG = 0X64
MPU_I2CSLV2_DO_REG = 0X65
MPU_I2CSLV3_DO_REG = 0X66

MPU_I2CMST_DELAY_REG = 0X67
MPU_SIGPATH_RST_REG = 0X68
MPU_MDETECT_CTRL_REG = 0X69
MPU_USER_CTRL_REG = 0X6A
MPU_PWR_MGMT1_REG = 0X6B
MPU_PWR_MGMT2_REG = 0X6C
MPU_FIFO_CNTH_REG = 0X72
MPU_FIFO_CNTL_REG = 0X73
MPU_FIFO_RW_REG = 0X74
MPU_DEVICE_ID_REG = 0X75
 
MPU_ADDR = 0X68

class MPU6050:
	def __init__(self, sclIO, sdaIO):
		self.i2c = I2C(1, scl=Pin(sclIO), sda=Pin(sdaIO))
		#初始化mpu6050
		self.WriteByte(MPU_PWR_MGMT1_REG, 0x80)
		utime.sleep_ms(100)
		self.WriteByte(MPU_PWR_MGMT1_REG, 0x00)
		self.SetGyroFsr(3) #设置陀螺仪量程
		self.SetAccelFsr(0) #设置加速度量程
		self.SetRate(50)
		self.WriteByte(MPU_INT_EN_REG, 0x00) #关闭所有中断
		self.WriteByte(MPU_USER_CTRL_REG, 0x00) #iic主模式关闭
		self.WriteByte(MPU_FIFO_EN_REG, 0x00) #关闭FIFO
		self.WriteByte(MPU_INTBP_CFG_REG, 0x80) #INT引脚低电平有效
		
	#设置陀螺仪量程
	def SetGyroFsr(self, fsr):
		self.WriteByte(MPU_GYRO_CFG_REG, fsr<<3)
		
	#设置加速度量程
	def SetAccelFsr(self, fsr):
		self.WriteByte(MPU_ACCEL_CFG_REG, fsr<<3)

	def SetRate(self, rate):
		if rate > 1000:
			rate = 1000
		if rate < 4:
			rate=4
		data = int(1000 / rate - 1)
		self.WriteByte(MPU_SAMPLE_RATE_REG, data)
		self.SetLPF(rate/2)

	def SetLPF(self, lpf):
		data = 0
		if lpf >= 188:
			data = 1
		elif lpf >= 98:
			data = 2
		elif lpf >= 42:
			data = 3
		elif lpf >= 20:
			data = 4
		elif lpf >= 10:
			data = 5
		else:
			data = 6 
		self.WriteByte(MPU_CFG_REG, data)

	#获取温度
	def GetTemp(self): 
		buf = self.ReadLen(MPU_TEMP_OUTH_REG, 2)
		raw = self.bytes_toint(buf[0], buf[1]) 
		temp = 36.53 + raw / 340  
		return temp

	#获取陀螺仪的值
	def GetGyro(self):
		buf = self.ReadLen(MPU_GYRO_XOUTH_REG, 6)
		gx = self.bytes_toint(buf[0], buf[1])
		gy = self.bytes_toint(buf[2], buf[3])
		gz = self.bytes_toint(buf[4], buf[5])
		return gx, gy, gz

	#获取加速度的值
	def GetAccel(self):
		buf = self.ReadLen(MPU_ACCEL_XOUTH_REG, 6)
		ax = self.bytes_toint(buf[0], buf[1])
		ay = self.bytes_toint(buf[2], buf[3])
		az = self.bytes_toint(buf[4], buf[5])
		return ax, ay, az


	def WriteByte(self, reg, data):
		self.i2c.writeto_mem(MPU_ADDR, reg, bytearray([data]))

	def ReadByte(self, reg):
		buf = self.i2c.readfrom_mem(MPU_ADDR, reg, 1)
		return bytearray(buf)

	#向reg写入多个字符buf
	def WriteLen(self, reg, buf):
		self.i2c.writeto_mem(MPU_ADDR, reg, bytearray([buf]))

	#从reg读取len个字符
	def ReadLen(self, reg, len):
		buf = self.i2c.readfrom_mem(MPU_ADDR, reg, len)
		return bytearray(buf)
		
	#将byte数据额转化为short类型
	def bytes_toint(self, firstbyte, secondbyte):
		if not firstbyte & 0x80:
			return firstbyte << 8 | secondbyte
		return - (((firstbyte ^ 255) << 8) | (secondbyte ^ 255) + 1)

main.py

import MPU6050

mpu = MPU6050.MPU6050(sclIO=22, sdaIO=21) #实例化MPU6050类
gx, gy, gz = mpu.GetGyro() #获取陀螺仪读数
ax, ay, az = mpu.GetAccel() #获取加速度读数
temp = mpu.GetTemp() #获取温度值
print('gx:'+str(gx))
print('gy:'+str(gy))
print('gz:'+str(gz))
print('ax:'+str(ax))
print('ay:'+str(ay))
print('az:'+str(az))
print('temp:'+str(temp))