【驱动】ina3221 德州仪器3通道电流采样芯片驱动

说明

基于stm32f103的ina3221电流采样芯片驱动,使用LL库进行开发。已经过验证。
INA3221 是一款三通道、高侧电流和总线电压监视器,具有一个兼容I2C 和SMBUS 的接口。INA3221不仅能够监视分流压降和总线电源电压,还针对这些信号提供有可编程的转换时间和平均值计算模式。INA3221 提供关键报警和警告报警,用于检测每条通道上可编程的多种超范围情况。
INA3221 感测总线(电压在0V 至+26V 范围内变化)上的电流。此器件由2.7V 至5.5V 单电源供电,电源电流消耗为350μA(典型值)。INA3221 的额定运行温度范围为-40°C 至+125°C。兼容I2C 和SMBUS 的接口具有四个可编程地址。

代码

INA3221.h

/*
 * @Author: xmprocat
 * @Date: 2022-07-31 15:36:14
 * @LastEditors: xmprocat
 * @LastEditTime: 2022-08-06 21:24:03
 * @Description: 
 */
#ifndef __INA3221_H
#define __INA3221_H
#include "stdint.h"

#define INA3221_ADDR1 0x80  // A0=GND
#define INA3221_ADDR2 0x82  // A0=VS
#define INA3221_ADDR3 0x84  // A0=SDA
#define INA3221_ADDR4 0x86  // A0=SCL

void INA3221_Init(uint8_t addr);
uint16_t INA3221_GetVoltage(uint8_t addr, uint8_t channel);
uint16_t INA3221_GetShuntVoltage(uint8_t addr, uint8_t channel);

#endif

INA3221.c

/*
 * @Author: xmprocat
 * @Date: 2022-07-31 15:35:40
 * @LastEditors: xmprocat
 * @LastEditTime: 2022-08-06 21:23:35
 * @Description: ina3221 模拟IIC驱动
 */

#include "INA3221.h"
#include "stm32f1xx_ll_utils.h"
#include "stm32f1xx_ll_gpio.h"

/*****************硬件连接定义*********************/
#define INA3221_SCL_PORT GPIOB
#define INA3221_SCL_PIN LL_GPIO_PIN_6

#define INA3221_SDA_PORT GPIOB
#define INA3221_SDA_PIN LL_GPIO_PIN_7

/************************延时接口****************************/
#define delay_nms_3221 LL_mDelay       //毫秒延时
// #define delay_nns_3221 delay_nus_3221       //毫秒延时

#define INA3221_CFG_REG         0x00    //配置寄存器
#define INA3221_CH1SHUNT_REG    0x01    //通道 1 分流电压
#define INA3221_CH1BUS_REG      0x02    //通道 1 总线电压
#define INA3221_CH2SHUNT_REG    0x03    //通道 2 分流电压
#define INA3221_CH2BUS_REG      0x04    //通道 2 总线电压
#define INA3221_CH3SHUNT_REG    0x05    //通道 3 分流电压
#define INA3221_CH3BUS_REG      0x06    //通道 3 总线电压
#define INA3221_CH1CAL_REG      0x07    //通道 1 严重警报限制
#define INA3221_CH1WAL_REG      0x08    //通道 1 警告警报限制
#define INA3221_CH2CAL_REG      0x09    //通道 2 严重警报限制
#define INA3221_CH2WAL_REG      0x0A    //通道 2 警告警报限制
#define INA3221_CH3CAL_REG      0x0B    //通道 3 严重警报限制
#define INA3221_CH3WAL_REG      0x0C    //通道 3 警告警报限制
#define INA3221_SVS_REG         0x0D    //分流电压和
#define INA3221_SVSLIMIT_REG    0x0E    //分流电压和限制
#define INA3221_ME_REG          0x0F    //屏蔽/启用 警报
#define INA3221_PVUPPER_REG     0x10    //功率有效上限
#define INA3221_PVLOW_REG       0x11    //功率有效下限
#define INA3221_MANUID_REG      0xFE    //制造商标识号
#define INA3221_DIEID_REG       0xFF    //模具标识号

#define INA3221_MANU_ID     0x5449  //唯一制造商标识号
#define INA3221_DIE_ID      0x3220  //唯一模具标识号


#define IIC_SCL_L_3221 LL_GPIO_ResetOutputPin(INA3221_SCL_PORT, INA3221_SCL_PIN)
#define IIC_SCL_H_3221 LL_GPIO_SetOutputPin(INA3221_SCL_PORT, INA3221_SCL_PIN)

#define IIC_SDA_L_3221 LL_GPIO_ResetOutputPin(INA3221_SDA_PORT, INA3221_SDA_PIN)
#define IIC_SDA_H_3221 LL_GPIO_SetOutputPin(INA3221_SDA_PORT, INA3221_SDA_PIN)
#define SDA_READ_3221 LL_GPIO_IsInputPinSet(INA3221_SDA_PORT, INA3221_SDA_PIN)
#define SDA_IN_3221                                                                \
    do                                                                             \
    {                                                                              \
        LL_GPIO_SetPinMode(INA3221_SDA_PORT, INA3221_SDA_PIN, LL_GPIO_MODE_INPUT); \
    } while (0)
#define SDA_OUT_3221                                                                \
    do                                                                              \
    {                                                                               \
        LL_GPIO_SetPinMode(INA3221_SDA_PORT, INA3221_SDA_PIN, LL_GPIO_MODE_OUTPUT); \
    } while (0)


static void delay_nns_3221(uint16_t D) // 30纳秒ns  根据手册要用到IIC的HS高速模式
{
    while (--D)
        ;
}

/**
 * @description: stm32f103c8t6 微秒延迟函数 72Mhz
 * @param {uint16_t} us
 * @return {*}
 */
void delay_nus_3221(uint16_t us)
{
    uint32_t temp;
    SysTick->LOAD = us * (72000000 / 8000000); //时间加载
    SysTick->VAL = 0x00;                       //清空计数器
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;  //开始倒数
    do
    {
        temp = SysTick->CTRL;
    } while ((temp & 0x01) && !(temp & (1 << 16))); //等待时间到达
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;      //关闭计数器
    SysTick->VAL = 0X00;                            //清空计数器
}

/************************模拟IIC接口****************************/
void INA3221_IIC_Init(void)
{
    // IO初始化设置由cubeMX完成 移植的话需要在此处实现IO初始化

    IIC_SDA_H_3221;
    IIC_SCL_H_3221;

    delay_nms_3221(5);
}
void INA3221_IIC_Start(void)
{
    IIC_SDA_H_3221;
    IIC_SCL_H_3221;
    delay_nns_3221(5);
    IIC_SDA_L_3221; // START:when CLK is high,DATA change form high to low
    delay_nns_3221(5);
    IIC_SCL_L_3221; //钳住I2C总线,准备发送或接收数据
    delay_nns_3221(5);
}

void INA3221_IIC_Stop(void)
{
    IIC_SDA_L_3221; // STOP:when CLK is high DATA change form low to high
    delay_nns_3221(5);
    IIC_SCL_H_3221;
    delay_nns_3221(5);
    IIC_SDA_H_3221; //发送I2C总线结束信号
    delay_nns_3221(5);
}

void INA3221_IIC_Ack(void)
{
    IIC_SDA_L_3221;
    delay_nns_3221(5);
    IIC_SCL_H_3221;
    delay_nns_3221(5);
    IIC_SCL_L_3221;
    delay_nns_3221(5);
    IIC_SDA_H_3221;
}

void INA3221_IIC_NAck(void)
{
    IIC_SDA_H_3221;
    delay_nns_3221(5);
    IIC_SCL_H_3221;
    delay_nns_3221(5);
    IIC_SCL_L_3221;
    delay_nns_3221(5);
    IIC_SDA_L_3221;
}

uint8_t INA3221_IIC_Wait_Ack(void)
{
    uint8_t ucErrTime = 0;
    IIC_SDA_H_3221;
    SDA_IN_3221; // SDA设置为输入
    delay_nns_3221(5);
    IIC_SCL_H_3221;
    delay_nns_3221(5);

    while (SDA_READ_3221)
    {
        ucErrTime++;
        if (ucErrTime > 250)
        {
            INA3221_IIC_Stop();
            return 1;
        }
    }
    IIC_SCL_L_3221; //时钟输出0
    SDA_OUT_3221; // SDA设置为输入
    return 0;
}

void INA3221_IIC_Send_Byte(uint8_t txd)
{
    IIC_SCL_L_3221; //拉低时钟开始数据传输
    for (uint8_t i = 0; i < 8; i++)
    {
        if (txd & 0x80)
            IIC_SDA_H_3221;
        else
            IIC_SDA_L_3221;
        txd <<= 1;

        IIC_SCL_H_3221;
        delay_nns_3221(5);
        IIC_SCL_L_3221;
        delay_nns_3221(5);
    }
    //    IIC_SDA_H_3221;
    //    IIC_SCL_H_3221;            //当去掉wait_ack时的时候添加
    //    delay_nns_3221(5);
    // IIC_SCL_L_3221;
}

uint8_t INA3221_IIC_Read_Byte(unsigned char ack)
{
    uint8_t TData = 0, i;
    SDA_IN_3221; // SDA设置为输入
    for (i = 0; i < 8; i++)
    {
        IIC_SCL_H_3221;
        delay_nns_3221(5);
        TData = TData << 1;
        // if(GPIOB->IDR& GPIO_IDR_IDR7)        //判断SDA是否为高
        if (SDA_READ_3221)
        {
            TData |= 0x01;
        }
        IIC_SCL_L_3221;
        delay_nns_3221(5);
    }
    SDA_OUT_3221; // SDA设置为输出
    if (!ack)
        INA3221_IIC_NAck();
    else
        INA3221_IIC_Ack();

    return TData;
}


void INA3221_SendData(uint8_t addr, uint8_t reg, uint16_t data)
{
    uint8_t temp = 0;
    INA3221_IIC_Start();
    INA3221_IIC_Send_Byte(addr);
    INA3221_IIC_Wait_Ack();

    INA3221_IIC_Send_Byte(reg);
    INA3221_IIC_Wait_Ack();

    temp = (uint8_t)(data >> 8);
    INA3221_IIC_Send_Byte(temp);
    INA3221_IIC_Wait_Ack();

    temp = (uint8_t)(data & 0x00FF);
    INA3221_IIC_Send_Byte(temp);
    INA3221_IIC_Wait_Ack();

    INA3221_IIC_Stop();
}

void INA3221_SetRegPointer(uint8_t addr, uint8_t reg)
{
    INA3221_IIC_Start();

    INA3221_IIC_Send_Byte(addr);
    INA3221_IIC_Wait_Ack();

    INA3221_IIC_Send_Byte(reg);
    INA3221_IIC_Wait_Ack();

    INA3221_IIC_Stop();
}

uint16_t INA3221_ReadData(uint8_t addr)
{
    uint16_t temp = 0;
    INA3221_IIC_Start();

    INA3221_IIC_Send_Byte(addr + 1);
    INA3221_IIC_Wait_Ack();

    temp = INA3221_IIC_Read_Byte(1);
    temp <<= 8;
    temp |= INA3221_IIC_Read_Byte(0);

    INA3221_IIC_Stop();
    return temp;
}


/**
 * @description: INA3221自检
 * @param {uint8_t} addr
 * @return {*}
 */
void INA3221_SelfCheck(uint8_t addr)
{
    uint16_t id = 0;
    while (id != INA3221_DIE_ID)
    {
        delay_nms_3221(50);
        //卡这说明硬件连接异常或者是地址错误
        INA3221_SetRegPointer(addr, INA3221_DIEID_REG);
        id = INA3221_ReadData(addr);
    }
}

/********************************应用部分****************************************/

/**
 * @description: INA3221初始化
 * @return {*}
 */
void INA3221_Init(uint8_t addr)
{
    
    INA3221_IIC_Init();     //初始化IIC

    INA3221_SendData(addr, INA3221_CFG_REG, 0x8000); //软件复位
    LL_mDelay(10);

    // 配置寄存器设置控制三个输入通道的分流和总线电压测量的工作模式。 
    // 该寄存器控制分流和总线电压测量的转换时间设置以及使用的平均模式。 
    // 配置寄存器用于独立启用或禁用每个通道,以及选择控制选择要测量的信号的操作模式。
    // 详见数据手册P26
    INA3221_SendData(addr, INA3221_CFG_REG, 0x7127); // 7127为默认配置

    INA3221_SelfCheck(addr);
     
}

/**
 * @description: 获取电压
 * @param {uint8_t} addr
 * @param {uint8_t} channel 通道编号(1\2\3)
 * @return {uint16_t} 通道所对应的电压
 */
uint16_t INA3221_GetVoltage(uint8_t addr, uint8_t channel)
{
    uint32_t temp = 0;
    switch (channel)
    {
    case 1:
        INA3221_SetRegPointer(addr, INA3221_CH1BUS_REG);
        break;
    case 2:
        INA3221_SetRegPointer(addr, INA3221_CH2BUS_REG);
        break;
    case 3:
        INA3221_SetRegPointer(addr, INA3221_CH3BUS_REG);
        break;
    default:
        break;
    }
    temp = INA3221_ReadData(addr);
    if (temp & 0x8000)
        temp = ~(temp - 1);
    return (uint16_t)temp;
}


/**
 * @description: 获取分流电压
 * @param {uint8_t} addr    ina3221的IIC地址
 * @param {uint8_t} channel 通道编号(1\2\3)
 * @return {uint16_t} 通道的分流电压
 */
uint16_t INA3221_GetShuntVoltage(uint8_t addr, uint8_t channel)
{
    uint32_t temp = 0;
    switch (channel)
    {
    case 1:
        INA3221_SetRegPointer(addr, INA3221_CH1SHUNT_REG);
        break;
    case 2:
        INA3221_SetRegPointer(addr, INA3221_CH2SHUNT_REG);
        break;
    case 3:
        INA3221_SetRegPointer(addr, INA3221_CH3SHUNT_REG);
        break;
    default:
        break;
    }
    temp = INA3221_ReadData(addr);
    if (temp & 0x8000)
        temp = ~(temp - 1);
    return (uint16_t)temp;
}

硬件

image.png

结果

在这里插入图片描述

1bc74d11890cfe64b69c6af4bca7b53.jpg

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
INA3221电流监测芯片是一种具有高精度的电流监测芯片,可用于测量直流电源上的电流。当使用INA3221芯片监测电流时,如果出现电流异常,可能会出现以下情况: 1. 过载保护触发:INA3221芯片内置了过载保护功能,当被测电路中的电流超过芯片规定的最大电流范围时,芯片会自动触发过载保护功能,此时电流监测值会异常。 2. 供电电压异常:INA3221芯片需要通过供电电压来工作,如果供电电压不稳定或异常,可能导致芯片无法正常工作,进而导致电流监测值异常。 3. 接线错误:INA3221芯片需要正确连接到被测电路中,如果接线错误或接触不良,可能导致芯片无法准确测量电流值,从而出现电流监测异常。 对于INA3221电流监测芯片监测电流异常的处理方法如下: 1. 检查被测电路的电流是否超过芯片规定的最大电流范围,如果超过,应采取相应的措施,如减小负载或增加额外的保护措施,以确保电流在允许范围内。 2. 检查INA3221芯片的供电电压是否正常,如果不正常,应检查供电电压源是否稳定,并确保电压在芯片的工作范围内。 3. 检查INA3221芯片的接线是否正确,确认与被测电路的连接是否牢固可靠。如果发现问题,应及时修复或更换不良的接线。 总之,INA3221电流监测芯片监测电流异常可能是由于过载、供电电压异常或接线错误所致,需要检查相应的问题并采取适当的措施进行修复。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值