• 注册 / 登录
  • 切换到窄版
  • 查看: 4945|回复: 2

    电压电流功率检测器INA226使用教程

    [复制链接]

    676

    主题

    690

    帖子

    6808

    积分

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    6808
    发表于 2022-1-19 10:37:54 | 显示全部楼层 |阅读模式

    路线栈欢迎您!

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    INA226是一路电压电流功率检测器,可以检测线电压,分流电阻的电压和分流电阻电流。

    具体实现要看INA226数据手册。

    INA226.c:
    1. #include "INA226.h"


    2. INA226 INA226_data;

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

    7. void delay_nms(uint16_t ms)  //毫秒
    8. {
    9.     uint16_t i;
    10.     uint32_t M = 0;//720W
    11.     for(i = 0;i < ms; i++)
    12.     for(M=12000;M > 0;M--);
    13. }

    14. void delay_nus(uint16_t us)//微秒
    15. {
    16.     uint16_t i;
    17.     uint16_t M = 0;//720W
    18.     for(i = 0;i < us; i++)
    19.     for(M=72;M > 0;M--);
    20. }

    21. /****************IIC***************************/
    22. void INA226_IIC_Init(void)
    23. {
    24.     GPIO_InitTypeDef GPIO_Initure;
    25.     __HAL_RCC_GPIOB_CLK_ENABLE();   //使能GPIOB时钟
    26.    
    27.      //PC11,12初始化设置
    28.     GPIO_Initure.Pin=GPIO_PIN_10|GPIO_PIN_11;//PB10SCL PB11SDA
    29.     GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽输出
    30.     GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
    31.     GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;     //高速
    32.     HAL_GPIO_Init(GPIOB,&GPIO_Initure);
    33.    
    34.     IIC_SDA_H;
    35.     IIC_SCL_H;  
    36.         delay_nms(5);
    37. }
    38.    
    39. void INA226_IIC_Start(void)
    40. {
    41.     IIC_SDA_H;            
    42.     IIC_SCL_H;
    43.     delay_nns(5);
    44.      IIC_SDA_L;//START:when CLK is high,DATA change form high to low
    45.     delay_nns(5);
    46.     IIC_SCL_L;//钳住I2C总线,准备发送或接收数据
    47.     delay_nns(5);
    48. }   

    49. void INA226_IIC_Stop(void)
    50. {
    51.     IIC_SDA_L;//STOP:when CLK is high DATA change form low to high
    52.      delay_nns(5);
    53.     IIC_SCL_H;
    54.         delay_nns(5);
    55.     IIC_SDA_H;//发送I2C总线结束信号
    56.     delay_nns(5);                                   
    57. }

    58. void INA226_IIC_Ack(void)
    59. {
    60.     IIC_SDA_L;
    61.     delay_nns(5);
    62.     IIC_SCL_H;
    63.     delay_nns(5);
    64.     IIC_SCL_L;
    65.         delay_nns(5);
    66.     IIC_SDA_H;
    67. }

    68. void INA226_IIC_NAck(void)
    69. {
    70.     IIC_SDA_H;
    71.     delay_nns(5);
    72.     IIC_SCL_H;
    73. delay_nns(5);
    74.     IIC_SCL_L;
    75.     delay_nns(5);
    76.     IIC_SDA_L;
    77. }        

    78. uint8_t INA226_IIC_Wait_Ack(void)
    79. {
    80.     uint8_t ucErrTime=0;
    81.     //SDA_IN();      //SDA设置为输入  
    82.     IIC_SDA_H;
    83.     delay_nns(5);      
    84.     IIC_SCL_H;
    85.     delay_nns(5);         
    86.    
    87.     while(READ_SDA)
    88.     {
    89.         ucErrTime++;
    90.         if(ucErrTime>250)
    91.         {
    92.             INA226_IIC_Stop();
    93.             return 1;
    94.         }
    95.     }
    96.     IIC_SCL_L;//时钟输出0        
    97.     return 0;  
    98. }

    99. void INA226_IIC_Send_Byte(uint8_t txd)
    100. {                              
    101.    IIC_SCL_L;//拉低时钟开始数据传输
    102.    for(uint8_t i = 0;i < 8;i++)
    103.     {              
    104.         if(txd&0x80)
    105.                     IIC_SDA_H;
    106.                 else
    107.                     IIC_SDA_L;               
    108.         txd<<=1;      
    109.                
    110.         IIC_SCL_H;
    111.         delay_nns(5);
    112.         IIC_SCL_L;
    113.         delay_nns(5);
    114.     }            
    115.     //    IIC_SDA_H;
    116.     //    IIC_SCL_H;            //当去掉wait_ack时的时候添加
    117.     //    delay_nns(5);
    118.         //IIC_SCL_L;
    119. }

    120. uint8_t INA226_IIC_Read_Byte(unsigned char ack)
    121. {
    122.       uint8_t TData=0,i;
    123.     for(i=0;i<8;i++)
    124.     {
    125.         IIC_SCL_H;
    126.         delay_nns(5);
    127.         TData=TData<<1;
    128.         //if(GPIOB->IDR& GPIO_IDR_IDR7)        //判断SDA是否为高
    129.             if(SDA_READ)
    130.         {
    131.             TData|=0x01;
    132.         }
    133.         IIC_SCL_L;
    134.         delay_nns(5);
    135.     }
    136.         if(!ack)
    137.             INA226_IIC_NAck();
    138.         else
    139.             INA226_IIC_Ack();
    140. //    IIC_SCL_L;
    141. //    delay_nns(5);
    142. //    IIC_SDA_L;
    143. //    delay_nns(5);                //ACK
    144. //    IIC_SCL_H;
    145. //    delay_nns(5);
    146. //    IIC_SCL_L;
    147. //    delay_nns(5);
    148. //    IIC_SDA_H;
    149.     return TData;
    150. }

    151. /**********************IIC_END*************************/

    152. void INA226_Init(void)
    153. {
    154.     INA226_IIC_Init();
    155.     HAL_Delay(10);
    156.     //    INA226_SendData(INA226_ADDR1,CFG_REG,0xC000);

    157. //    HAL_Delay(10);
    158.     //uint16_t cfg_reg_value = 0x4000|(3<<9)|(4<<6)|(4<<3)|7;
    159. //    INA226_SendData(INA226_ADDR1,CFG_REG,0x484f);
    160. //    INA226_SendData(INA226_ADDR1,CAL_REG,0x0012);
    161.     INA226_SendData(INA226_ADDR1,0x00,0x4727);
    162.     INA226_SendData(INA226_ADDR1,0x05,0x800);//A00
    163. }

    164. void INA226_SendData(uint8_t addr,uint8_t reg,uint16_t data)
    165. {
    166.     uint8_t temp = 0;
    167.     INA226_IIC_Start();
    168.     INA226_IIC_Send_Byte(addr);
    169.     INA226_IIC_Wait_Ack();

    170.     INA226_IIC_Send_Byte(reg);
    171.     INA226_IIC_Wait_Ack();
    172.    
    173.     temp = (uint8_t)(data>>8);
    174.     INA226_IIC_Send_Byte(temp);
    175.     INA226_IIC_Wait_Ack();

    176.     temp = (uint8_t)(data&0x00FF);
    177.     INA226_IIC_Send_Byte(temp);
    178.     INA226_IIC_Wait_Ack();
    179.    
    180.     INA226_IIC_Stop();
    181. }


    182. void INA226_SetRegPointer(uint8_t addr,uint8_t reg)
    183. {
    184.     INA226_IIC_Start();

    185.     INA226_IIC_Send_Byte(addr);
    186.     INA226_IIC_Wait_Ack();

    187.     INA226_IIC_Send_Byte(reg);
    188.     INA226_IIC_Wait_Ack();

    189.     INA226_IIC_Stop();
    190. }


    191. uint16_t INA226_ReadData(uint8_t addr)
    192. {
    193.     uint16_t temp=0;
    194.     INA226_IIC_Start();

    195.     INA226_IIC_Send_Byte(addr+1);
    196.     INA226_IIC_Wait_Ack();
    197.    
    198.     temp = INA226_IIC_Read_Byte(1);
    199.     temp<<=8;   
    200.     temp |= INA226_IIC_Read_Byte(0);
    201.    
    202.     INA226_IIC_Stop();
    203.     return temp;
    204. }


    205. long INA226_GetShunt_Current(uint8_t addr)
    206. {
    207.     long temp=0;   
    208.     INA226_SetRegPointer(addr,CUR_REG);
    209.     temp = INA226_ReadData(addr);
    210.     if(temp&0x8000)   
    211.     {
    212.         temp = ~(temp - 1);   
    213.             temp = (uint16_t)temp - 2 * (uint16_t)temp;
    214.     }
    215.         return temp;
    216. }

    217. //获取 id
    218. uint16_t  INA226_Get_ID(uint8_t addr)
    219. {
    220.     uint32_t temp=0;
    221.     INA226_SetRegPointer(addr,INA226_GET_ADDR);
    222.     temp = INA226_ReadData(addr);
    223.     return (uint16_t)temp;
    224. }

    225. //获取校准值
    226. uint16_t INA226_GET_CAL_REG(uint8_t addr)
    227. {   
    228.     uint32_t temp=0;
    229.     INA226_SetRegPointer(addr,CAL_REG);
    230.     temp = INA226_ReadData(addr);
    231.     return (uint16_t)temp;
    232. }

    233. //1.25mV/bit
    234. uint32_t INA226_GetVoltage(uint8_t addr)
    235. {
    236.     uint32_t temp=0;
    237.     INA226_SetRegPointer(addr,BV_REG);
    238.     temp = INA226_ReadData(addr);
    239.     return (uint32_t)temp;   
    240. }



    241. //2.5uV/bit,感觉这个值是测不准的,所以下面改成2.2了
    242. uint32_t INA226_GetShuntVoltage(uint8_t addr)
    243. {
    244.     uint32_t temp=0;
    245.     INA226_SetRegPointer(addr,SV_REG);
    246.     temp = INA226_ReadData(addr);
    247.     if(temp&0x8000)    temp = ~(temp - 1);   
    248.     return (uint32_t)temp;   
    249. }


    250. uint16_t INA226_Get_Power(uint8_t addr)
    251. {
    252.     int16_t temp=0;
    253.     INA226_SetRegPointer(addr,PWR_REG);
    254.     temp = INA226_ReadData(addr);
    255.     return (uint16_t)temp;
    256. }


    257. void GetVoltage(float *Voltage)//mV
    258. {
    259.     Voltage[0] = INA226_GetVoltage(INA226_ADDR1)*1.25f;
    260.     printf("ina226 v = %.2f\r\n", Voltage[0]);
    261. }


    262. void Get_Shunt_voltage(float *Voltage)//uV
    263. {
    264.     Voltage[0] = (INA226_GetShuntVoltage(INA226_ADDR1)*2.2);//这里原来乘的系数是2.5
    265.    
    266. }


    267. void Get_Shunt_Current(float *Current)//mA
    268. {
    269.     Current[0] = (INA226_GetShunt_Current(INA226_ADDR1)* 2.5f);
    270. }


    271. void GetPower()//W
    272. {
    273.     GetVoltage(&INA226_data.voltageVal);            //mV
    274.     Get_Shunt_voltage(&INA226_data.Shunt_voltage);    //uV
    275.     Get_Shunt_Current(&INA226_data.Shunt_Current);    //mA
    276.     INA226_data.powerVal=INA226_data.voltageVal*0.001f * INA226_data.Shunt_Current*0.001f;
    277. }
    278. uint16_t read_dat;
    279. float read_vol;
    280. float GetV(void)
    281. {
    282.     //电压采样
    283.     INA226_IIC_Start();
    284.     INA226_IIC_Send_Byte(0x80);
    285.     INA226_IIC_Wait_Ack();
    286.   INA226_IIC_Send_Byte(0x00);
    287.   INA226_IIC_Wait_Ack();
    288.      INA226_IIC_Send_Byte(0x47);
    289.   INA226_IIC_Wait_Ack();
    290.      INA226_IIC_Send_Byte(0x27);
    291.   INA226_IIC_Wait_Ack();
    292.   INA226_IIC_Stop();
    293.     HAL_Delay(1);   
    294.         
    295.   INA226_IIC_Start();
    296.     INA226_IIC_Send_Byte(0x81);
    297.     INA226_IIC_Wait_Ack();
    298.     read_dat = INA226_IIC_Read_Byte(1)<<8;
    299.     //IIC_Wait_Ack();
    300.     read_dat = read_dat + INA226_IIC_Read_Byte(0);
    301.     read_vol = 0.00125*read_dat;   
    302.     INA226_IIC_Stop();
    303.     return read_vol;
    304. }
    复制代码


    INA226.h:
    1. #ifndef _INA226_H
    2. #define _INA226_H


    3. #include "main.h"


    4. #define     CFG_REG             0x00        //
    5. #define     SV_REG             0x01        //分流电压, 此处分流电阻为 0.1欧
    6. #define     BV_REG             0x02        //总线电压
    7. #define     PWR_REG         0x03        //电源功率
    8. #define     CUR_REG         0x04        //电流
    9. #define     CAL_REG         0x05        //校准,设定满量程范围以及电流和功率测数的
    10. //#define     ONFF_REG         0x06        //屏蔽 使能 警报配置和转换准备就绪
    11. //#define     AL_REG             0x07        //包含与所选警报功能相比较的限定值
    12. #define     INA226_GET_ADDR 0XFF        //包含唯一的芯片标识号
    13. #define       INA226_ADDR1    0x80



    14. //IO操作
    15. #define IIC_SCL_H   HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_SET) //SCL H
    16. #define IIC_SCL_L   HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET) //SCL H
    17. #define IIC_SDA_H    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,GPIO_PIN_SET) //SDA_H
    18. #define IIC_SDA_L      HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,GPIO_PIN_RESET) //SDA_L
    19. #define READ_SDA      HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_11)  //输入SDA
    20. #define SDA_READ   GPIOB->IDR& GPIO_IDR_IDR11


    21. typedef struct
    22. {
    23.     float voltageVal;            //mV
    24.     float Shunt_voltage;        //uV
    25.     float Shunt_Current;        //mA
    26.     float powerVal;
    27. }INA226;

    28. static void delay_nns(uint16_t D);
    29. void delay_nms(uint16_t ms);
    30. void delay_nus(uint16_t us);
    31. void INA226_IIC_Init(void);
    32. void INA226_IIC_Start(void);
    33. void INA226_IIC_Stop(void);
    34. void INA226_IIC_Ack(void);
    35. void INA226_IIC_NAck(void);
    36. uint8_t INA226_IIC_Wait_Ack(void);
    37. void INA226_IIC_Send_Byte(uint8_t txd);
    38. uint8_t INA226_IIC_Read_Byte(unsigned char ack);
    39. void INA226_Init(void);
    40. void INA226_SendData(uint8_t addr,uint8_t reg,uint16_t data);
    41. void INA226_SetRegPointer(uint8_t addr,uint8_t reg);
    42. uint16_t INA226_ReadData(uint8_t addr);
    43. long INA226_GetShunt_Current(uint8_t addr);
    44. uint16_t  INA226_Get_ID(uint8_t addr);
    45. uint16_t INA226_GET_CAL_REG(uint8_t addr);
    46. uint32_t INA226_GetVoltage(uint8_t addr);
    47. uint32_t INA226_GetShuntVoltage(uint8_t addr);
    48. uint16_t INA226_Get_Power(uint8_t addr);
    49. void GetVoltage(float *Voltage);
    50. void Get_Shunt_voltage(float *Voltage);
    51. void Get_Shunt_Current(float *Current);
    52. void GetPower();
    53. extern INA226 INA226_data;
    54. float GetV(void);
    55. #endif
    复制代码


    由于这个电路参考电压是负值,所以在计算电压时需要减去这个负值,所以以后用的时候最好是接地。

    参考电路接法:
    1.png

    INA226 高侧低侧测量.pdf

    1.26 MB, 下载次数: 21

    回复

    使用道具 举报

    0

    主题

    1

    帖子

    26

    积分

    新手上路

    Rank: 1

    积分
    26
    发表于 2022-9-1 20:35:50 | 显示全部楼层
    下不了啊
    回复

    使用道具 举报

    676

    主题

    690

    帖子

    6808

    积分

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    6808
     楼主| 发表于 2022-9-1 22:09:14 | 显示全部楼层

    我试了可以呀
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    小黑屋|路丝栈 ( 粤ICP备2021053448号 )

    GMT+8, 2024-12-22 14:53 , Processed in 0.050022 second(s), 21 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表