1,用stm32的普通IO口模拟iic时序,可以用较少的IO口实现iic功能,在实际使用中有很大优势。
2,stm32的IO可以设置为推挽,开漏输出模式,在开漏输出下,如果带上拉电阻,则可以双向传输数据,
如输出1(PCout()=1),从它的输入引脚可以读出状态(PCin()),
这样在不需要配置输入,输出模式,就可以实现iic数据线的写和读。
程序实现过程:
#define AT_IIC_SCL PCout(12)
#define AT_IIC_SDA PCout(11)
#define AT_IIC_SDA_READ PCin(11)
void I2cIoInit()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_SetBits(GPIOC,GPIO_Pin_12|GPIO_Pin_11);
}
void I2cStart()
{
AT_IIC_SDA=1;
AT_IIC_SCL=1;
delay_us(4);
AT_IIC_SDA=0;
delay_us(4);
AT_IIC_SCL=0;
}
void I2cStop()
{
AT_IIC_SCL=0;
AT_IIC_SDA=0;
delay_us(4);
AT_IIC_SCL=1;
AT_IIC_SDA=1;
delay_us(4);
}
uint8_t I2cWaitAck()
{
uint8_t errTimes=0;
AT_IIC_SDA=1;
delay_us(1);
AT_IIC_SCL=1;
delay_us(1);
while(AT_IIC_SDA_READ)
{
errTimes++;
if(errTimes>250)
{
I2cStop();
return 1;
}
}
AT_IIC_SCL=0;
return 0;
}
void I2cAck()
{
AT_IIC_SCL=0;
AT_IIC_SDA=0;
delay_us(2);
AT_IIC_SCL=1;
delay_us(2);
AT_IIC_SCL=0;
}
void I2cNoAck()
{
AT_IIC_SCL=0;
AT_IIC_SDA=1;
delay_us(2);
AT_IIC_SCL=1;
delay_us(2);
AT_IIC_SCL=0;
}
void I2cSendByte(uint8_t txdata)
{
uint8_t t;
AT_IIC_SCL=0;
for(t=0;t<8;t++)
{
if((txdata&0x80)>>7)
{
AT_IIC_SDA=1;
}
else
{
AT_IIC_SDA=0;
}
txdata<<=1;
delay_us(2);
AT_IIC_SCL=1;
delay_us(2);
AT_IIC_SCL=0;
delay_us(2);
}
}
uint8_t I2cReadByte(uint8_t ack)
{
unsigned char i,receive=0;
for(i=0;i<8;i++ )
{
AT_IIC_SCL=0;
delay_us(2);
AT_IIC_SCL=1;
receive<<=1;
if(AT_IIC_SDA_READ)
{
receive++;
}
delay_us(1);
}
if (!ack)
{
I2cNoAck();
}
else
{
I2cAck();
}
return receive;
}
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』