|
路线栈欢迎您!
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
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\r\n", 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;
- }
复制代码
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
复制代码
由于这个电路参考电压是负值,所以在计算电压时需要减去这个负值,所以以后用的时候最好是接地。
参考电路接法:
|
|