目录
1.GPIO模拟I2C(用C语言描述时序图)
首先认识一下I2C通信协议组成,主要由下面几部分组成。
1)开始与停止
总线在空闲状态时,SCL和SDA都保持着高电平。
启动信号:当SCL为高电平时,SDA由高到低的跳变,表示产生一个起始条件。
停止信号:当SCL为高电平时,SDA由低到高的跳变,表示产生一个停止条件。
#define I2C_SCL_L() HAL_GPIO_WritePin(GPIOB, I2C_SCL_Pin, GPIO_PIN_RESET)/* I2C接口的时钟信号*/
#define I2C_SCL_H() HAL_GPIO_WritePin(GPIOB, I2C_SCL_Pin, GPIO_PIN_SET)
#define I2C_SDA_L() HAL_GPIO_WritePin(GPIOB, I2C_SDA_Pin, GPIO_PIN_RESET)/* I2C接口的数据信号*/
#define I2C_SDA_H() HAL_GPIO_WritePin(GPIOB, I2C_SDA_Pin, GPIO_PIN_SET)
void I2C_Start()
{
SDA_OUT();
I2C_SCL_H();
Delay_us(1);
I2C_SDA_H();
Delay_us(1);
I2C_SDA_L();
Delay_us(1);
}
void I2C_Stop()
{
SDA_OUT();
I2C_SCL_H();
Delay_us(1);
I2C_SDA_L();
Delay_us(1);
I2C_SDA_H();
Delay_us(1);
}
/*标准C语言中没有空语句,但在C51中常使用空指令产生延时效果,调用该函数相当于调用汇编中的NOp指令
*延时一个机器周期的时间8M的晶振也差不多就1us*/
void Delay_us(u32t us)
{
u32t i;
for(i = 0; i < us; i++)
{
__nop();
}
}
void I2C_SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/*Configure GPIO pins : PB9 */
GPIO_InitStruct.Pin = I2C_SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void I2C_SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/*Configure GPIO pins : PB9 */
GPIO_InitStruct.Pin = I2C_SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void I2C_SCL_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/*Configure GPIO pins : PB8 */
GPIO_InitStruct.Pin = I2C_SCL_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
2)应答与非应答
应答:SCL为高电平SDA为低电平表示从机产生应答
非应答:SCL为高电平SDA为高电平表示从机产生非应答