zoukankan      html  css  js  c++  java
  • INA226使用教程(IIC)

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

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

    INA226.c:

    #include "INA226.h"
    
    
    INA226 INA226_data;
    
    static void delay_nns(uint16_t D)  //30纳秒ns  根据手册要用到IIC的HS高速模式
    {
        while(--D);
    }
    
    void delay_nms(uint16_t ms)  //毫秒
    {
        uint16_t i;
        uint32_t M = 0;//720W
        for(i = 0;i < ms; i++)
        for(M=12000;M > 0;M--);
    }
    
    void delay_nus(uint16_t us)//微秒
    {
        uint16_t i;
        uint16_t M = 0;//720W
        for(i = 0;i < us; i++)
        for(M=72;M > 0;M--);
    }
    
    /****************IIC***************************/
    void INA226_IIC_Init(void)
    {
        GPIO_InitTypeDef GPIO_Initure;
        __HAL_RCC_GPIOB_CLK_ENABLE();   //使能GPIOB时钟
        
         //PC11,12初始化设置
        GPIO_Initure.Pin=GPIO_PIN_10|GPIO_PIN_11;//PB10SCL PB11SDA
        GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽输出
        GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
        GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;     //高速
        HAL_GPIO_Init(GPIOB,&GPIO_Initure);
        
        IIC_SDA_H;
        IIC_SCL_H;  
            delay_nms(5);
    }
        
    void INA226_IIC_Start(void)
    {
        IIC_SDA_H;            
        IIC_SCL_H;
        delay_nns(5);
         IIC_SDA_L;//START:when CLK is high,DATA change form high to low 
        delay_nns(5);
        IIC_SCL_L;//钳住I2C总线,准备发送或接收数据 
        delay_nns(5);
    }    
    
    void INA226_IIC_Stop(void)
    {
        IIC_SDA_L;//STOP:when CLK is high DATA change form low to high
         delay_nns(5);
        IIC_SCL_H; 
            delay_nns(5);
        IIC_SDA_H;//发送I2C总线结束信号
        delay_nns(5);                                   
    }
    
    void INA226_IIC_Ack(void)
    {
        IIC_SDA_L;
        delay_nns(5);
        IIC_SCL_H;
        delay_nns(5);
        IIC_SCL_L;
            delay_nns(5);
        IIC_SDA_H;
    }
    
    void INA226_IIC_NAck(void)
    {
        IIC_SDA_H;
        delay_nns(5);
        IIC_SCL_H;
    delay_nns(5);
        IIC_SCL_L;
        delay_nns(5);
        IIC_SDA_L;
    }        
    
    uint8_t INA226_IIC_Wait_Ack(void)
    {
        uint8_t ucErrTime=0;
        //SDA_IN();      //SDA设置为输入  
        IIC_SDA_H;
        delay_nns(5);       
        IIC_SCL_H;
        delay_nns(5);          
        
        while(READ_SDA)
        {
            ucErrTime++;
            if(ucErrTime>250)
            {
                INA226_IIC_Stop();
                return 1;
            }
        }
        IIC_SCL_L;//时钟输出0        
        return 0;  
    }
    
    void INA226_IIC_Send_Byte(uint8_t txd)
    {                              
       IIC_SCL_L;//拉低时钟开始数据传输
       for(uint8_t i = 0;i < 8;i++)
        {              
            if(txd&0x80)
                        IIC_SDA_H;
                    else
                        IIC_SDA_L;                
            txd<<=1;       
                    
            IIC_SCL_H;
            delay_nns(5);
            IIC_SCL_L;
            delay_nns(5);
        }            
        //    IIC_SDA_H;
        //    IIC_SCL_H;            //当去掉wait_ack时的时候添加
        //    delay_nns(5);
            //IIC_SCL_L;
    } 
    
    uint8_t INA226_IIC_Read_Byte(unsigned char ack)
    {
          uint8_t TData=0,i;
        for(i=0;i<8;i++)
        {
            IIC_SCL_H;
            delay_nns(5);
            TData=TData<<1;
            //if(GPIOB->IDR& GPIO_IDR_IDR7)        //判断SDA是否为高
                if(SDA_READ)
            {
                TData|=0x01;
            }
            IIC_SCL_L;
            delay_nns(5);
        }
            if(!ack)
                INA226_IIC_NAck();
            else
                INA226_IIC_Ack();
    //    IIC_SCL_L;
    //    delay_nns(5);
    //    IIC_SDA_L;
    //    delay_nns(5);                //ACK
    //    IIC_SCL_H;
    //    delay_nns(5);
    //    IIC_SCL_L;
    //    delay_nns(5);
    //    IIC_SDA_H;
        return TData;
    }
    
    /**********************IIC_END*************************/
    
    void INA226_Init(void)
    {
        INA226_IIC_Init();
        HAL_Delay(10);
        //    INA226_SendData(INA226_ADDR1,CFG_REG,0xC000);
    
    //    HAL_Delay(10);
        //uint16_t cfg_reg_value = 0x4000|(3<<9)|(4<<6)|(4<<3)|7;
    //    INA226_SendData(INA226_ADDR1,CFG_REG,0x484f);
    //    INA226_SendData(INA226_ADDR1,CAL_REG,0x0012);
        INA226_SendData(INA226_ADDR1,0x00,0x4727);
        INA226_SendData(INA226_ADDR1,0x05,0x800);//A00
    }
    
    void INA226_SendData(uint8_t addr,uint8_t reg,uint16_t data)
    {
        uint8_t temp = 0;
        INA226_IIC_Start();
        INA226_IIC_Send_Byte(addr);
        INA226_IIC_Wait_Ack();
     
        INA226_IIC_Send_Byte(reg);
        INA226_IIC_Wait_Ack();
        
        temp = (uint8_t)(data>>8);
        INA226_IIC_Send_Byte(temp);
        INA226_IIC_Wait_Ack();
     
        temp = (uint8_t)(data&0x00FF);
        INA226_IIC_Send_Byte(temp);
        INA226_IIC_Wait_Ack();
        
        INA226_IIC_Stop();
    }
    
    
    void INA226_SetRegPointer(uint8_t addr,uint8_t reg)
    {
        INA226_IIC_Start();
     
        INA226_IIC_Send_Byte(addr);
        INA226_IIC_Wait_Ack();
     
        INA226_IIC_Send_Byte(reg);
        INA226_IIC_Wait_Ack();
     
        INA226_IIC_Stop();
    }
    
    
    uint16_t INA226_ReadData(uint8_t addr)
    {
        uint16_t temp=0;
        INA226_IIC_Start();
     
        INA226_IIC_Send_Byte(addr+1);
        INA226_IIC_Wait_Ack();
        
        temp = INA226_IIC_Read_Byte(1);
        temp<<=8;    
        temp |= INA226_IIC_Read_Byte(0);
        
        INA226_IIC_Stop();
        return temp;
    }
    
    
    long INA226_GetShunt_Current(uint8_t addr)
    {
        long temp=0;    
        INA226_SetRegPointer(addr,CUR_REG);
        temp = INA226_ReadData(addr);
        if(temp&0x8000)    
        {
            temp = ~(temp - 1);    
                temp = (uint16_t)temp - 2 * (uint16_t)temp;
        }
            return temp;
    }
     
    //获取 id
    uint16_t  INA226_Get_ID(uint8_t addr)
    {
        uint32_t temp=0;
        INA226_SetRegPointer(addr,INA226_GET_ADDR);
        temp = INA226_ReadData(addr);
        return (uint16_t)temp;
    }
     
    //获取校准值
    uint16_t INA226_GET_CAL_REG(uint8_t addr)
    {    
        uint32_t temp=0;
        INA226_SetRegPointer(addr,CAL_REG);
        temp = INA226_ReadData(addr);
        return (uint16_t)temp;
    }
     
    //1.25mV/bit
    uint32_t INA226_GetVoltage(uint8_t addr)
    {
        uint32_t temp=0;
        INA226_SetRegPointer(addr,BV_REG);
        temp = INA226_ReadData(addr);
        return (uint32_t)temp;    
    }
     
     
     
    //2.5uV/bit,感觉这个值是测不准的,所以下面改成2.2了
    uint32_t INA226_GetShuntVoltage(uint8_t addr)
    {
        uint32_t temp=0;
        INA226_SetRegPointer(addr,SV_REG);
        temp = INA226_ReadData(addr);
        if(temp&0x8000)    temp = ~(temp - 1);    
        return (uint32_t)temp;    
    }
     
     
    uint16_t INA226_Get_Power(uint8_t addr)
    {
        int16_t temp=0;
        INA226_SetRegPointer(addr,PWR_REG);
        temp = INA226_ReadData(addr);
        return (uint16_t)temp;
    }
     
     
    void GetVoltage(float *Voltage)//mV
    {
        Voltage[0] = INA226_GetVoltage(INA226_ADDR1)*1.25f;
        printf("ina226 v = %.2f
    ", Voltage[0]);
    }
     
     
    void Get_Shunt_voltage(float *Voltage)//uV
    {
        Voltage[0] = (INA226_GetShuntVoltage(INA226_ADDR1)*2.2);//这里原来乘的系数是2.5
        
    }
     
     
    void Get_Shunt_Current(float *Current)//mA
    {
        Current[0] = (INA226_GetShunt_Current(INA226_ADDR1)* 2.5f);
    }
     
     
    void GetPower()//W
    {
        GetVoltage(&INA226_data.voltageVal);            //mV
        Get_Shunt_voltage(&INA226_data.Shunt_voltage);    //uV
        Get_Shunt_Current(&INA226_data.Shunt_Current);    //mA
        INA226_data.powerVal=INA226_data.voltageVal*0.001f * INA226_data.Shunt_Current*0.001f;
    }
    uint16_t read_dat;
    float read_vol;
    float GetV(void)
    {
        //电压采样
        INA226_IIC_Start();
        INA226_IIC_Send_Byte(0x80);
        INA226_IIC_Wait_Ack();
      INA226_IIC_Send_Byte(0x00);
      INA226_IIC_Wait_Ack();
         INA226_IIC_Send_Byte(0x47);
      INA226_IIC_Wait_Ack();
         INA226_IIC_Send_Byte(0x27);
      INA226_IIC_Wait_Ack();
      INA226_IIC_Stop();
        HAL_Delay(1);    
            
      INA226_IIC_Start();
        INA226_IIC_Send_Byte(0x81);
        INA226_IIC_Wait_Ack();
        read_dat = INA226_IIC_Read_Byte(1)<<8;
        //IIC_Wait_Ack();
        read_dat = read_dat + INA226_IIC_Read_Byte(0);
        read_vol = 0.00125*read_dat;    
        INA226_IIC_Stop();
        return read_vol;
    }
    View Code

    INA226.h:

    #ifndef _INA226_H
    #define _INA226_H
    
    
    #include "main.h"
    
    
    #define     CFG_REG             0x00        //
    #define     SV_REG             0x01        //分流电压, 此处分流电阻为 0.1欧
    #define     BV_REG             0x02        //总线电压
    #define     PWR_REG         0x03        //电源功率
    #define     CUR_REG         0x04        //电流
    #define     CAL_REG         0x05        //校准,设定满量程范围以及电流和功率测数的 
    //#define     ONFF_REG         0x06        //屏蔽 使能 警报配置和转换准备就绪
    //#define     AL_REG             0x07        //包含与所选警报功能相比较的限定值
    #define     INA226_GET_ADDR 0XFF        //包含唯一的芯片标识号
    #define       INA226_ADDR1    0x80
    
    
    
    //IO操作
    #define IIC_SCL_H   HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_SET) //SCL H
    #define IIC_SCL_L   HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET) //SCL H
    #define IIC_SDA_H    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,GPIO_PIN_SET) //SDA_H
    #define IIC_SDA_L      HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,GPIO_PIN_RESET) //SDA_L
    #define READ_SDA      HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_11)  //输入SDA
    #define SDA_READ   GPIOB->IDR& GPIO_IDR_IDR11
    
    
    typedef struct
    {
        float voltageVal;            //mV
        float Shunt_voltage;        //uV
        float Shunt_Current;        //mA
        float powerVal;
    }INA226;
    
    static void delay_nns(uint16_t D);
    void delay_nms(uint16_t ms);
    void delay_nus(uint16_t us);
    void INA226_IIC_Init(void);
    void INA226_IIC_Start(void);
    void INA226_IIC_Stop(void);
    void INA226_IIC_Ack(void);
    void INA226_IIC_NAck(void);
    uint8_t INA226_IIC_Wait_Ack(void);
    void INA226_IIC_Send_Byte(uint8_t txd);
    uint8_t INA226_IIC_Read_Byte(unsigned char ack);
    void INA226_Init(void);
    void INA226_SendData(uint8_t addr,uint8_t reg,uint16_t data);
    void INA226_SetRegPointer(uint8_t addr,uint8_t reg);
    uint16_t INA226_ReadData(uint8_t addr);
    long INA226_GetShunt_Current(uint8_t addr);
    uint16_t  INA226_Get_ID(uint8_t addr);
    uint16_t INA226_GET_CAL_REG(uint8_t addr);
    uint32_t INA226_GetVoltage(uint8_t addr);
    uint32_t INA226_GetShuntVoltage(uint8_t addr);
    uint16_t INA226_Get_Power(uint8_t addr);
    void GetVoltage(float *Voltage);
    void Get_Shunt_voltage(float *Voltage);
    void Get_Shunt_Current(float *Current);
    void GetPower();
    extern INA226 INA226_data;
    float GetV(void);
    #endif
    View Code

    IIC协议参考之前那份。

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

    参考电路接法:

  • 相关阅读:
    2015上海网络赛 A Puzzled Elena
    容斥原理——uva 10325 The Lottery
    2015北京网络赛B题 Mission Impossible 6
    2015北京网络赛A题The Cats' Feeding Spots
    POJ3087——map——Shuffle'm Up
    POJ3126——BFS——Prime Path
    POJ1426——BFS——Find The Multiple
    算法总结——Prim
    算法总结——Dijkstra
    算法总结——Floyed
  • 原文地址:https://www.cnblogs.com/zjx123/p/12874803.html
Copyright © 2011-2022 走看看