活动任务三是使用INA219对测量5V,12V负载电压电流并显示在OLED。首先对硬件部分进行介绍。
# 硬件连接
开发板上的I2C3的SCL为PA8,SDA为PC9。

INA219模块的接口是I2C,连接开发板I2C3和模块的对应管脚,实现开发板与模块之间的硬件连接。另外,连接开关电源、稳压模块、继电器、OLED屏幕和负载。
连接12V负载的连接图如下,

检测负载的效果如下
# INA219驱动移植
INA219的驱动使用现有的libdriver中的INA219驱动。
https://gitee.com/libdriver/ina219
驱动库的代码分布如下,在移植时,复制驱动源码到工程中,参考驱动接口中的模板实现MCU平台上的通讯接口,参考示例程序使用驱动函数获取INA219的信息。

使用上述驱动库,需要完成几个接口函数,针对开发板的实现如下
#include "driver_ina219_interface.h"
#include <stdarg.h>
#include <main.h>
/**
* @brief interface iic bus init
* @return status code
* - 0 success
* - 1 iic init failed
* @note none
*/
uint8_t ina219_interface_iic_init(void)
{
return 0;
}
/**
* @brief interface iic bus deinit
* @return status code
* - 0 success
* - 1 iic deinit failed
* @note none
*/
uint8_t ina219_interface_iic_deinit(void)
{
return 0;
}
/**
* @brief interface iic bus read
* @param[in] addr iic device write address
* @param[in] reg iic register address
* @param[out] *buf pointer to a data buffer
* @param[in] len length of the data buffer
* @return status code
* - 0 success
* - 1 read failed
* @note none
*/
uint8_t ina219_interface_iic_read(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len)
{
HAL_StatusTypeDef ret;
ret=HAL_I2C_Mem_Read(&hi2c3, addr, reg, 1, buf, len, HAL_MAX_DELAY);
if(ret!=HAL_OK)
return 1;
return 0;
}
/**
* @brief interface iic bus write
* @param[in] addr iic device write address
* @param[in] reg iic register address
* @param[in] *buf pointer to a data buffer
* @param[in] len length of the data buffer
* @return status code
* - 0 success
* - 1 write failed
* @note none
*/
uint8_t ina219_interface_iic_write(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len)
{
HAL_StatusTypeDef ret;
ret=HAL_I2C_Mem_Write(&hi2c3, addr, reg, 1, buf, len, HAL_MAX_DELAY);
if(ret!=HAL_OK)
return 1;
return 0;
}
/**
* @brief interface delay ms
* @param[in] ms time
* @note none
*/
void ina219_interface_delay_ms(uint32_t ms)
{
HAL_Delay(ms);
}在工程中添加驱动相关的代码文件,并且在工程的路径中添加存放代码的文件夹路径。

这样,就可以在工程中调用驱动库中的函数来使用INA219检测设备的功率信息。
# INA219驱动使用
在工程中,封装INA219的初始化过程和功率信息的操作为以下两个函数:
uint8_t ina219_basic_init(ina219_address_t addr_pin, double r)
{
uint8_t res;
uint16_t calibration;
/* link interface function */
DRIVER_INA219_LINK_INIT(&gs_handle, ina219_handle_t);
DRIVER_INA219_LINK_IIC_INIT(&gs_handle, ina219_interface_iic_init);
DRIVER_INA219_LINK_IIC_DEINIT(&gs_handle, ina219_interface_iic_deinit);
DRIVER_INA219_LINK_IIC_READ(&gs_handle, ina219_interface_iic_read);
DRIVER_INA219_LINK_IIC_WRITE(&gs_handle, ina219_interface_iic_write);
DRIVER_INA219_LINK_DELAY_MS(&gs_handle, ina219_interface_delay_ms);
DRIVER_INA219_LINK_DEBUG_PRINT(&gs_handle, ina219_interface_debug_print);
/* set addr pin */
res = ina219_set_addr_pin(&gs_handle, addr_pin);
if (res != 0)
{
return 1;
}
/* set the r */
res = ina219_set_resistance(&gs_handle, r);
if (res != 0)
{
return 1;
}
/* init */
res = ina219_init(&gs_handle);
if (res != 0)
{
return 1;
}
/* set bus voltage range */
res = ina219_set_bus_voltage_range(&gs_handle, INA219_BASIC_DEFAULT_BUS_VOLTAGE_RANGE);
if (res != 0)
{
(void)ina219_deinit(&gs_handle);
return 1;
}
/* set bus voltage adc mode */
res = ina219_set_bus_voltage_adc_mode(&gs_handle, INA219_BASIC_DEFAULT_BUS_VOLTAGE_ADC_MODE);
if (res != 0)
{
(void)ina219_deinit(&gs_handle);
return 1;
}
/* set shunt voltage adc mode */
res = ina219_set_shunt_voltage_adc_mode(&gs_handle, INA219_BASIC_DEFAULT_SHUNT_VOLTAGE_ADC_MODE);
if (res != 0)
{
(void)ina219_deinit(&gs_handle);
return 1;
}
/* set shunt bus voltage continuous */
res = ina219_set_mode(&gs_handle, INA219_MODE_SHUNT_BUS_VOLTAGE_CONTINUOUS);
if (res != 0)
{
(void)ina219_deinit(&gs_handle);
return 1;
}
/* set pga */
res = ina219_set_pga(&gs_handle, INA219_BASIC_DEFAULT_PGA);
if (res != 0)
{
(void)ina219_deinit(&gs_handle);
return 1;
}
/* calculate calibration */
res = ina219_calculate_calibration(&gs_handle, (uint16_t *)&calibration);
if (res != 0)
{
(void)ina219_deinit(&gs_handle);
return 1;
}
/* set calibration */
res = ina219_set_calibration(&gs_handle, calibration);
if (res != 0)
{
(void)ina219_deinit(&gs_handle);
return 1;
}
return 0;
}
/**
* @brief basic example read
* @param[out] *mV pointer to a mV buffer
* @param[out] *mA pointer to a mA buffer
* @param[out] *mW pointer to a mW buffer
* @return status code
* - 0 success
* - 1 read failed
* @note none
*/
uint8_t ina219_basic_read(float *mV, float *mA, float *mW)
{
uint8_t res;
int16_t s_raw;
uint16_t u_raw;
/* read bus voltage */
res = ina219_read_bus_voltage(&gs_handle, (uint16_t *)&u_raw, mV);
if (res != 0)
{
return 1;
}
/* read current */
res = ina219_read_current(&gs_handle, (int16_t *)&s_raw, mA);
if (res != 0)
{
return 1;
}
/* read power */
res = ina219_read_power(&gs_handle, (uint16_t *)&u_raw, mW);
if (res != 0)
{
return 1;
}
return 0;
}在主函数中调用定义的INA219初始化函数以及功率信息读取函数来获取功率信息。
ina219_basic_init(INA219_ADDRESS_0, 0.01); ina219_interface_delay_ms(1000); ina219_basic_read(&mV, &mA, &mW);
将获取到到的功率信息显示在OLED屏幕上
float mV;
float mA,mA_sum,mA_ave;
float mW;
static ina219_handle_t gs_handle; /**< ina219 handle */
static char V_info[32];
static char I_info[32];
static char W_info[32];
while (1)
{
u8g2_ClearDisplay(&myDisplay);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
sprintf(V_info,"电压:%.2fmV",mV);
sprintf(I_info,"电流:%.2fmA",mA_ave);
sprintf(W_info,"功率:%.2fmW",mW);
u8g2_DrawUTF8(&myDisplay,0,16,"功率检测和显示");
u8g2_DrawUTF8(&myDisplay,0,32,V_info);
u8g2_DrawUTF8(&myDisplay,0,48,I_info);
u8g2_DrawUTF8(&myDisplay,0,64,W_info);
u8g2_SendBuffer(&myDisplay);
}# 实际效果演示
选择一个路由器作为12负载,在连接后INA219采集到功率数据如下图所示。

配套的电机工作电压为3V,电机和其他部分连接如下。

读取到的功率信息如下所示。

# 总结
使用现有的libdriver驱动INA219,在使用时只需要实现不同MCU的通讯接口就可以使用函数库的功能,可以快速上手,对于初期开发是有参考价值的,后续可在此基础上进行驱动的优化。
我要赚赏金
