ch347连接mpu6050

在上一篇文章 详解I2C 的末尾,有这样一张波形图:

实例2

这个对应的就是常见的从设备寄存器读数据的波形,只是在写数据时多了一个字节。

通用的从I2C设备读寄存器数据的模式应该是这样的:

从从设备寄存器读数据示例

mpu6050数据表中的9.3 I2C Communications Protocol章节说明了mpu6050的i2c接口协议,符合通用模式。

mpu6050单字节写和加速写序列如下:

mpu6050单字节写和加速写

mpu6050单字节读和加速读序列如下:

mpu6050单字节读和加速读

上面的加速写和加速读都是以2个数据字节为例的。

从实例2的波形图可以看出,启动传输后,写了0x12 0x13 0x143个字节,这3个字节后都是NACK,然后是重复起始信号,跟着刚才地址字节0x12+10x13,I2C从写转换到读,然后开始读数据字节。

对应代码为:

result = ch347_driver.i2c_set(device_index, 1)
if result:
    print("Success to set I2C speed.")
else:
    print("Failed to set I2C speed.")

result = ch347_driver.i2c_set_delay_ms(device_index, 1)
if result:
    print("Success to set I2C delay.")
else:
    print("Failed to set I2C delay.")


result = ch347_driver.stream_i2c(device_index, b'\x12\x13\x14', 8)
if result:
    print("Success!")
else:
    print("Failed!")

将上面这段代码稍加修改:

result = ch347_driver.i2c_set(device_index, 1)
if result:
    print("Success to set I2C speed.")
else:
    print("Failed to set I2C speed.")

result = ch347_driver.i2c_set_delay_ms(device_index, 1)
if result:
    print("Success to set I2C delay.")
else:
    print("Failed to set I2C delay.")


result = ch347_driver.stream_i2c(device_index, b'\xd0\x75', 1)
if result:
    print("Success! result:", result.hex())
else:
    print("Failed!")

mpu6050模块的地址是0b1101000(AD0 = 0),左移1位得到设备写地址0xd0,读数据时的读地址ch347会自动产生,波形如下:

读寄存器

还没有连接mpu6050模块,所以没有数据返回。现在把mpu6050模块i2c接口连接到ch347模块上,运行程序,结果为:

❯  python test.py
Successfully opened device index: 0
Device Information:
iIndex: 0
DevicePath: \\?\USB#VID_1A86&PID_55DB&MI_02#7&2887B016&0&0002#{5446F048-98B4-4EF0-96E8-27994BAC0D00}
UsbClass: 0
FuncType: 1
DeviceID: USB\VID_1A86&PID_55DB&MI_02#7&2887B016&0&0002#
ChipMode: 1
DevHandle: 912
BulkOutEndpMaxSize: 512
BulkInEndpMaxSize: 512
UsbSpeedType: 1
CH347IfNum: 0
DataUpEndp: 6
DataDnEndp: 6
ProductString:
ManufacturerString:
WriteTimeout: 500
ReadTimeout: 500
FuncDescStr: USB2.0 To SPI&IIC
FirewareVer: 64
<ch347.mDeviceInforS object at 0x000002465A1E63C0>
Version Information:
Driver Version: 35
DLL Version: 34
Device Version: 64
Chip Type: 1
Success to set I2C speed.
Success to set I2C delay.
Success! result: 68
Successfully closed device index: 0

可以看到返回了数据0x680x75是’WHO_AM_I’寄存器,默认值为0x68

'WHO_AM_I'寄存器

完整代码:

import ch347

dll_path = "ch347dlla64.dll"  # Replace with the actual path to the DLL
device_index = 0  # Set the device index according to your requirements

ch347_driver = ch347.CH347Driver(dll_path)

result = ch347_driver.open_device(device_index)
if result:
    print(f"Successfully opened device index: {device_index}")
else:
    print(f"Failed to close device index: {device_index}")

result, device_info = ch347_driver.get_device_info(device_index)
if result:
    print("Device Information:")
    print(f"iIndex: {device_info.iIndex}")
    print(f"DevicePath: {device_info.DevicePath.decode()}")
    print(f"UsbClass: {device_info.UsbClass}")
    print(f"FuncType: {device_info.FuncType}")
    print(f"DeviceID: {device_info.DeviceID.decode()}")
    print(f"ChipMode: {device_info.ChipMode}")
    print(f"DevHandle: {device_info.DevHandle}")
    print(f"BulkOutEndpMaxSize: {device_info.BulkOutEndpMaxSize}")
    print(f"BulkInEndpMaxSize: {device_info.BulkInEndpMaxSize}")
    print(f"UsbSpeedType: {device_info.UsbSpeedType}")
    print(f"CH347IfNum: {device_info.CH347IfNum}")
    print(f"DataUpEndp: {device_info.DataUpEndp}")
    print(f"DataDnEndp: {device_info.DataDnEndp}")
    print(f"ProductString: {device_info.ProductString.decode()}")
    print(f"ManufacturerString: {device_info.ManufacturerString.decode()}")
    print(f"WriteTimeout: {device_info.WriteTimeout}")
    print(f"ReadTimeout: {device_info.ReadTimeout}")
    print(f"FuncDescStr: {device_info.FuncDescStr.decode()}")
    print(f"FirewareVer: {device_info.FirewareVer}")
    print(repr(device_info))
else:
    print("Failed to get device information.")

result, driver_ver, dll_ver, device_ver, chip_type = ch347_driver.get_version(device_index)
if result:
    print("Version Information:")
    print(f"Driver Version: {driver_ver}")
    print(f"DLL Version: {dll_ver}")
    print(f"Device Version: {device_ver}")
    print(f"Chip Type: {chip_type}")
else:
    print("Failed to get version information.")

result = ch347_driver.i2c_set(device_index, 1)
if result:
    print("Success to set I2C speed.")
else:
    print("Failed to set I2C speed.")

result = ch347_driver.i2c_set_delay_ms(device_index, 1)
if result:
    print("Success to set I2C delay.")
else:
    print("Failed to set I2C delay.")


result = ch347_driver.stream_i2c(device_index, b'\xd0\x75', 1)
if result:
    print("Success! result:", result.hex())
else:
    print("Failed!")


# Example usage of CH347CloseDevice
result = ch347_driver.close_device(device_index)
if result:
    print(f"Successfully closed device index: {device_index}")
else:
    print(f"Failed to close device index: {device_index}")

接下来就可以对mpu6050各种功能进行封装,然后在电脑上直接获取传感器数据了。

公众号 | FunIO
微信搜一搜 “funio”,发现更多精彩内容。
个人博客 | blog.boringhex.top

### 硬件连接配置 在CH32V307微控制器上实现读取MPU6050传感器数据的功能,首先需要正确配置硬件连接MPU6050通过I2C总线进行通信,因此需要将MPU6050的SDA引脚连接CH32V307的I2C数据线,SCL引脚连接CH32V307的I2C时钟线。通常,CH32V307的I2C接口可以通过GPIO引脚进行配置,例如使用PA9和PA10作为I2C1的SDA和SCL引脚。 ### 初始化I2C接口 在CH32V307上初始化I2C接口时,需要配置相关的GPIO引脚为复用推挽模式,并设置I2C的工作频率。以下是一个初始化I2C接口的示例代码: ```c #include "ch32v30x.h" void I2C_Init(void) { // 使能GPIO和I2C时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); // 配置I2C1的SDA和SCL引脚 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 复用开漏模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置I2C1 I2C_InitTypeDef I2C_InitStructure; I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructure.I2C_OwnAddress1 = 0x00; // 不使用自身地址 I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_ClockSpeed = 100000; // 设置I2C频率为100kHz I2C_Init(I2C1, &I2C_InitStructure); // 使能I2C1 I2C_Cmd(I2C1, ENABLE); } ``` ### MPU6050初始化与数据读取 MPU6050在上电后需要进行初始化,设置其寄存器以启用传感器并配置测量范围。以下是一个初始化MPU6050的示例代码: ```c void MPU6050_Init(void) { // 向MPU6050的电源管理寄存器写入0x00,启用传感器 I2C_WriteRegister(MPU6050_ADDRESS, MPU6050_PWR_MGMT_1, 0x00); // 向MPU6050的陀螺仪配置寄存器写入0x18,设置陀螺仪范围为±2000°/s I2C_WriteRegister(MPU6050_ADDRESS, MPU6050_GYRO_CONFIG, 0x18); // 向MPU6050的加速度计配置寄存器写入0x01,设置加速度计范围为±2g I2C_WriteRegister(MPU6050_ADDRESS, MPU6050_ACCEL_CONFIG, 0x01); } // 读取MPU6050的加速度和陀螺仪数据 void MPU6050_ReadData(int16_t *accel, int16_t *gyro) { uint8_t data[14]; I2C_ReadRegisters(MPU6050_ADDRESS, MPU6050_ACCEL_XOUT_H, data, 14); // 解析加速度数据 accel[0] = (int16_t)((data[0] << 8) | data[1]); accel[1] = (int16_t)((data[2] << 8) | data[3]); accel[2] = (int16_t)((data[4] << 8) | data[5]); // 解析温度数据(可选) int16_t temperature = (int16_t)((data[6] << 8) | data[7]); // 解析陀螺仪数据 gyro[0] = (int16_t)((data[8] << 8) | data[9]); gyro[1] = (int16_t)((data[10] << 8) | data[11]); gyro[2] = (int16_t)((data[12] << 8) | data[13]); } ``` ### 数据处理与应用 读取到MPU6050的原始数据后,可以根据需要进行进一步处理。加速度计和陀螺仪的数据通常需要进行校准,以消除偏移和噪声。校准可以通过采集静止状态下的数据并计算平均值来实现,然后将这些平均值作为偏移量从后续的测量数据中减去。 ### 相关函数实现 在上述代码中,`I2C_WriteRegister`和`I2C_ReadRegisters`是自定义的I2C通信函数,用于向MPU6050的特定寄存器写入数据和从特定寄存器读取数据。这些函数的具体实现取决于所使用的I2C库或驱动程序。 ### 总结 通过正确配置CH32V307的I2C接口并实现与MPU6050的通信,可以有效地读取传感器数据。初始化MPU6050后,读取其加速度计和陀螺仪数据,并进行必要的数据处理,可以应用于各种运动检测和控制系统中[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值