模块:
平台:STM32F103C8T6
标准库
软件模拟IIC
C文件:
#include "ina226.h"
//delay
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
/****************IIC***************************/
void INA226_IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(INA_SCL_RCC|INA_SDA_RCC, ENABLE); /* 打开GPIO时钟 */
GPIO_InitStructure.GPIO_Pin=INA_SCL_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(INA_SCL_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=INA_SDA_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(INA_SDA_GPIO_PORT, &GPIO_InitStructure);
INA_SCL=1;
INA_SDA=1;
delay_nms(5);
}
void INA226_IIC_Start(void)
{
INA_SCL=1;
INA_SDA=1;
delay_nns(5);
INA_SDA=0;//START:when CLK is high,DATA change form high to low
delay_nns(5);
INA_SCL=0;;//钳住I2C总线,准备发送或接收数据
delay_nns(5);
}
void INA226_IIC_Stop(void)
{
INA_SDA=0;//STOP:when CLK is high DATA change form low to high
delay_nns(5);
INA_SCL=1;
delay_nns(5);
INA_SDA=1;//发送I2C总线结束信号
delay_nns(5);
}
void INA226_IIC_Ack(void)
{
INA_SDA=0;
delay_nns(5);
INA_SCL=1;
delay_nns(5);
INA_SCL=0;;
delay_nns(5);
INA_SDA=1;
}
void INA226_IIC_NAck(void)
{
INA_SDA=1;
delay_nns(5);
INA_SCL=1;
delay_nns(5);
INA_SCL=0;;
delay_nns(5);
INA_SDA=0;
}
uint8_t INA226_IIC_Wait_Ack(void)
{
uint8_t ucErrTime=0;
INA_SDA=1;
delay_nns(5);
INA_SCL=1;
delay_nns(5);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
INA226_IIC_Stop();
return 1;
}
}
INA_SCL=0;//时钟输出0
return 0;
}
void INA226_IIC_Send_Byte(uint8_t txd)
{ int i;
INA_SCL=0;;//拉低时钟开始数据传输
for( i = 0;i < 8;i++)
{
if(txd&0x80)
INA_SDA=1;
else
INA_SDA=0;
txd<<=1;
INA_SCL=1;
delay_nns(5);
INA_SCL=0;
delay_nns(5);
}
}
uint8_t INA226_IIC_Read_Byte(unsigned char ack)
{
uint8_t TData=0,i;
for(i=0;i<8;i++)
{
INA_SCL=1;
delay_nns(5);
TData=TData<<1;
if(READ_SDA)
{
TData|=0x01;
}
INA_SCL=0;;
delay_nns(5);
}
if(!ack)
INA226_IIC_NAck();
else
INA226_IIC_Ack();
return TData;
}
/**********************IIC_END*************************/
void INA226_Init(void)
{
INA226_IIC_Init();
delay_nms(10);
INA226_SendData(WRITE_ADDR,0x00,0x4727);//初始化结果采用64次平均值,全功能,连续模式
INA226_SendData(WRITE_ADDR,0x05,0x200);//(当单位为mA时:0.002R=0xA00;0.01R=0x200);(上限8A)
}
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;
}
H文件
#ifndef INA226_H
#define INA226_H
#include "sys.h"
#define INA_SCL PBout(8) //SCL引脚
#define INA_SDA PBout(9) //SDA引脚
#define INA_SCL_GPIO_PORT GPIOB /* GPIO端口 */
#define INA_SCL_RCC RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
#define INA_SCL_PIN GPIO_Pin_8 /* 连接到SCL时钟线的GPIO */
#define INA_SDA_GPIO_PORT GPIOB /* GPIO端口 */
#define INA_SDA_RCC RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
#define INA_SDA_PIN GPIO_Pin_9 /* 连接到SDA数据线的GPIO */
#define READ_SDA GPIO_ReadInputDataBit(INA_SDA_GPIO_PORT,INA_SDA_PIN)
#define READ_ADDR 0x81 //A0=GND,A1=GND // R=1, W=0
#define WRITE_ADDR 0x80 //芯片IIC地址
#define Config_Reg 0x00 //模式配置寄存器
#define Shunt_V_Reg 0x01 //采样电阻压差;取值:2.5uV~81.92mV(0~7FFF)(10mΩ采样电阻下最大电流8A)
#define Bus_V_Reg 0x02 //BUS总线电压:1.25mV~40.96V(0~7FFF)
#define Power_Reg 0x03 //功率;Current_LSB * 25,FSR = 0xFFFF
#define Current_Reg 0x04 //电流;LSB = 0.02mA,FSR = 0x7FFF
#define Calib_Reg 0x05 //(当单位为mA时:采样电阻0.002R=0xA00;0.01R=0x200);写入Calibration Register的数据需要根据实际电路中的采样电阻阻值以及电流分辨率来设置
#define Mask_En_Reg 0x06 //
#define Alert_Reg 0x07 //
#define Man_ID_Reg 0xFE //0x5449
#define ID_Reg 0xFF //0x2260
void INA226_Init(void);
void INA226_SendData(uint8_t addr,uint8_t reg,uint16_t data);
uint16_t INA226_Get_ID(uint8_t addr);
uint16_t INA226_GetShuntVoltage(uint8_t addr);
uint16_t INA226_GetShuntCurrent(uint8_t addr);
uint16_t INA226_GetVoltage(uint8_t addr);
uint16_t INA226_Get_Power(uint8_t addr);
#endif