1,启用I2C1,如下图,PB8 PB9自动变成I2C模式
2,实现I2C读写驱动函数
//i2c 写
int VI2C_STD_Writebytes(uchar device,uchar reg,uchar *buff,uchar len)
{
return HAL_I2C_Mem_Write(&hi2c1, device, reg, 1,buff, len, 100);
}
//i2c 读
int VI2C_STD_Readbytes(uchar device,uchar reg,uchar *buff,uchar len)
{
return HAL_I2C_Mem_Read(&hi2c1, device, reg, 1,buff, len, 100);
}
3,protues不支持stm32硬件I2C,下面是模拟I2C驱动,注意将PB8配置为推挽输出,PB9配置为开漏输出并上拉使能实现双向读写
#define VI2C_SCL_0() HAL_GPIO_WritePin(I2C_SCL_GPIO_Port, I2C_SCL_Pin, GPIO_PIN_RESET)
#define VI2C_SCL_1() HAL_GPIO_WritePin(I2C_SCL_GPIO_Port, I2C_SCL_Pin, GPIO_PIN_SET)
#define VI2C_SDA_0() HAL_GPIO_WritePin(I2C_SDA_GPIO_Port, I2C_SDA_Pin, GPIO_PIN_RESET)
#define VI2C_SDA_1() HAL_GPIO_WritePin(I2C_SDA_GPIO_Port, I2C_SDA_Pin, GPIO_PIN_SET)
void i2c_delay()
{
__IO unsigned int cnts=10;
while(cnts--);
}
void VI2C_Start()
{
VI2C_SDA_1();
i2c_delay();
VI2C_SCL_1();
i2c_delay();
VI2C_SDA_0();
i2c_delay();
}
void VI2C_Stop(void)
{
VI2C_SDA_0();
i2c_delay();
VI2C_SCL_1();
i2c_delay();
VI2C_SDA_1();
i2c_delay();
}
uchar VI2C_ReadACK(void)
{
uchar ret=1;
VI2C_SCL_1();
i2c_delay();
if(VI2C_READ_SDA()==0)
ret=0;
VI2C_SCL_0();
i2c_delay();
return ret;
}
uchar VI2C_WriteData(uchar data)
{
uchar i;
for(i=0;i<8;i++)
{
VI2C_SCL_0();
i2c_delay();
if(data&0x80)
VI2C_SDA_1();
else
VI2C_SDA_0();
i2c_delay();
VI2C_SCL_1();
i2c_delay();
data=data<<1;
}
VI2C_SCL_0();
i2c_delay();
VI2C_SDA_1();
return VI2C_ReadACK();
}
uchar VI2C_WriteAdd(uchar add,uchar w)
{
uchar data;
if(w)
{
data=add;
}
else
{
data=(add|0x01);
}
return VI2C_WriteData(data);
}
uchar VI2C_ReadData(uchar *data,uchar ack)
{
uchar ret , i;
VI2C_SCL_0();
i2c_delay();
for(i=0;i<8;i++)
{
ret=ret<<1;
VI2C_SCL_1();
i2c_delay();
if(VI2C_READ_SDA())
ret=ret|1;
else
ret=ret&0xfe;
VI2C_SCL_0();
i2c_delay();
}
if(ack)
VI2C_SDA_0();
else
VI2C_SDA_1();
i2c_delay();
VI2C_SCL_1();
i2c_delay();
VI2C_SCL_0();
i2c_delay();
VI2C_SDA_1();
*data=ret;
return 0;
}
uchar VI2C_STD_Writebytes(uchar add,uchar cmd,uchar *data, uchar len)
{
unsigned char i,err=0;
VI2C_Start();
if(VI2C_WriteAdd(add,1))
{
err|=2;//no ack
goto end;
}
if(VI2C_WriteData(cmd))
{
err|=4;//no ack
goto end;
}
for(i=0;i<len;i++)
{
if(VI2C_WriteData(data[i]))
{
err|=4;//no ack
goto end;
}
}
end:
VI2C_Stop();
return err;
}
uchar VI2C_STD_Readbytes(uchar add,uchar cmd,uchar *data, uchar len)
{
unsigned char i,err=0;
VI2C_Start();
if(VI2C_WriteAdd(add,1))
{
err|=2;//no ack
goto end;
}
if(VI2C_WriteData(cmd))
{
err|=4;//no ack
goto end;
}
VI2C_Start();
if(VI2C_WriteAdd(add,0))
{
err|=2;//no ack
goto end;
}
for(i=0;i<len;i++)
{
if(VI2C_ReadData(data+i,1))
{
err|=4;//no ack
goto end;
}
}
end:
VI2C_Stop();
return err;
}
4,PCF8563时钟读写驱动
typedef struct
{
uchar sec;
uchar min;
uchar hour;
uchar day;
uchar week;
uchar month;
uchar year;
}Struct_CLOCK;
#define TB_PCF8563_ADDR 0XA2
Struct_CLOCK systemclock={0x10,0x30,0X13,0X01,0X02,0X10,0X24};//2024-10-1 13:30:10
void PCF8563_Init(void)
{
uchar I2cwdtbuf[16];
I2cwdtbuf[0] = 0x00;
I2cwdtbuf[1] = 0x00;
I2cwdtbuf[13] = 0xFF; //CLK out 1HZ
I2cwdtbuf[14] = 0x00;
I2cwdtbuf[15] = 0x00;
VI2C_STD_Writebytes(TB_PCF8563_ADDR,0,I2cwdtbuf,2);
VI2C_STD_Writebytes(TB_PCF8563_ADDR,13,(I2cwdtbuf+13),1);
VI2C_STD_Writebytes(TB_PCF8563_ADDR,14,(I2cwdtbuf+14),2);
}
void PCF8563_Read(void)
{
if(VI2C_STD_Readbytes(TB_PCF8563_ADDR,0X02,(uchar *)&systemclock,7)==0)
{
systemclock.sec &= 0X7F;
systemclock.min &= 0X7F;
systemclock.hour &= 0X3F;
systemclock.day &= 0X3F;
systemclock.week &= 0X07;
systemclock.month &= 0X1F;
//systemclock.year &= 0XFF;
}
}
void ZPCF8563_Write()
{
if(VI2C_STD_Writebytes(TB_PCF8563_ADDR,0X02,(uchar *)&systemclock,7)==0)
{
}
}
git源码:https://gitee.com/armfun/stm32_proteus
近期评论