STM32软件模拟I2C
初始化I2C通讯模块
开启对应外设时钟
开启GPIO的APB2外设时钟。
| RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx, ENABLE);
|
设置引脚输出模式
SCL和SDA引脚输出模式需要设置为开漏输出模式。
| GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_scl | GPIO_Pin_sda; //SCL和SDA所对应的GPIO引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(IIC_GPIO_SELECT, &GPIO_InitStructure);
|
SCL、SDA引脚置高电平
将SCL和SDA对应的GPIO引脚置高电平完成IIC的初始化。
| GPIO_SetBits(IIC_GPIO_SELECT, IIC_SCL); //初始化SCL、SDA引脚置高电平
GPIO_SetBits(IIC_GPIO_SELECT, IIC_SDA);
|
IIC的6个基本时序单元
起始条件
确保SDA和SCL都被释放,然后先拉底SDA后拉低SCL就可以实现起始条件。
| void IIC_Start(){ //起始条件
IIC_W_SDA(1); //确保SCL、SDA置高电平
IIC_W_SCL(1);
IIC_W_SDA(0); //先拉低SDA后拉低SCL进入起始条件
IIC_W_SCL(0);
}
|
终止条件
终止条件下,需要先拉低SDA,然后释放SCL,再释放SDA。
| void IIC_Stop(){ //终止条件
IIC_W_SDA(0);
IIC_W_SDA(1);
IIC_W_SDA(1);
}
|
发送一个字节
| void IIC_SendBit(uint8_t Byte){ //发送一个字节
uint8_t i;
for (i=0;i<8;i++){ //循环8次发送一个字节
IIC_W_SDA (Byte & (0x80 >> i)); //通过按位与的方式取出8位变量Byte的最高位
IIC_W_SCL(1); //驱动时钟
IIC_W_SCL(0);
}
}
|
接收一个字节
| uint8_t IIC_ReceiveByte(){ //接收一个字节
uint8_t i,Byte = 0x00;
IIC_W_SDA(1); //释放SDA
for (i=0;i<8;i++){
IIC_W_SCL(1); //时钟置高电平接收数据
if (IIC_R_SDA() == 1){ //如果读取数据为1
Byte |= (0x80 >> i); //最高位置1
IIC_W_SCL(1); //读取完成拉低SCL
}
}
return Byte;
}
|
发送应答
| void IIC_SendAck(uint8_t AckBit){ //发送应答
IIC_W_SDA(AckBit); //发送一个字节
IIC_W_SCL(1); //驱动时钟
IIC_W_SCL(0);
}
|
接收应答
| uint8_t IIC_ReceiveAck(){ //接收应答
uint8_t AckBit;
IIC_W_SDA(1); //释放SDA
IIC_W_SCL(1); //时钟置高电平接收数据
AckBit = IIC_R_SDA(); //读取值
IIC_W_SCL(0); //SCL置低
return AckBit;
}
|