- //delay
- static void delay_nns(uint16_t D) //30纳秒ns 根据手册要用到IIC的HS高速模式
- {
- uint16_t i;
- uint32_t M = 0;//720W
- for(i = 0;i < D; i++)
- for(M=10;M > 0;M--);
- }
- void delay_nms(uint16_t ms) //毫秒
- {
- uint16_t i;
- uint32_t M = 0;//720W
- for(i = 0;i < ms; i++)
- for(M=120000;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=720;M > 0;M--);
- }
- //IIC
- /****************IIC***************************/
- void INA226_SDA_Set_Output()
- {
- GPIO_InitTypeDef GPIO_InitStructure;
-
- GPIO_InitStructure.Pins = INA_SDA_PIN;
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
- GPIO_Init(INA_SDA_GPIO_PORT, &GPIO_InitStructure);
- }
- void INA226_SDA_Set_Input()
- {
- GPIO_InitTypeDef GPIO_InitStructure;
-
- GPIO_InitStructure.Pins = INA_SDA_PIN;
- GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
- GPIO_Init(INA_SDA_GPIO_PORT, &GPIO_InitStructure);
- }
- void INA226_IIC_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.Pins = INA_SDA_PIN | INA_SCL_PIN;
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
- GPIO_Init(INA_SDA_GPIO_PORT, &GPIO_InitStructure);
-
- GPIO_WritePin(INA_SCL_GPIO_PORT, INA_SCL_PIN, GPIO_Pin_SET);
- GPIO_WritePin(INA_SDA_GPIO_PORT, INA_SDA_PIN, GPIO_Pin_SET);
- delay_nms(5);
- }
-
- void INA226_IIC_Start(void)
- {
- GPIO_WritePin(INA_SCL_GPIO_PORT, INA_SCL_PIN, GPIO_Pin_SET);
- GPIO_WritePin(INA_SDA_GPIO_PORT, INA_SDA_PIN, GPIO_Pin_SET);
- delay_nns(5);
- GPIO_WritePin(INA_SDA_GPIO_PORT, INA_SDA_PIN, GPIO_Pin_RESET);//START:when CLK is high,DATA change form high to low
- delay_nns(5);
- GPIO_WritePin(INA_SCL_GPIO_PORT, INA_SCL_PIN, GPIO_Pin_RESET);//钳住I2C总线,准备发送或接收数据
- delay_nns(5);
- }
- void INA226_IIC_Stop(void)
- {
- GPIO_WritePin(INA_SDA_GPIO_PORT, INA_SDA_PIN, GPIO_Pin_RESET);//STOP:when CLK is high DATA change form low to high
- delay_nns(5);
- GPIO_WritePin(INA_SCL_GPIO_PORT, INA_SCL_PIN, GPIO_Pin_SET);
- delay_nns(5);
- GPIO_WritePin(INA_SDA_GPIO_PORT, INA_SDA_PIN, GPIO_Pin_SET);//发送I2C总线结束信号
- delay_nns(5);
- }
- void INA226_IIC_Ack(void)
- {
- GPIO_WritePin(INA_SDA_GPIO_PORT, INA_SDA_PIN, GPIO_Pin_RESET);
- delay_nns(5);
- GPIO_WritePin(INA_SCL_GPIO_PORT, INA_SCL_PIN, GPIO_Pin_SET);
- delay_nns(5);
- GPIO_WritePin(INA_SCL_GPIO_PORT, INA_SCL_PIN, GPIO_Pin_RESET);;
- delay_nns(5);
- GPIO_WritePin(INA_SDA_GPIO_PORT, INA_SDA_PIN, GPIO_Pin_SET);
- }
- void INA226_IIC_NAck(void)
- {
- GPIO_WritePin(INA_SDA_GPIO_PORT, INA_SDA_PIN, GPIO_Pin_SET);
- delay_nns(5);
- GPIO_WritePin(INA_SCL_GPIO_PORT, INA_SCL_PIN, GPIO_Pin_SET);
- delay_nns(5);
- GPIO_WritePin(INA_SCL_GPIO_PORT, INA_SCL_PIN, GPIO_Pin_RESET);;
- delay_nns(5);
- GPIO_WritePin(INA_SDA_GPIO_PORT, INA_SDA_PIN, GPIO_Pin_RESET);
- }
- uint8_t INA226_IIC_Wait_Ack(void)
- {
- uint8_t ucErrTime=0;
-
- GPIO_WritePin(INA_SDA_GPIO_PORT, INA_SDA_PIN, GPIO_Pin_SET);
- delay_nns(5);
- GPIO_WritePin(INA_SCL_GPIO_PORT, INA_SCL_PIN, GPIO_Pin_SET);
- delay_nns(5);
-
- INA226_SDA_Set_Input();
-
- while(GPIO_ReadPin(INA_SDA_GPIO_PORT, INA_SDA_PIN))
- {
- ucErrTime++;
- if(ucErrTime>250)
- {
- INA226_IIC_Stop();
- return 1;
- }
- }
-
- INA226_SDA_Set_Output();
-
- GPIO_WritePin(INA_SCL_GPIO_PORT, INA_SCL_PIN, GPIO_Pin_RESET);//时钟输出0
- return 0;
- }
- void INA226_IIC_Send_Byte(uint8_t txd)
- {
- GPIO_WritePin(INA_SCL_GPIO_PORT, INA_SCL_PIN, GPIO_Pin_RESET);;//拉低时钟开始数据传输
- for(uint8_t i = 0;i < 8;i++)
- {
- if(txd&0x80)
- GPIO_WritePin(INA_SDA_GPIO_PORT, INA_SDA_PIN, GPIO_Pin_SET);
- else
- GPIO_WritePin(INA_SDA_GPIO_PORT, INA_SDA_PIN, GPIO_Pin_RESET);
- txd<<=1;
-
- GPIO_WritePin(INA_SCL_GPIO_PORT, INA_SCL_PIN, GPIO_Pin_SET);
- delay_nns(5);
- GPIO_WritePin(INA_SCL_GPIO_PORT, INA_SCL_PIN, GPIO_Pin_RESET);
- delay_nns(5);
- }
- }
- uint8_t INA226_IIC_Read_Byte(unsigned char ack)
- {
- uint8_t TData=0,i;
-
- INA226_SDA_Set_Input();
-
- for(i=0;i<8;i++)
- {
- GPIO_WritePin(INA_SCL_GPIO_PORT, INA_SCL_PIN, GPIO_Pin_SET);
- delay_nns(5);
- TData=TData<<1;
- if(GPIO_ReadPin(INA_SDA_GPIO_PORT, INA_SDA_PIN))
- {
- TData|=0x01;
- }
- GPIO_WritePin(INA_SCL_GPIO_PORT, INA_SCL_PIN, GPIO_Pin_RESET);;
- delay_nns(5);
- }
-
- INA226_SDA_Set_Output();
-
- if(!ack)
- INA226_IIC_NAck();
- else
- INA226_IIC_Ack();
-
- return TData;
- }
接下来就是INA226的一些配置,配置采集电流和电压,通过电流和电压算出功率。
- void INA226_Init(void)
- {
- INA226_IIC_Init();
- delay_nms(10);
- INA226_SendData(WRITE_ADDR,0x00,0x4727);//初始化结果采用64次平均值,全功能,连续模式
- INA226_SendData(WRITE_ADDR,0x05,0xE800);//(当单位为mA时:0.002R=0xA00;0.01R=0x200);(上限8A)
-
- INA226_Get_ID(WRITE_ADDR);
- }
- 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;
- }
- uint16_t INA226_GetShuntCurrent(uint8_t addr)
- {
- uint16_t temp=0;
- INA226_SetRegPointer(addr,Current_Reg);
- temp = INA226_ReadData(addr);
- // if(temp&0x8000) temp = ~(temp - 1);//保留符号留给读数函数处理
- return temp;
- }
-
- //获取 id
- uint16_t INA226_Get_ID(uint8_t addr)
- {
- uint16_t temp=0;
- INA226_SetRegPointer(addr,ID_Reg);
- temp = INA226_ReadData(addr);
- return (uint16_t)temp;
- }
-
- //获取校准值
- uint16_t INA226_GET_CAL_REG(uint8_t addr)
- {
- uint16_t temp=0;
- INA226_SetRegPointer(addr,Calib_Reg);
- temp = INA226_ReadData(addr);
- return temp;
- }
-
- //1.25mV/bit
- uint16_t INA226_GetVoltage(uint8_t addr)
- {
- uint16_t temp=0;
- INA226_SetRegPointer(addr,Bus_V_Reg);
- temp = INA226_ReadData(addr);
- return temp;
- }
-
-
-
- //2.5uV/bit
- uint16_t INA226_GetShuntVoltage(uint8_t addr)
- {
- uint16_t temp=0;
- INA226_SetRegPointer(addr,Shunt_V_Reg);
- temp = INA226_ReadData(addr);
- if(temp&0x8000) temp = ~(temp - 1);
- return temp;
- }
-
- //2.5mW/bit
- uint16_t INA226_Get_Power(uint8_t addr)
- {
- uint16_t temp=0;
- INA226_SetRegPointer(addr,Power_Reg);
- temp = INA226_ReadData(addr);
- return temp;
- }
配置对于的参数,设置电流电压的系数,然后将数据通过串口发送给上位机
其中控制板载LED亮灭,这样可以采集出不同的功率。
- while(1)
- {
- voltage_value = INA226_GetVoltage(WRITE_ADDR)*1.25f*0.001f;
- current_value = INA226_GetShuntCurrent(WRITE_ADDR)*0.002f;
- power_value = voltage_value * current_value;
- power_total_value += power_value / 3600;
-
- sprintf(uart_send, "Current:%.2fmA, Volatage:%.2fV, Power:%.2fmW, PowerTotal:%.3fmW/h\r\n", current_value, voltage_value, current_value * voltage_value, power_total_value);
- USART_SendBuf_Polling(DEBUG_USARTx, (uint8_t *)uart_send, strlen(uart_send));
- FirmwareDelay(1000000);
- GPIO_TogglePin(CW_GPIOA, GPIO_PIN_7);
- GPIO_TogglePin(CW_GPIOA, GPIO_PIN_6);
- }
4、上机演示
将开发板串口接入PC,打开串口调试助手,可以看到能一直收到开发板的电源状态信息。
视频演示: