如何用Python实现树莓派3通过I2C向STM32F205发送浮点数据
树莓派3 I2C主设备发送浮点数据实现
1. 依赖安装
先安装树莓派I2C操作的Python库:
sudo apt-get install python3-smbus2
2. Python发送代码
模拟原Arduino的浮点数据字节化逻辑(默认小端字节序,与Arduino/STM32的浮点存储格式一致):
from smbus2 import SMBus import struct # 配置参数 I2C_BUS = 1 # 树莓派3默认I2C总线(SDA=GPIO2, SCL=GPIO3) SLAVE_ADDR = 0x08 # STM32从设备地址,需与原Arduino代码一致 # 待发送的测量数据 meas_data = { "id": 1, "voltage": 220.5, "current": 1.23, "voltage_phase": 30.0, "current_phase": -15.5, "frequency": 50.0 } def float_to_le_bytes(f): # 将float转为4字节小端字节数组 return struct.pack('<f', f) def uint16_to_le_bytes(i): # 将16位ID转为2字节小端字节数组(若原Arduino用32位ID则改用'<I') return struct.pack('<H', i) # 打包并发送数据 with SMBus(I2C_BUS) as bus: send_buf = bytearray() send_buf.extend(uint16_to_le_bytes(meas_data["id"])) send_buf.extend(float_to_le_bytes(meas_data["voltage"])) send_buf.extend(float_to_le_bytes(meas_data["current"])) send_buf.extend(float_to_le_bytes(meas_data["voltage_phase"])) send_buf.extend(float_to_le_bytes(meas_data["current_phase"])) send_buf.extend(float_to_le_bytes(meas_data["frequency"])) # 发送数据(0x00为起始寄存器地址,若原Arduino有指定则替换) bus.write_i2c_block_data(SLAVE_ADDR, 0x00, send_buf)
STM32端接收字节转浮点型处理
1. 定义接收缓冲区与数据结构
#include <string.h> #include "stm32f1xx_hal.h" // 接收缓冲区:ID(2字节) + 5个float(各4字节),总长度22字节 uint8_t i2c_rx_buf[2 + 4*5] = {0}; uint8_t rx_idx = 0; // 存储解析后的数据结构 typedef struct { uint16_t id; float voltage; float current; float voltage_phase; float current_phase; float frequency; } MeasData; MeasData received_data;
2. I2C中断回调接收字节
在I2C从设备中断回调中填充缓冲区:
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) { if(hi2c->Instance == I2C1) { // 读取DR寄存器值存入缓冲区 i2c_rx_buf[rx_idx++] = hi2c->Instance->DR; // 继续接收下一字节,直到缓冲区填满 if(rx_idx < sizeof(i2c_rx_buf)) { HAL_I2C_Slave_Receive_IT(hi2c, &i2c_rx_buf[rx_idx], 1); } else { // 解析数据 parse_i2c_data(); rx_idx = 0; // 重置索引准备下次接收 } } }
3. 字节数组转浮点型
利用memcpy直接将字节块转换为float(小端字节序与发送端一致):
void parse_i2c_data(void) { // 转换ID(小端字节序) received_data.id = (uint16_t)(i2c_rx_buf[1] << 8) | i2c_rx_buf[0]; // 转换各浮点变量 memcpy(&received_data.voltage, &i2c_rx_buf[2], sizeof(float)); memcpy(&received_data.current, &i2c_rx_buf[6], sizeof(float)); memcpy(&received_data.voltage_phase, &i2c_rx_buf[10], sizeof(float)); memcpy(&received_data.current_phase, &i2c_rx_buf[14], sizeof(float)); memcpy(&received_data.frequency, &i2c_rx_buf[18], sizeof(float)); }
关键注意事项
- 确保树莓派与STM32的字节序一致(示例用小端,与Arduino默认逻辑匹配),若原Arduino用大端,需将Python的
struct.pack格式改为'>f',STM32转换时也需调整字节顺序。 - 树莓派需先通过
raspi-config启用I2C功能。 - STM32的I2C从设备地址必须与树莓派代码中的
SLAVE_ADDR完全一致。
内容的提问来源于stack exchange,提问作者Marius Gerhard
相关产品推荐
相关产品推荐

