STM32-IIC协议理解和IO模拟IIC程序实现

1. IIC简介

IIC通信方式为:半双工、同步、串行通信。
IIC协议由飞利浦公司设计的,属于一主多从的总线结构,总线上的每个设备都有一个特定的设备地址,以区分同一I2C总线上的其他设备。

2. IIC物理拓扑结构

物理拓扑结构:
在这里插入图片描述
SDA:双向数据线,主机可以通过SDA线发送数据给从机,从机也可以通过SDA线
发送数据给主机。
SCL: 时钟信号线。驱动数据线收发数据的脉冲信号由SCL提供。注意SCL脉冲信号永远
由主机发出。
注意:IIC总线要求每个设备SCL/SDA线都是开漏模式,因此必须带上拉电阻才能正常工作。

3. IIC协议时序

3.1 空闲状态

空闲状态SDA和SCL都处于高电平
此时输出级场效应管均处在截止状态,即释放总线,由两条信号线的上拉电阻把电平拉高。

3.2 起始(START)信号

起始信号:SCL为高电平期间,SDA有一个下降沿
逻辑分析仪波形:
在这里插入图片描述
程序实现:

static void I2C_Start(void)
{
	PO_SCL_H();
	I2C_DELAY();
	PO_SDA_H();
	I2C_DELAY(); //确保发送起始信号前处于空闲状态
	
	PO_SDA_L();
	I2C_DELAY();//SDA产生下降沿,即是起始信号

	PO_SCL_L();
	I2C_DELAY();//为接下来传输数据做准备
}

3.3 停止(STOP)信号

停止信号:SCL为高电平期间,SDA有一个上升沿
逻辑分析仪波形:
在这里插入图片描述
程序实现:

static void I2C_Stop(void)
{
	PO_SDA_L();
	I2C_DELAY();
	
	PO_SCL_H();
	I2C_DELAY();
	
	PO_SDA_H();//SDA产生上升沿,即是停止信号
	I2C_DELAY();
}

3.4 读写数据

在这里插入图片描述
注意:在数据传输时,如果SCL为高电平,数据不允许改变(为了区别起始条件和停止条件),必须保持稳定。数据传输是以高位在前,低位在后。

3.4.1 写数据

逻辑分析仪获取的写时序:
在这里插入图片描述
写一个字节数据步骤:
在这里插入图片描述

①主设备发送一个起始信号,占用总线;
②主设备发送设备地址(设备地址7bit + 写控制位1bit);
③等待从设备的应答ACK;
④收到ACK后,开始发送数据,主设备先发送内部地址,然后等待从设备的应答;
⑤收到ACK后,主设备开始发送一个字节的数据;
⑥等待从设备ACK,确定从设备收到数据后,主设备发送停止信号,释放总线。

程序实现:


static U8 I2C_WriteByte(U8 data)
{
	U8 cnt;

	for (cnt = 0; cnt < 8; cnt++)
	{
		PO_SCL_L();
		I2C_DELAY();

		if (data & 0x80)
		{
			PO_SDA_H();
		}
		else
		{
			PO_SDA_L();
		}
		
		data <<= 1;
		I2C_DELAY();

		PO_SCL_H();
		I2C_DELAY();
	}

	PO_SCL_L();
	I2C_DELAY();

	return I2C_GetAck();//返回应答情况
}

void I2C_WriteNBytes(U8 deviceadd, U8 subadd, U8 *buf, U8 len)
{
	U8 i, j;
	U8 tmp;

	for (j = 0; j < 3; j++)
	{
		I2C_Start();
		tmp = I2C_WriteByte(deviceadd);

		if (tmp == ACK)
		{
			tmp = I2C_WriteByte(subadd);
		}

		if (tmp == ACK)
		{
			for (i = 0; i < len; i++)
			{
				I2C_WriteByte(*(buf + i));
			}

			j = 3;//写成功
		}

		I2C_Stop();
		delay_ms(1);
	}
}

3.4.2 读数据

逻辑分析仪获取的读时序:
在这里插入图片描述
读取一个字节数据的步骤:
在这里插入图片描述

①主设备发送一个起始信号,占用总线;
②主设备发送设备地址(设备地址7bit + 写控制位1bit);
③等待从设备应答ACK
④收到ACK后,主设备发送内部地址,等待从设备应答;
⑤收到ACK后,主设备再次发送起始信号;
⑥主设备发送设备地址(设备地址7bit + 读控制位1bit);
⑦等待从设备应答
⑧收到ACK后,开始从从设备读取一个字节的数据
⑨接收完最后一个数据后,主设备发送一个NACK;
⑩然后主设备发送停止信号,释放总线。

程序实现:

static U8 I2C_ReadByte(U8 ack)
{
	U8 cnt, data = 0;

	PO_SCL_L();
	I2C_DELAY();

	PO_SDA_H();
	I2C_DELAY();

	for (cnt = 0; cnt < 8; cnt++)
	{
		PO_SCL_H();
		I2C_DELAY();
		
		data <<= 1;
		
		if (GET_SDA_STATE())
		{
			data |= 0x01;
		}

		PO_SCL_L();
		I2C_DELAY();
	}

	I2C_PutAck(ack);
	
	return data;
}

3.5 应答信号(ACK:有效应答,NACK:无效应答)

在这里插入图片描述
当SDA是低电平为有效应答(ACK),表示对方接收成功;
当SDA是高电平为无效应答(NACK),表示对方没有接收成功。

程序实现:

//获取从设备应答
static U8 I2C_GetAck(void)
{
	U8 ack;

	PO_SCL_L();
	I2C_DELAY();

	PO_SDA_H();
	I2C_DELAY();

	PO_SCL_H();
	I2C_DELAY();

	if (GET_SDA_STATE())
	{
		ack = NO_ACK;
	}
	else
	{
		ack = ACK;
	}

	PO_SCL_L();
	I2C_DELAY();
	
	return ack;
}

static void I2C_PutAck(U8 ack)
{
	PO_SCL_L();
	I2C_DELAY();

	if (ack == ACK)
	{
		PO_SDA_L();
	}
	else
	{
		PO_SDA_H();
	}
	
	I2C_DELAY();

	PO_SCL_H();
	I2C_DELAY();
	PO_SCL_L();
	I2C_DELAY();
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
您好!对于使用HAL库来实现STM32IO模拟IIC驱动程序,您可以按照以下步骤进行操作: 1. 配置GPIO引脚: 首先,您需要将IIC的SCL和SDA引脚配置为GPIO模式,并设置为推挽输出。您可以使用HAL库提供的函数来完成引脚的初始化配置。 2. 定义IIC相关的宏和函数: 在驱动程序中,您需要定义一些相关的宏和函数来实现IIC的功能,例如IIC的起始信号、停止信号、发送数据、接收数据等。 3. 初始化IIC总线: 在主程序中,您需要调用HAL库提供的函数来初始化IIC总线,并设置相关的参数,例如时钟频率、数据传输速率等。 4. 实现IIC的起始信号和停止信号: 通过GPIO操作,您可以实现IIC的起始信号和停止信号。起始信号是将SDA引脚从高电平切换到低电平,然后再将SCL引脚从高电平切换到低电平。停止信号是将SDA引脚从低电平切换到高电平,然后再将SCL引脚从低电平切换到高电平。 5. 实现IIC的数据传输: 通过GPIO操作,您可以实现IIC的数据传输。发送数据时,您需要将数据从高位到低位依次发送,并在每个位发送后切换SCL引脚的电平。接收数据时,您需要在每个位发送后读取SDA引脚的电平,并将数据从低位到高位依次接收。 请注意,以上仅为一个简单的示例,您可能需要根据具体的硬件和需求进行适当的调整和扩展。此外,使用HAL库编写驱动程序时,您可以参考HAL库的文档和示例代码来了解更多使用方法和注意事项。 希望以上信息对您有所帮助!如果您还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值