- //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,打开串口调试助手,可以看到能一直收到开发板的电源状态信息。
视频演示: