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

2023-11-09

说明

基于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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【驱动】ina3221 德州仪器3通道电流采样芯片驱动 的相关文章

  • 设计模式---中介者模式(DesignPattern_Mediator)

    摘录自 设计模式与游戏完美开发 十年磨一剑 作者将设计模式理论巧妙地融入到实践中 以一个游戏的完整实现呈现设计模式的应用及经验的传承 轩辕剑 之父 蔡明宏 资深游戏制作人 李佳泽 Product Evangelist at Unity Te
  • CRM接口开发日志

    文章目录 前言 一 Inbound WebService的创建 1 对应关系 2 通过BS创建Inbound WebService 入栈WS 创建IO 创建BS 创建Inbound WebService 测试 二 Outbound WebS
  • 动画实战:打造炫酷的加载动画

    前言 很多时候 我们的页面需要网络请求完毕再根据数据加载 UI 而在此过程中 用户等待时 一般会有一个加载中的提示 本文结合自定义 View ViewGroup 以及属性动画相关知识 讲述较为炫酷的动画效果的 LoadingView 并在细

随机推荐

  • Python入门(如何下载Python、Pycharm、和配置环境变量 )

    目录 一 如何下载Python windows版本 1 查看电脑查操作系统 2 Python官网网址 Welcome to Python org 二 下载Pycharm 1 Pycharm官网网址 PyCharm the Python ID
  • scrapy xpath解析出现:AttributeError: 'list' object has no attribute 'xpath'

    当我们在tbody标签里面取多个tr标签里面的内容时 我们一般都会取出个list集合 然后再进行遍历 获取里面的标签内容 node list response xpath class list 1 tr extract for node i
  • MySQL8.0 函数索引

    文章目录 MySQL8 0 函数索引 创建表与索引 针对JSON数据 创建索引 创建一个虚拟列 小问题 官方文档例子 总结 参考文档 MySQL8 0 函数索引 MySQL8 0 13 开始支持 在索引中使用函数的值 支持降序索引 支持JS
  • 【电路补习笔记】8、稳压电路 —— 线性电源及LDO

    目录 有名的电源芯片品牌 DCDC电源分类 开关电源vs线性稳压器 线性电源 参数 线性电源工作原理 集成稳压器 78 79系列 固定输出电压 正 负对称输出两组电源的稳压电路 扩展输出电压 扩大输出电流 LM317 LM337 可调输出电
  • 编程入门到进大厂,你需要这套学习架构

    我相信大多数学习编程的同学都有着对大公司的憧憬 技术 声望 薪资 福利 这些都足以成为吸引你进入大厂的理由 但是 如何进入大厂呢 对于很多同学来说 通往大厂的道路并不明朗 不知道是否有希望 也不知道怎么努力 感觉遥不可及 其实 我身边有很多
  • python range()函数 while循环 for in循环 break continue与else语句 嵌套循环

    range 函数的使用 1 用于生成一个整数序列 2 创建range对象的三种方式 lt 1 gt range stop gt 创建一个 0 stop 之间的整数序列 步长为1 第一种 range stop gt 创建一个 0 stop 之
  • C++ 简介

    C 简介 C 是一种静态类型的 编译式的 通用的 大小写敏感的 不规则的编程语言 支持过程化编程 面向对象编程和泛型编程 C 被认为是一种中级语言 它综合了高级语言和低级语言的特点 C 是由 Bjarne Stroustrup 于 1979
  • 变音量——动态规划

    问题描述 你将要在元旦演奏一场吉他专场 但你不希望声音平淡 所以你希望每个曲之间都有变化 现在你已经确定了每个曲可以与上一个曲之间的音量的变化量 即每首曲开始 你可以对音量选择增加或减少一个指定的变化值 当然音量不可能为负数 也不能太高 因
  • opensuse13.2上nfs无法使用

    转载 http bbs 51cto com thread 1134848 1 html 问题描述 板子设置挂载nfs文件系统启动 无法启动 错误提示见上图 设置nfs的步骤 1 vi etc exports 加入 home filesys
  • 【问题-已解决】Unity3d Animator的状态转换时,状态变量改变而State没有改变

    先给出素材 Tip Panel 动画状态机 用于控制Tip Panel的动画 通过将Exit变量设置为True时执行Tip Panel的退出动画 ClosePanel 代码 某用于统一管理Panel的管理类中统一关闭Panel的方法 通过传
  • Percona XtraBackup 安装介绍篇

    XtraBackup介绍 XtraBackup是Percona公司的开源项目 用以实现类似Innodb官方的热备份工具InnoDB Hot Backup的功能 它支持在线热备份 备份时不影响数据读写 到目前为止 最新的版本为Percona
  • 蓝桥杯2022年第十三届嵌入式详解

    此前也发了关于蓝桥杯的题目 昨天刚比完赛 放松了一下 没来得及整理 早上我就把我所有的思路整理了一下 发出来 希望能帮到大家 当然也有很多不足的地方 希望大家能提出 我们一起讨论 首先 关于题目的功能 我基本全部实现 一开始发题目 花了10
  • 大数据——Hadoop 知识点整理

    目录 1 大数据的特点 4V特征 2 谈谈 Hadoop 的优缺点 3 为什么 HDFS 不适合存小文件 4 Hadoop 的核心组件有哪些 并说明下功能 5 Hadoop 与关系型数据库对比 6 如果集群中 DataNode 出现错误 比
  • Mac使用Sequel Pro技巧

    智能提示 即auto completion功能 太慢 解决方法 performance gt query editor的auto completion下有delay by的选项 可以改为0 5 连接数据库 Add to Favorites
  • I2C基本概念讲解(时序,架构,速率)

    一 什么是I2C I2C是一种同步串口总线的协议 由NXP公司设计 主要的架构为一主多从 为什么IIC是同步串口总线 因为它是通过两根线在主控制器和从机进行通讯 一根为同步时钟线 SCL 一根为串行数据线 SDA 两根总线需要上拉电阻 总线
  • qml 静态编译程序执行错误 无法定位程序输入点 CreateDXGIFactory2 于动态链接库 dxgi.dll 上...

    重新编译 qt 静态库即可 或 删除该动态库 no feature d3d12 解决方案请参考如下网址 https forum qt io topic 78380 entry point not found the procedure en
  • 面Android的时候要想些什么

    http blog zhuimengfb com 2017 04 23 E9 9D A2Android E7 9A 84 E6 97 B6 E5 80 99 E8 A6 81 E6 83 B3 E4 BA 9B E4 BB 80 E4 B9
  • 再见,深圳。

    春去秋来 我已离开深圳好长一段时间了 回首最近的一年 就像是一场梦 一场让我无法忘记的梦 2011年6月份 我辞去了原先的工作 开始了新的职业旅程 其实在这之前的几年 我一直想从事软件业 可惜不得其门而入 仔细想想 根本的原因是自己把行业的
  • 最简易操作:让vscode终端支持x11图形化界面

    1 配置vscode ssh远程连接服务器 略 在vscode中远程 ssh 右键ssh打开ssh配置文件 添加以下三行 Host HostName User ForwardX11 yes ForwardX11Trusted yes For
  • 【驱动】ina3221 德州仪器3通道电流采样芯片驱动

    说明 基于stm32f103的ina3221电流采样芯片驱动 使用LL库进行开发 已经过验证 INA3221 是一款三通道 高侧电流和总线电压监视器 具有一个兼容I2C 和SMBUS 的接口 INA3221不仅能够监视分流压降和总线电源电压