新唐单片机与INA226实现高精度数字电压电流表

新唐单片机与INA226实现高精度数字电压电流表

1. 项目背景与核心器件选型

在电子测量领域,电压电流表头是最基础也最常用的工具之一。传统指针式表头虽然直观,但精度和功能扩展性有限。基于单片机的数字表头不仅读数精确,还能实现数据记录、报警阈值设置等智能功能。这次我选择新唐单片机搭配INA226的方案,主要看中其高性价比和易用性。

1.1 为什么选择新唐单片机

新唐科技(Nuvoton)的8051内核单片机在工控领域应用广泛,特别是NuMicro系列。以常用的N76E003为例,它具备以下优势:

  • 内置16KB Flash和1KB SRAM,足够处理测量数据
  • 12位ADC分辨率,基准电压可选内部2.4V或外部输入
  • 支持硬件SPI接口,与INA226通信更高效
  • 工作电压2.4V-5.5V,适合电池供电场景
  • 价格通常在5元以内,性价比极高

相比STM32等ARM内核芯片,新唐单片机开发环境更简单,特别适合快速原型开发。我用的是Keil C51开发环境,配合Nu-Link调试器,烧录调试都很方便。

1.2 INA226的关键特性

INA226是TI推出的双向电流/功率监测芯片,通过I2C接口输出数据。其核心参数:

  • 测量范围:±36V总线电压,±3.2A电流(可外接分流电阻扩展)
  • 内置0.1Ω分流电阻(最大耐受2W功耗)
  • 16位ADC,电压测量精度±0.1%
  • 可编程警报输出
  • 工作电压3-5.5V

这个芯片最实用的特点是自带校准功能,通过写入校准寄存器值(0x0054)即可自动计算电流值,省去了软件校准的麻烦。实际测试在0-3A范围内线性度非常好。

2. 硬件电路设计详解

2.1 整体架构设计

系统框图如下:

[被测电路] → [INA226] ←I2C→ [新唐单片机] → SPI→ [OLED] ↑(分流电阻) ↑ └───── 供电 ─────┘

2.2 关键电路设计要点

INA226外围电路:

  1. 电源引脚:VCC接3.3V,GND接地
  2. 总线电压检测:VBUS+接被测电压正极,VBUS-接负极
  3. 分流电阻连接:IN+和IN-之间接被测电路电流路径
  4. I2C接口:SCL/SDA接单片机对应引脚,需加上拉电阻(4.7kΩ)

特别注意:

  • 当测量高压(>28V)时,需要在VBUS+串联100kΩ电阻保护
  • 分流电阻功率要足够,建议选用1206封装1%精度的合金电阻
  • 布局时INA226要尽量靠近测量点,避免引线电阻引入误差

2.3 单片机最小系统

新唐N76E003的最小系统包含:

  1. 电源电路:AMS1117-3.3稳压芯片,输入5V输出3.3V
  2. 复位电路:10kΩ上拉电阻+104电容
  3. 晶振电路:内置RC振荡器(可外接12MHz晶振提高精度)
  4. 调试接口:SWD四线接口(SWDIO/SWCLK/RST/GND)

3. 软件实现关键代码解析

3.1 INA226驱动开发

首先定义器件地址和寄存器映射:

#define INA226_ADDR 0x40 // A0=A1=GND时的地址 typedef enum { INA226_REG_CONFIG = 0x00, INA226_REG_SHUNT_VOLTAGE = 0x01, INA226_REG_BUS_VOLTAGE = 0x02, INA226_REG_CALIBRATION = 0x05 } INA226_Registers;

初始化配置函数:

void INA226_Init(void) { // 设置采样参数:平均128次,总线电压采样8.244ms I2C_WriteWord(INA226_ADDR, INA226_REG_CONFIG, 0x47FF); // 写入校准值:0.1Ω分流电阻,最大3.2A I2C_WriteWord(INA226_ADDR, INA226_REG_CALIBRATION, 0x0054); }

数据读取函数示例:

float ReadBusVoltage(void) { uint16_t raw = I2C_ReadWord(INA226_ADDR, INA226_REG_BUS_VOLTAGE); return raw * 1.25f; // 1.25mV/LSB }

3.2 OLED显示驱动

使用硬件SPI驱动OLED 12864屏幕:

void OLED_ShowMeasurement(float voltage, float current) { char buf[16]; OLED_Clear(); sprintf(buf, "V: %.2f V", voltage); OLED_ShowString(0, 0, buf); sprintf(buf, "I: %.3f A", current); OLED_ShowString(0, 2, buf); // 计算并显示功率 float power = voltage * current; sprintf(buf, "P: %.2f W", power); OLED_ShowString(0, 4, buf); }

4. 校准与精度优化实践

4.1 三点校准法

为提高测量精度,建议采用三点校准:

  1. 零点校准:输入端短路,读取偏移值
  2. 满量程校准:施加已知电流(如1A标准源)
  3. 中间点验证:检查线性度

校准数据存储到单片机Flash中,上电时自动加载。

4.2 软件滤波算法

实测中发现电源噪声会影响测量值,采用滑动平均滤波:

#define FILTER_SIZE 8 float voltage_buffer[FILTER_SIZE]; uint8_t filter_index = 0; float Filter_Voltage(float new_val) { voltage_buffer[filter_index] = new_val; filter_index = (filter_index + 1) % FILTER_SIZE; float sum = 0; for(int i=0; i<FILTER_SIZE; i++) { sum += voltage_buffer[i]; } return sum / FILTER_SIZE; }

4.3 温度补偿

INA226的精度会受温度影响,可通过以下方式补偿:

  1. 测量芯片温度(内置传感器)
  2. 根据温度-误差曲线进行修正
  3. 公式:V_corrected = V_raw × (1 + 0.0005×(T-25))

5. 常见问题与解决方案

5.1 I2C通信失败排查

现象:单片机无法读取INA226数据 排查步骤:

  1. 检查电源电压(3.3V要稳定)
  2. 测量SCL/SDA波形(应有标准方波)
  3. 确认上拉电阻值(4.7kΩ最佳)
  4. 检查地址配置(A0/A1引脚电平)

5.2 测量值跳变问题

可能原因及解决:

  1. 电源噪声 → 增加10μF电解电容
  2. 分流电阻发热 → 改用更大封装电阻
  3. SPI与I2C干扰 → 分开布线,降低时钟频率

5.3 量程扩展技巧

当需要测量更大电流时:

  1. 外接分流电阻(如0.01Ω/5W)
  2. 修改校准寄存器值:
    // 新分流电阻0.01Ω,最大10A uint16_t cal = 0.00512 / (0.01 * 0.00002); I2C_WriteWord(INA226_ADDR, INA226_REG_CALIBRATION, cal);

6. 进阶功能扩展

6.1 数据记录功能

添加SD卡模块,实现测量数据存储:

void SaveToSD(float v, float i) { FIL file; f_open(&file, "data.csv", FA_WRITE | FA_OPEN_ALWAYS); f_lseek(&file, f_size(&file)); char buf[64]; sprintf(buf, "%.2f,%.3f\n", v, i); f_puts(buf, &file); f_close(&file); }

6.2 蓝牙传输

通过HC-05模块上传数据到手机:

  1. 配置蓝牙模块为从机模式
  2. 单片机通过UART发送AT指令
  3. 手机端用Serial Bluetooth Terminal等APP接收

6.3 报警功能实现

利用INA226的警报引脚:

// 设置电流超限报警(3A) I2C_WriteWord(INA226_ADDR, 0x06, 0x8000); // 警报使能 I2C_WriteWord(INA226_ADDR, 0x07, 3000); // 3A对应值 // 中断服务函数 void EXTI_IRQHandler(void) { if(EXTI_GetFlag(ALERT_PIN)) { Buzzer_On(); // 触发蜂鸣器 EXTI_ClearFlag(); } }

这个项目最让我惊喜的是INA226的易用性,相比传统的运放方案,集成芯片大大降低了开发难度。实际测试在0-30V/0-3A范围内,精度可以达到0.5%以内,完全满足日常电子制作需求。如果要做产品化改进,建议考虑添加隔离电路和外壳防护。