IIC协议原理及IIC通信的具体实现(S3C2440裸机开发)


前言

本期和大家主要分享的是一种非常常见并且非常常用的的一种协议------IIC通信协议;既然能称为一种协议,那么一定是通信中人们需要去遵守的一种通信标准,接下来让我们细细来了解一下!


一、IIC协议

IIC有两条串行线,一条是专用串行数据线(SDA),另一条是专用串行时钟线(SCL),并且这两根线都是双向的;
同步串行半双工,多主的总线协议;

二、IIC的控制

2.1 IIC控制相关寄存器

S3C2440要是想控制IIC总线,那么必须写入值到以下寄存器中:

多主控 IIC 总线控制寄存器,IICCON
多主控 IIC 总线控制/状态寄存器,IICSTAT
多主控 IIC 总线 Tx/Rx 数据移位寄存器,IICDS
多主控 IIC 总线地址寄存器,IICADD

IIC的总线框图如下:
在这里插入图片描述

2.2 IIC控制中的特征信号

要想合理的控制IIC总线,必须清楚几个重要的信号:
(1)当IIC总线空闲时,SCL和SDA两个串行线都为高电平;
(2)IIC总线的起始信号:SCL为高时(总线空闲),SDA由高变低的这个信号,定义其为一个起始信号(start);
(3)IIC总线的停止信号:SCL为高时(总线使用时),SDA由低变高的这个信号,定义其为一个停止信号(stop);
在这里插入图片描述
这里需要注意的是start和end只能由主机发出;当产生了stop信号后,iic总线变为空闲状态;

2.3 IIC的数据传输格式

当start信号被发送后,要想进行通信,必须指出通信目标的地址,之后再进行数据发送;发送完毕后再发送stop信号;按字节发送,高位先发 ,每8位发送必须有一个位应答;

start发送后,紧接着的1个字节允许用户写入从机地址和读写标志,这一个字节中前七位为从机地址,最后一位是读写标志(0为写标志,1为读标志);

start	  +	1字节				+	ack	+	数据
SCL=1		前七位为从机地址		
SDA=0		最后一位为读写标志

2.3.1 ACK信号

(1)为了完成一次单字节传输操作,接收器应该发送一个 ACK 位给发送器。ACK 脉冲应该发生在 SCL 线的第 9个时钟。前 8 个时钟是提供给单字节传输的。主机需要应该产生时钟脉冲来发送 ACK 位。
(2)当发送器收到 ACK 时钟脉冲时,应该通过拉高 SDA 线(stop)来释放 SDA 线。当接收器在 ACK 时钟脉冲期间也应该驱动 SDA 线为低,在第 9 个脉冲的高电平时期期间保持 SDA 为低。
(3)ACK 位发送功能可以由软件(IICSTAT)使能或禁止。然而,需要 SCL 的第 9 个时钟上的 ACK 脉冲来完成单字节的传输操作。
在这里插入图片描述

2.3.2 数据读写操作

(1)发送模式中当发送了数据时,在 IIC 总线数据移位(IICDS)寄存器收到新数据之前 IIC 总线接口将会一直等待。在新数据写入到寄存器之前,SCL 线将会保持为低,然后在其写入后释放。S3C2440A 应该等待中断来确定当前数据发送的完成。在 CPU 收到中断请求后,需要再次写一个新数据到 IICDS 寄存器中。
(2)接收模式中当收到了数据时,在读取 IICDS 寄存器前 IIC 接口将会一直等待。在新数据读出前,SCL 线将会保持为低,然后在其读取后释放。S3C2440A 应该等待中断来确定当前数据接收的完成。在 CPU 收到中断请求后,需要从 IICDS 寄存器中读取数据。
在这里插入图片描述
这里当主机发送了一个数据后并且ACK信号产生之后,SCL会变为低电平,这个时候从机可以读取数据;

2.3.3 中止通信

(1)如果从接收器不能应答从地址的确认,其应该保持 SDA 线的电平为高。这种情况中,主机应该产生一个停止条件并且中止传输。
(2)如果主机接收器受到了传输中止的影响,其应该通过取消来自从机收到的最后数据字节后 ACK(nack)的产生来指示从发送操作的结束。从发送器应该随后释放 SDA 来允许主机产生停止条件。

三、 IIC编程

3.1 IIC编程的相关寄存器

  1. start stop ack noack
    IICCON 第7位 1使能ack 0禁止ack
    IICSTAT 第5位 写操作 1 start信号 0 stop信号 读操作 1 总线忙碌 0 总线空闲
    IICSTAT 第4位 1使能电路
    在这里插入图片描述
    在这里插入图片描述

  2. 数据
    IICDS发送和接收的缓存区
    IICADDIIC 总线地址寄存器
    在这里插入图片描述
    在这里插入图片描述

  3. 数据操作时刻
    IICCON第5位使能中断(发完8位 接够8位产生中断)
    IICCON第4位 中断标志(读操作 1 产生中断 0 没有中断 写0清除中断)
    IICSTAT 第0位 0 接收到ack 1没有ack

  4. 时钟 IICCON 第6位 一级分频 第3-0位二级分频值

3.2 IIC代码实现

void iic_init()
{
	GPECON &= ~(0xf<<28);
	GPECON |= 0xa<<28;						  //设置GPE14,15为IIC功能
	IICCON = (1<<7) | (1<<5) | (1<<6);		  //使能ack,使能中断,时钟=50M/512/1 = 97k;
	IICSTAT = 1<<4;							  //使能输出
}

int wait_pend()
{
	int cnt = 0xffff;

	while (cnt--)
	{
		if(IICCON & (1<<4))			//标志位是否置位,置位代表发完了
		{
			return 0;
		}
	}
	return -1;
}

void clear()
{
	IICCON &= ~(1<<4);	   //清除中断标志位
}

void stop()
{
	int num = 1000;

	IICSTAT = 0xd0;	//发送stop信号
	clear();	
	while(num--);	//电路作用需要时间
}

int iic_write(char s_addr, char d_addr, char data) //总流程是写入从机地址,写入数据地址,最后写入数据
{
	int ret = -1;

	IICDS = s_addr<<1;			//写入从机地址和写标志(最后一位是写标志)
	IICSTAT = 0xf0;				//发送start信号

	if(wait_pend() < 0)			//(如果中断标志位置位)判断发送完毕
	{
		stop();
		return ret;				//没发完,发的有问题
	}

	if(IICSTAT & 1)				//没有收到ack
	{
		stop();
		return ret;	
	}							//上面两个if的作用是条件不成立时退出

	IICDS = d_addr;
	clear();					//开始发送数据地址

	if(wait_pend() < 0)			//判断发送完毕
	{
		stop();
		return ret;
	}

	if(IICSTAT & 1)				//有没有收到ack
	{
		stop();
		return ret;	
	}							//上面两个if的作用是条件不成立时退出

	IICDS = data;
	clear();					//开始发送数据

	if(wait_pend() < 0)			//判断发送完毕
	{
		stop();
		return ret;
	}

	if(IICSTAT & 1)				//有没有收到ack
	{
		stop();
		return ret;	
	}							//上面两个if的作用是条件不成立时退出
	stop();
	ret = 0;
	return ret;
}


int iic_read(char s_addr, char d_addr, char *data)
{
	int ret = -1;

 	IICDS = s_addr<<1;			//写入从机地址和写标志(最后一位是写标志)
	IICSTAT = 0xf0;				//发送start信号

	if(wait_pend() < 0)			//判断发送完毕
	{
		stop();
		return ret;
	}

	if(IICSTAT & 1)				//没有收到ack
	{
		stop();
		return ret;	
	}							//上面两个if的作用是条件不成立时退出

	IICDS = d_addr;
	clear();					//开始发送数据地址

	if(wait_pend() < 0)			//判断发送完毕
	{
		stop();
		return ret;
	}

	if(IICSTAT & 1)				//没有收到ack
	{
		stop();
		return ret;	
	}
	stop();						//发送start信号的stop(一个start一个stop)

	IICDS = (s_addr<<1) | 1;	//写入从机地址和读标志(最后一位是写标志)
	IICSTAT = 0xb0;				//发送start信号

	if(wait_pend() < 0)			//判断发送完毕
	{
		stop();
		return ret;
	}

	if(IICSTAT & 1)				//没有收到ack
	{
		stop();
		return ret;	
	}

	IICCON &= ~(1<<7);			//禁止ack
	clear();					//清除标志位,也就是开始接收
	if(wait_pend() < 0)			//判断是否接收完毕
	{
		stop();
		return ret;
	}
	*data = IICDS;				 //一个字节收到

	stop();
	ret = 0;
	return ret;
}

测试代码:

void main(void)
{
	uart_init();
	iic_init();
	uprintf("ni hao pc!\r\n");
	
//	while(iic_write(0x50, 0x23, 0x45) < 0);		  //返回值为0跳出循环,写入成功
	
	while(iic_read(0x50, 0x23, &info) < 0);
	uprintf("info = %c\r\n", info);
	while(1)
	{
	
	}
}

总结

本期和大家分享的是IIC协议以及IIC编程,将数据写入板载的EEPROM中,再从EEPROM中读出来,实现一个IIC协议的demo,希望通过这个demo各位小伙伴们能够掌握IIC通信的全过程。个人观点:S3C2440中的IIC机制相对比较完善,如果想要更深一步学习IIC,大家可以使用IO口模拟IIC,以此提升自己对IIC协议的理解!最后,各位小伙伴们如果喜欢我的分享可以点赞收藏哦,你们的认可是我创作的动力,一起加油!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
IIC(Inter-Integrated Circuit)是一种双向串行通信协议,也叫做TWI(Two-Wire Interface),它由Philips公司开发,现在已经被广泛应用于各种嵌入式系统中。IIC通信协议基于主从架构,通过两根线进行通信,其中包括一个数据线(SDA)和一个时钟线(SCL)。 IIC通信协议的基本原理如下: 1. 通信起始 通信起始是指主机向从机发送起始信号,表示通信即将开始。通信起始的时序如下: 主机在SCL线上发送一个低电平,然后在SDA线上发送一个高电平,这个时候SDA线上的电平高电平,SCL线上的电平为低电平,表示起始信号已经发送。 2. 从机地址 从机地址是指主机向从机发送地址信息,以确定通信对象。从机地址的时序如下: 主机首先向SDA线上发送从机地址,从机地址是一个7位二进制数,最高位为0表示写操作,为1表示读操作,后6位为从机的地址。 从机接收到地址信息后,会发送一个应答信号,表示从机已经准备好接收数据。应答信号是由从机在SCL线上拉低SDA线来实现的。 3. 数据传输 数据传输是指主机向从机发送数据或从从机接收数据。数据传输的时序如下: 主机首先向SDA线上发送一个8位二进制数据,然后从机接收到数据后会发送一个应答信号,表示数据已经接收。 如果是主机向从机发送多个数据,则在发送完一个数据后,主机会继续发送下一个数据,直到所有数据传输完成。 4. 通信结束 通信结束是指主机向从机发送结束信号,表示通信已经结束。通信结束的时序如下: 主机在SCL线上发送一个高电平,然后在SDA线上发送一个低电平,这个时候SDA线上的电平为低电平,SCL线上的电平为高电平,表示结束信号已经发送。 总之,IIC通信协议是一种简单、可靠的通信协议,具有通信速率快、线路简单、可靠性高等优点,广泛应用于各种嵌入式系统中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值