系统连接与工作原理
整个系统的数据流动如下:
硬件连接
1. INA226 与 STM32 连接 (I2C接口)
| INA226 引脚 | STM32 引脚 | 说明 |
|---|---|---|
| VCC | 3.3V | 电源正极 |
| GND | GND | 电源地 |
| SCL | PB6 (或其它I2C SCL引脚) | I2C时钟线 |
| SDA | PB7 (或其它I2C SDA引脚) | I2C数据线 |
| A0 | GND或VCC | 地址选择引脚0 |
| A1 | GND或VCC | 地址选择引脚1 |
INA226的I2C地址由A0和A1引脚决定:
- 两个都接地(GND):0x40 (7位地址)
- 在代码中,HAL库通常需要将7位地址左移1位(0x40 << 1 = 0x80)
2. HMI串口屏与STM32连接 (UART接口)
| HMI串口屏引脚 | STM32 引脚 | 说明 |
|---|---|---|
| RX | PA2 (USART2_TX) | 串口接收数据 |
| TX | PA3 (USART2_RX) | 串口发送数据(可选) |
| GND | GND | 共同地线 |
| VCC | 5V或3.3V | 电源(根据屏规格) |
3. INA226 与被测电路连接
| INA226 引脚 | 被测电路连接 | 说明 |
|---|---|---|
| V+ | 电源正极 | 测量总线电压 |
| V- | 负载输入正极 | |
| S+ | 电源正极 | 电流检测正 |
| S- | 负载输入正极 | 电流检测负 |
注意:需要在S+和S-之间连接一个分流电阻(Shunt Resistor),例如0.1Ω/1W的精密电阻。电流通过测量该电阻两端的压降计算得出。
STM32代码实现 (HAL库)
1. INA226驱动代码 (ina226.c / ina226.h)
首先,我们需要编写INA226的驱动程序。
ina226.h
#ifndefINA226_H#defineINA226_H#include"stm32f1xx_hal.h"// 根据你的STM32系列调整// INA226寄存器地址#defineINA226_CONFIG_REG0x00#defineINA226_SHUNT_VOLTAGE_REG0x01#defineINA226_BUS_VOLTAGE_REG0x02#defineINA226_POWER_REG0x03#defineINA226_CURRENT_REG0x04#defineINA226_CALIBRATION_REG0x05#defineINA226_MASK_ENABLE_REG0x06#defineINA226_ALERT_LIMIT_REG0x07#defineINA226_MANUFACTURER_ID_REG0xFE#defineINA226_DIE_ID_REG0xFF// INA226默认I2C地址(A0和A1接地)#defineINA226_ADDRESS0x80// (0x40 << 1)// 配置寄存器设置(根据你的需求调整)#defineINA226_CONFIG_DEFAULT0x4727// 0100 0111 0010 0111// 函数声明voidINA226_Init(I2C_HandleTypeDef*hi2c);floatINA226_ReadBusVoltage(void);floatINA226_ReadShuntVoltage(void);floatINA226_ReadCurrent(void);floatINA226_ReadPower(void);uint16_tINA226_ReadManufacturerID(void);uint16_tINA226_ReadDieID(void);externI2C_HandleTypeDef hi2c1;// 你的I2C句柄#endifina226.c
#include"ina226.h"#include<math.h>// I2C句柄I2C_HandleTypeDef*ina226_i2c;// 校准值(需要根据你的分流电阻计算)staticuint16_tcalibrationValue=0;// 将在Init中计算voidINA226_Init(I2C_HandleTypeDef*hi2c){ina226_i2c=hi2c;// 验证器件IDuint16_tmanufID=INA226_ReadManufacturerID();uint16_tdieID=INA226_ReadDieID();// 预期值:制造商ID应为0x5449,芯片ID应为0x2260if(manufID!=0x5449||dieID!=0x2260){// 器件识别失败,处理错误Error_Handler();}// 计算校准值(示例:分流电阻0.1Ω,最大预期电流2A)// 公式:Cal = 0.00512 / (Current_LSB * Rshunt)// Current_LSB = 最大预期电流 / 2^15floatmaxExpectedCurrent=2.0;// 2AfloatrShunt=0.1;// 0.1ΩfloatcurrentLSB=maxExpectedCurrent/32768.0;calibrationValue=(uint16_t)(0.00512/(currentLSB*rShunt));// 写入校准寄存器uint8_tcalibData[3]={INA226_CALIBRATION_REG,(uint8_t)(calibrationValue>>8),(uint8_t)(calibrationValue&0xFF)};HAL_I2C_Master_Transmit(ina226_i2c,INA226_ADDRESS,calibData,3,HAL_MAX_DELAY);// 写入配置寄存器uint8_tconfigData[3]={INA226_CONFIG_REG,(uint8_t)(INA226_CONFIG_DEFAULT>>8),(uint8_t)(INA226_CONFIG_DEFAULT&0xFF)};HAL_I2C_Master_Transmit(ina226_i2c,INA226_ADDRESS,configData,3,HAL_MAX_DELAY);}// 读取总线电压(单位:伏特)floatINA226_ReadBusVoltage(){uint8_treg=INA226_BUS_VOLTAGE_REG;uint8_tdata[2];HAL_I2C_Master_Transmit(ina226_i2c,INA226_ADDRESS,®,1,HAL_MAX_DELAY);HAL_I2C_Master_Receive(ina226_i2c,INA226_ADDRESS,data,2,HAL_MAX_DELAY);uint16_tvoltageRaw=(data[0]<<8)|data[1];returnvoltageRaw*0.00125;// 1.25mV/LSB}// 读取电流值(单位:安培)floatINA226_ReadCurrent(){uint8_treg=INA226_CURRENT_REG;uint8_tdata[2];HAL_I2C_Master_Transmit(ina226_i2c,INA226_ADDRESS,®,1,HAL_MAX_DELAY);HAL_I2C_Master_Receive(ina226_i2c,INA226_ADDRESS,data,2,HAL_MAX_DELAY);int16_tcurrentRaw=(data[0]<<8)|data[1];// 计算Current_LSBfloatmaxExpectedCurrent=2.0;// 与初始化时一致floatcurrentLSB=maxExpectedCurrent/32768.0;returncurrentRaw*currentLSB;}// 读取其他数据的函数类似实现...uint16_tINA226_ReadManufacturerID(){uint8_treg=INA226_MANUFACTURER_ID_REG;uint8_tdata[2];HAL_I2C_Master_Transmit(ina226_i2c,INA226_ADDRESS,®,1,HAL_MAX_DELAY);HAL_I2C_Master_Receive(ina226_i2c,INA226_ADDRESS,data,2,HAL_MAX_DELAY);return(data[0]<<8)|data[1];}uint16_tINA226_ReadDieID(){uint8_treg=INA226_DIE_ID_REG;uint8_tdata[2];HAL_I2C_Master_Transmit(ina226_i2c,INA226_ADDRESS,®,1,HAL_MAX_DELAY);HAL_I2C_Master_Receive(ina226_i2c,INA226_ADDRESS,data,2,HAL_MAX_DELAY);return(data[0]<<8)|data[1];}2. 主程序代码 (main.c)
#include"main.h"#include"stm32f1xx_hal.h"#include"ina226.h"#include<stdio.h>#include<string.h>// 全局变量I2C_HandleTypeDef hi2c1;UART_HandleTypeDef huart2;// 函数声明voidSystemClock_Config(void);staticvoidMX_GPIO_Init(void);staticvoidMX_I2C1_Init(void);staticvoidMX_USART2_UART_Init(void);voidSendToHMI(constchar*variable,floatvalue);intmain(void){HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_I2C1_Init();MX_USART2_UART_Init();// 初始化INA226INA226_Init(&hi2c1);// 给INA226和HMI屏一点启动时间HAL_Delay(100);charmsg[50];sprintf(msg,"System Started\r\n");HAL_UART_Transmit(&huart2,(uint8_t*)msg,strlen(msg),HAL_MAX_DELAY);while(1){// 读取电流值floatcurrent=INA226_ReadCurrent();// 发送到HMI串口屏SendToHMI("current",current);// 可选:读取并发送其他值floatvoltage=INA226_ReadBusVoltage();SendToHMI("voltage",voltage);// 每秒更新一次(可根据需要调整)HAL_Delay(1000);}}// 发送数据到HMI串口屏的函数voidSendToHMI(constchar*variable,floatvalue){charbuffer[50];if(strcmp(variable,"current")==0){// 发送电流值到HMI的n0组件(数值显示)sprintf(buffer,"n0.val=%d\xFF\xFF\xFF",(int)(value*1000));// 转换为毫安HAL_UART_Transmit(&huart2,(uint8_t*)buffer,strlen(buffer),HAL_MAX_DELAY);// 可选:同时发送到文本组件显示更详细的信息sprintf(buffer,"t0.txt=\"%.2fA\"\xFF\xFF\xFF",value);HAL_UART_Transmit(&huart2,(uint8_t*)buffer,strlen(buffer),HAL_MAX_DELAY);}elseif(strcmp(variable,"voltage")==0){// 发送电压值到HMI的n1组件sprintf(buffer,"n1.val=%d\xFF\xFF\xFF",(int)(value*1000));// 转换为毫伏HAL_UART_Transmit(&huart2,(uint8_t*)buffer,strlen(buffer),HAL_MAX_DELAY);sprintf(buffer,"t1.txt=\"%.2fV\"\xFF\xFF\xFF",value);HAL_UART_Transmit(&huart2,(uint8_t*)buffer,strlen(buffer),HAL_MAX_DELAY);}}// 系统时钟配置voidSystemClock_Config(void){// 根据你的STM32型号配置}// I2C初始化staticvoidMX_I2C1_Init(void){hi2c1.Instance=I2C1;hi2c1.Init.ClockSpeed=400000;// 400kHzhi2c1.Init.DutyCycle=I2C_DUTYCYCLE_2;hi2c1.Init.OwnAddress1=0;hi2c1.Init.AddressingMode=I2C_ADDRESSINGMODE_7BIT;hi2c1.Init.DualAddressMode=I2C_DUALADDRESS_DISABLE;hi2c1.Init.OwnAddress2=0;hi2c1.Init.GeneralCallMode=I2C_GENERALCALL_DISABLE;hi2c1.Init.NoStretchMode=I2C_NOSTRETCH_DISABLE;HAL_I2C_Init(&hi2c1);}// USART2初始化(用于HMI串口屏)staticvoidMX_USART2_UART_Init(void){huart2.Instance=USART2;huart2.Init.BaudRate=9600;// 或115200,根据你的HMI屏设置huart2.Init.WordLength=UART_WORDLENGTH_8B;huart2.Init.StopBits=UART_STOPBITS_1;huart2.Init.Parity=UART_PARITY_NONE;huart2.Init.Mode=UART_MODE_TX_RX;huart2.Init.HwFlowCtl=UART_HWCONTROL_NONE;huart2.Init.OverSampling=UART_OVERSAMPLING_16;HAL_UART_Init(&huart2);}// GPIO初始化staticvoidMX_GPIO_Init(void){// GPIO初始化代码}HMI串口屏配置
HMI串口屏通常使用USART HMI或类似的软件进行配置。
1. 在HMI屏上创建显示元件
- 添加一个数值显示元件(如n0)用于显示电流值
- 添加一个文本显示元件(如t0)用于显示带单位的电流值
2. HMI屏指令格式
STM32需要按照HMI屏的协议格式发送数据:
指令格式:组件ID.属性=值[0xFF 0xFF 0xFF] 示例:n0.val=1000\xFF\xFF\xFF(设置n0组件的值为1000)参考代码 STM32读取INA226的电流值 并用串口发送给HMI串口屏显示www.3dddown.com/csa/56677.html
调试与优化建议
I2C通信调试:
- 如果读取不到INA226的数据,先用逻辑分析仪或示波器检查I2C信号。
- 确认INA226的地址是否正确(A0和A1引脚电平决定地址)。
- 检查I2C线路上是否有适当的上拉电阻(通常4.7kΩ)。
电流测量校准:
- INA226的测量精度高度依赖校准寄存器的设置。校准公式为:
CAL = 0.00512 / (Current_LSB × Rshunt)
其中Current_LSB = 最大预期电流 / 32768 - 可以用万用表测量实际电流,与INA226读数对比,微调校准值。
- INA226的测量精度高度依赖校准寄存器的设置。校准公式为:
串口通信调试:
- 确保STM32与HMI屏的波特率、数据位、停止位和校验位设置一致。
- HMI指令必须以
0xFF 0xFF 0xFF结尾。
抗干扰处理:
- 电流检测路径(特别是分流电阻连接)应尽量短而直接,减少噪声干扰。
- 在INA226的电源引脚附近添加去耦电容(100nF)。
功能扩展:
- 可以增加功率计算和电能累计功能。
- 添加阈值报警功能,当电流超过设定值时,在HMI屏上显示警告。