IIC协议_符号标志

欢迎转载和指导,然后再吐槽!!!

 

重要的符号标志

——————————————

S          1位) :开始位

P           (1 )  :停止位

Rd/Wr       (1 )  :读写位,读,它就等于1,写,它就等于0

A,NA         1位) :应答和非应答位

Addr       7位) I2C 7位地址。注意此地址也可以扩展到10位地址。

Comm        8位) :命令字节,就是一个数据用来选择设备上面的一个寄存器

Data           8位) :普通数据字节。如果是16位数据,我也会写高数据位和低数据位

Count         8位) :  包含块操作长度的数据字节

[. .]                :   I2C设备的数据发送,与之对应的,主控制器数据的发送

 

 

 

简单发送事务

————————————————

这个相当于i2c_master_send

 

S  Addr  Wr  [A]  Data  [A]  Data  [A]  ...  [A]  Data  [A]  P

 

简单接收事务

————————————————

这个就相当于i2c_master_recv

 

       S  Addr  Rd  [A]  [Data]  A  [Data]  A  ...  A [ Data]  NA  P

 

组合事务传输

————————————————

这个就相当于i2c_transfer

 

他们就像上面说的事务那样,但是不是一个停止位P,而是接着一个开始位S发送,然后事务继续进行。一个字节写后面跟着一个字节读得例子:

      

      S  Addr  Rd  [A]  [Data]  NA  S  Addr  Wr  [A]  Data  [A]  P

 

改进的事务传输

————————————————

我们发现一些I2C 设备需要进入如下的修改。

 

       标志 I2C_M_NOSTART

              在一个组合传输中,在某些点上,‘S Addr Wr/Rd [A]’不会产生。例如,在第二部分消息设置I2C_M_NOSTART,产生如下所示的东西:

              S  Addr  Rd  [A]  [Data]  NA  Data  [A]  P

        如果你在第一个部分消息中设置了I2C_M_NOSTART变量,我们不会产生地址,但是会产生开始位S。这个可能会是你适配器上面的client设备产生混乱,所以不要试。

 

       标志 I2C_M_REV_DIR_ADDR

       这个用来切换Rd/Wr标志,也就是说,当你想写的时候,你需要发送Rd而不是Wr,反之亦然。例如:

       S  Addr  Rd  [A]  Data [A]  Data  [A]  ...  [A]  Data  [A]  P

 

标志 I2C_M_IGNORE_NAK

如果从client设备传回的是一个[NA]的话,那么正常的消息就会被马上打断。设置这个的话,就把所有[NA]当做[A]来处理,那么所有的消息继续发送。

 

标志I2C_M_NO_RD_ACK

在读消息中,master控制器的A/NA会被跳过。

/************************************************************************************************************************************************************* Copyright (C), 2023-2024, First-micro Tech. Co., Ltd. File name: ina3221.c Author: Edgar Version: V1.0 Date: 20230902 Description: Static Function List: 1. Extern Function List: 1. History: 1. Date: 20230902 Author: Edgar Modification: 创建此文件 2. ... *************************************************************************************************************************************************************/ #include "ina3221.h" #include "iic.h" /************************************************************************************************************************************************************* 外部变量声明区 *************************************************************************************************************************************************************/ /************************************************************************************************************************************************************* 全局变量声明区 *************************************************************************************************************************************************************/ u8 Ina3221Setp = 0; //电流采样状态机步骤标志位 stcINA3221 INA3221[4][4] = {0}; void Ina3221_Delay( void ) { Delay_us(2); } void Ina3221_Iic1_Init(void) { stc_gpio_init_t stcGpioInit; (void)GPIO_StructInit(&stcGpioInit); stcGpioInit.u16PinDir = PIN_DIR_OUT; stcGpioInit.u16PullUp = PIN_PU_OFF; stcGpioInit.u16PinDrv = PIN_HIGH_DRV; stcGpioInit.u16PinOutputType = PIN_OUT_TYPE_CMOS; (void)GPIO_Init (INA3221_IIC1_SCL_PORT, INA3221_IIC1_SCL_PIN, &stcGpioInit); (void)GPIO_Init (INA3221_IIC1_SDA_PORT, INA3221_IIC1_SDA_PIN, &stcGpioInit); GPIO_SetFunc (INA3221_IIC1_SCL_PORT, INA3221_IIC1_SCL_PIN, INA3221_IIC1_SCL_FUNC); GPIO_SetFunc (INA3221_IIC1_SDA_PORT, INA3221_IIC1_SDA_PIN, INA3221_IIC1_SDA_FUNC); GPIO_SetPins (INA3221_IIC1_SCL_PORT, INA3221_IIC1_SCL_PIN); GPIO_SetPins (INA3221_IIC1_SDA_PORT, INA3221_IIC1_SDA_PIN); } void Ina3221_Iic1_SclOutCfg(void) { stc_gpio_init_t stcGpioInit; (void)GPIO_StructInit(&stcGpioInit); stcGpioInit.u16PinDir = PIN_DIR_OUT; stcGpioInit.u16PullUp = PIN_PU_OFF; stcGpioInit.u16PinDrv = PIN_HIGH_DRV; stcGpioInit.u16PinOutputType = PIN_OUT_TYPE_CMOS; (void)GPIO_Init(INA3221_IIC1_SCL_PORT, INA3221_IIC1_SCL_PIN, &stcGpioInit); } void Ina3221_Iic1_SdaOutCfg(void) { stc_gpio_init_t stcGpioInit; (void)GPIO_StructInit(&stcGpioInit); stcGpioInit.u16PinDir = PIN_DIR_OUT; stcGpioInit.u16PullUp = PIN_PU_OFF; stcGpioInit.u16PinDrv = PIN_HIGH_DRV; stcGpioInit.u16PinOutputType = PIN_OUT_TYPE_CMOS; (void)GPIO_Init(INA3221_IIC1_SDA_PORT, INA3221_IIC1_SDA_PIN, &stcGpioInit); } void Ina3221_Iic1_SdaInCfg(void) { stc_gpio_init_t stcGpioInit; (void)GPIO_StructInit(&stcGpioInit); stcGpioInit.u16PinDir = PIN_DIR_IN; (void)GPIO_Init(INA3221_IIC1_SDA_PORT, INA3221_IIC1_SDA_PIN, &stcGpioInit); } void Ina3221_Iic1_SdaWR(u8 Level) { (Level) ? GPIO_SetPins(INA3221_IIC1_SDA_PORT,INA3221_IIC1_SDA_PIN) : GPIO_ResetPins(INA3221_IIC1_SDA_PORT,INA3221_IIC1_SDA_PIN); } void Ina3221_Iic1_SclWR(u8 Level) { (Level) ? GPIO_SetPins(INA3221_IIC1_SDA_PORT,INA3221_IIC1_SDA_PIN) : GPIO_ResetPins(INA3221_IIC1_SDA_PORT,INA3221_IIC1_SDA_PIN); } u8 Ina3221_Iic1_SclRD(void) { return GPIO_ReadInputPins(INA3221_IIC1_SDA_PORT,INA3221_IIC1_SDA_PIN); } //注册函数 IIC_TypeDef IIC1_INA3221 = { .index = 0, .I2C_addr = 0, .Delay = Ina3221_Delay, .Init_Cfg = Ina3221_Iic1_Init, .SCL_Out_Cfg = Ina3221_Iic1_SclOutCfg, .SDA_Out_Cfg = Ina3221_Iic1_SdaOutCfg, .SDA_In_Cfg = Ina3221_Iic1_SdaInCfg, .SCL_WR = Ina3221_Iic1_SclWR, .SDA_WR = Ina3221_Iic1_SdaWR, .SDA_RD = Ina3221_Iic1_SclRD }; IIC_TypeDef IIC2_INA3221 = { .index = 1, .I2C_addr = 0, .Delay = Ina3221_Delay, .Init_Cfg = Ina3221_Iic1_Init, .SCL_Out_Cfg = Ina3221_Iic1_SclOutCfg, .SDA_Out_Cfg = Ina3221_Iic1_SdaOutCfg, .SDA_In_Cfg = Ina3221_Iic1_SdaInCfg, .SCL_WR = Ina3221_Iic1_SclWR, .SDA_WR = Ina3221_Iic1_SdaWR, .SDA_RD = Ina3221_Iic1_SclRD }; IIC_TypeDef IIC3_INA3221 = { .index = 2, .I2C_addr = 0, .Delay = Ina3221_Delay, .Init_Cfg = Ina3221_Iic1_Init, .SCL_Out_Cfg = Ina3221_Iic1_SclOutCfg, .SDA_Out_Cfg = Ina3221_Iic1_SdaOutCfg, .SDA_In_Cfg = Ina3221_Iic1_SdaInCfg, .SCL_WR = Ina3221_Iic1_SclWR, .SDA_WR = Ina3221_Iic1_SdaWR, .SDA_RD = Ina3221_Iic1_SclRD }; IIC_TypeDef IIC4_INA3221 = { .index = 3, .I2C_addr = 0, .Delay = Ina3221_Delay, .Init_Cfg = Ina3221_Iic1_Init, .SCL_Out_Cfg = Ina3221_Iic1_SclOutCfg, .SDA_Out_Cfg = Ina3221_Iic1_SdaOutCfg, .SDA_In_Cfg = Ina3221_Iic1_SdaInCfg, .SCL_WR = Ina3221_Iic1_SclWR, .SDA_WR = Ina3221_Iic1_SdaWR, .SDA_RD = Ina3221_Iic1_SclRD }; u8 Ina3221SendData(IIC_TypeDef I2C ,u8 reg,u8 *data,u8 Size) { I2cStart(I2C); I2cSendByte(I2C, I2C.I2C_addr); I2cWaitAck(I2C); I2cSendByte(I2C, reg); I2cWaitAck(I2C); for(uint8_t i = 0; i<Size; i++) { I2cSendByte(I2C, *(data+i)); I2cWaitAck(I2C); } I2cStop(I2C); return 0; } void Ina3221ReadData(IIC_TypeDef I2C ,u8 reg,u8 *data,u8 Size) { //设置3221的读取寄存器 I2cStart(I2C); I2cSendByte(I2C, I2C.I2C_addr); I2cWaitAck(I2C); I2cSendByte(I2C, reg); I2cWaitAck(I2C); I2cStop(I2C); I2cStart(I2C); //读操作需要在地址值发送完后的一个位置1,写操作需要在地址值发送完后的一个位置0 I2cSendByte(I2C, I2C.I2C_addr+1); I2cWaitAck(I2C); uint8_t i; for(i = 0; i<Size; i++) { *(data + i) = I2cReadByte(I2C, 1); } I2cStop(I2C); } u16 Ina3221GetReg(IIC_TypeDef I2C ,stcINA3221 INA3221,u8 Reg) { u16 temp=0; I2C.I2C_addr = INA3221.DevAddr; Ina3221ReadData(I2C,Reg,(u8 *)&temp,2); return temp; } void Ina3221WriteReg(IIC_TypeDef I2C ,stcINA3221 INA3221,u8 Reg,u16 Data) { I2C.I2C_addr = INA3221.DevAddr; Ina3221SendData(I2C ,Reg,(u8 *)&Data,2); } u16 Ina3221GetId(IIC_TypeDef I2C ,stcINA3221 INA3221) { u16 temp=0; I2C.I2C_addr = INA3221.DevAddr; Ina3221ReadData(I2C,INA3221_DIE_ID,(u8 *)&temp,2); return temp; } void Ina3221Reset(IIC_TypeDef I2C ,stcINA3221 INA3221) { u16 temp=0x8000; I2C.I2C_addr = INA3221.DevAddr; Ina3221SendData(I2C ,CFG_REG,(u8 *)&temp,2); } void Ina3221_Init(IIC_TypeDef I2C) { u16 Ina3221_Id[4] = {0}; //初始化IO I2C.Init_Cfg(); INA3221[I2C.index][0].DevAddr = INA3221_ADDR_40; INA3221[I2C.index][1].DevAddr = INA3221_ADDR_41; INA3221[I2C.index][2].DevAddr = INA3221_ADDR_42; INA3221[I2C.index][3].DevAddr = INA3221_ADDR_43; for(u8 i=0;i<4;i++) { Ina3221Reset(I2C ,INA3221[I2C.index][i]); } //读取ID信息测试IIC读写是否正常 printf("\r\n IIC%d读取的ID信息:",I2C.index); for(u8 i=0;i<4;i++) { Ina3221_Id[i] = Ina3221GetId(I2C ,INA3221[I2C.index][i]); printf("DevAddr:0x%02X Id:0x%04X",INA3221[I2C.index][i].DevAddr,Ina3221_Id[i]); } //软件复位 for(u8 i=0;i<4;i++) { INA3221[I2C.index][i].U_CFGREG.INA3221CfgReg = 0x00; INA3221[I2C.index][i].U_CFGREG.Member.RST = 1; I2C.I2C_addr = INA3221[I2C.index][i].DevAddr; Ina3221WriteReg(I2C ,INA3221[I2C.index][i],CFG_REG,INA3221[I2C.index][i].U_CFGREG.INA3221CfgReg); } Delay_ms(10); //初始化设置 for(u8 i=0;i<4;i++) { INA3221[I2C.index][i].U_CFGREG.INA3221CfgReg = 0x00; /* Channel enable mode.这些位允许每个独立通道使能或失能 0 = Channel disable1 = Channel enable (default) */ INA3221[I2C.index][0].U_CFGREG.Member.CH1_EN = 1; INA3221[I2C.index][0].U_CFGREG.Member.CH2_EN = 1; INA3221[I2C.index][0].U_CFGREG.Member.CH3_EN = 1; /* AVG[2:0] 设定采集的样本数量并一起取平均值。 000b=1 001b=4 010b=16 011b=64 100b=128 101b=256 110b=512 111b=1024 */ INA3221[I2C.index][0].U_CFGREG.Member.AVG2 = 0; INA3221[I2C.index][0].U_CFGREG.Member.AVG1 = 1; INA3221[I2C.index][0].U_CFGREG.Member.AVG0 = 0; /* VbusCT 为总线电压测量设定转换时间。 000b=140us 001b=204us 010b=332us 011b=588us 100b=1.1ms 101b=2.116ms 110b=4.156ms 111b=8.244ms */ INA3221[I2C.index][0].U_CFGREG.Member.VBUS_CT2 = 0; INA3221[I2C.index][0].U_CFGREG.Member.VBUS_CT1 = 1; INA3221[I2C.index][0].U_CFGREG.Member.VBUS_CT0 = 1; /* cfg_VshCT 为总线电压测量设定转换时间。 000b=140us 001b=204us 010b=332us 011b=588us 100b=1.1ms 101b=2.116ms 110b=4.156ms 111b=8.244ms */ INA3221[I2C.index][0].U_CFGREG.Member.VSH_CT2 = 0; INA3221[I2C.index][0].U_CFGREG.Member.VSH_CT1 = 1; INA3221[I2C.index][0].U_CFGREG.Member.VSH_CT0 = 1; /* cfg_Mode value 选择连续的、 触发的、 或者省电运行模式。 0=省电 1=分流电压、触发模式 2=总线电压、触发模式 3=分流和总线电压、触发模式 4=省电 5=分流电压、持续模式 6=总线电压、持续模式 7=分流和总线电压、持续模式 */ INA3221[I2C.index][0].U_CFGREG.Member.MODE3 = 1; INA3221[I2C.index][0].U_CFGREG.Member.MODE2 = 1; INA3221[I2C.index][0].U_CFGREG.Member.MODE1 = 1; Ina3221WriteReg(I2C ,INA3221[I2C.index][i],CFG_REG,INA3221[I2C.index][i].U_CFGREG.INA3221CfgReg); } } void Ina3221GetBusVal(IIC_TypeDef I2C,stcINA3221 INA3221) { INA3221.BusValue[0] = Ina3221GetReg(I2C ,INA3221,BV_REG_CHANNEL_1); INA3221.BusValue[1] = Ina3221GetReg(I2C ,INA3221,BV_REG_CHANNEL_2); INA3221.BusValue[2] = Ina3221GetReg(I2C ,INA3221,BV_REG_CHANNEL_3); } void Ina3221GetShuntVal(IIC_TypeDef I2C,stcINA3221 INA3221) { INA3221.shuntValue[0] = Ina3221GetReg(I2C ,INA3221,SV_REG_CHANNEL_1); INA3221.shuntValue[1] = Ina3221GetReg(I2C ,INA3221,SV_REG_CHANNEL_2); INA3221.shuntValue[2] = Ina3221GetReg(I2C ,INA3221,SV_REG_CHANNEL_3); } //转换算法 float Ina3221ShuntConversion( signed short dat ) { u16 Temp; float Temp1; if( dat & 0x8000 )//负电压处理 { dat = ~dat;//取反 dat += 1;//+1 } Temp = dat; Temp = Temp>>3; Temp1 = Temp*40.0f;//得到uV电压(lsb=40uV) Temp1 = (Temp1/0.3F);//0.3欧采样电阻得到uA电流 return ( (float)Temp1 ); } u16 Ina3221BusConversion( signed short dat ) { unsigned long tmp; if( dat & 0x8000 )//负电压处理 { dat = ~dat;//取反 dat += 1;//+1 } tmp = dat; tmp >>= 3; tmp *= 8;//得到mV电压 return ( (u16)tmp ); }分析代码
最新发布
07-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值