IIC通信协议

IIC协议是一种两线制的串行通信总线,常用于低速设备间通信。协议包括数据有效性规则,起始和停止信号的生成,从机应答机制以及寻址和数据传输方式。文中提供了起始和停止信号的示例代码,并展示了数据发送和接收的函数。
摘要由CSDN通过智能技术生成

什么时IIC协议    

  IIC(Inter-Integrated Circuit)即集成电路总线,它是一种具有两线传输的串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机连接低速周边设备而发展,适用于数据量不大且传输距离短的场合。

    IIC串行总线由两根信号线组成,一根是双向的数据线SDA,另一根是单向的时钟线SCL,在空闲状态时,SDA和SCL线都置’1‘,为高电平。

IIC为同步的半双工通信方式

常见的传输速率有:100kb/s、300kb/s、3.4Mkb/s

IIC物理层介绍

在时钟信号线和双向数据线上连接着主机和从机,在上面接了两根上拉电阻,目的是使SDA和SCL都保持高电平

IIC协议层

(1)数据有效性规定

当scl为高电平时数据保持稳定,在scl为低电平时,允许数据变化,之后再让数据保持稳定

(2)起始和停止信号

起始信号

当SCL为高电平时,SDA由高电平转化为低电平时,主机发送起始信号。程序如下

void IIC_start(void)
{
scl=1;
delay_10us(1);
SDA=1;
delay_10us(1);
SDA=0;
delay_10us(1);
SCL=0;
delay_10us(1);
}

 终止信号

当SCL为低电平时。SDA由低电平变为高电平时发出终止信号

void IIC_stop(void)
{
SCL=0;
delay_10(1);
SDA=0;
delay_10(1);
SDA=1;
delay_10(1);
}

 (3)应答响应

 

 从机SDA为低电平的时候产生应答

void iic_ack(void)
{
	IIC_SCL=0;
	IIC_SDA=0;	//SDA为低电平
	delay_10us(1);
   	IIC_SCL=1;
	delay_10us(1);
	IIC_SCL=0;
}

 

void iic_nack(void)
{
	IIC_SCL=0;
	IIC_SDA=1;	//SDA为高电平
	delay_10us(1);
   	IIC_SCL=1;
	delay_10us(1);
	IIC_SCL=0;	
}

(4)总线的寻址方式

 (5)数据传输

一共有三种传输方式

a,主机向从机发送数据,数据传送方向在整个过程中不变

 

b,主机在第一个字节后,立即从从机读数据

c,在传递过程中,当需要改变传递方向时,起始信号和

从机地址都被重复产生一次,但两次读写方向位正好相反

 

 IIC.C文件

#include "iic.h"


/*******************************************************************************
* 函 数 名       : iic_start
* 函数功能		 : 产生IIC起始信号
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void iic_start(void)
{
	IIC_SDA=1;//如果把该条语句放在SCL后面,第二次读写会出现问题
	delay_10us(1);
	IIC_SCL=1;
	delay_10us(1);
	IIC_SDA=0;	//当SCL为高电平时,SDA由高变为低
	delay_10us(1);
	IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
	delay_10us(1);
}

/*******************************************************************************
* 函 数 名         : iic_stop
* 函数功能		   : 产生IIC停止信号   
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void iic_stop(void)
{	
	IIC_SDA=0;//如果把该条语句放在SCL后面,第二次读写会出现问题
	delay_10us(1);
	IIC_SCL=1;
	delay_10us(1);
	IIC_SDA=1;	//当SCL为高电平时,SDA由低变为高
	delay_10us(1);			
}

/*******************************************************************************
* 函 数 名         : iic_ack
* 函数功能		   : 产生ACK应答  
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void iic_ack(void)
{
	IIC_SCL=0;
	IIC_SDA=0;	//SDA为低电平
	delay_10us(1);
   	IIC_SCL=1;
	delay_10us(1);
	IIC_SCL=0;
}

/*******************************************************************************
* 函 数 名         : iic_nack
* 函数功能		   : 产生NACK非应答  
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void iic_nack(void)
{
	IIC_SCL=0;
	IIC_SDA=1;	//SDA为高电平
	delay_10us(1);
   	IIC_SCL=1;
	delay_10us(1);
	IIC_SCL=0;	
}

/*******************************************************************************
* 函 数 名         : iic_wait_ack
* 函数功能		   : 等待应答信号到来   
* 输    入         : 无
* 输    出         : 1,接收应答失败
        			 0,接收应答成功
*******************************************************************************/
u8 iic_wait_ack(void)
{
	u8 time_temp=0;
	
	IIC_SCL=1;
	delay_10us(1);
	while(IIC_SDA)	//等待SDA为低电平
	{
		time_temp++;
		if(time_temp>100)//超时则强制结束IIC通信
		{	
			iic_stop();
			return 1;	
		}			
	}
	IIC_SCL=0;
	return 0;	
}

/*******************************************************************************
* 函 数 名         : iic_write_byte
* 函数功能		   : IIC发送一个字节 
* 输    入         : dat:发送一个字节
* 输    出         : 无
*******************************************************************************/
void iic_write_byte(u8 dat)
{                        
    u8 i=0; 
	   	    
    IIC_SCL=0;
    for(i=0;i<8;i++)	//循环8次将一个字节传出,先传高再传低位
    {              
        if((dat&0x80)>0) 
			IIC_SDA=1;
		else
			IIC_SDA=0;
        dat<<=1; 	  
		delay_10us(1);  
		IIC_SCL=1;
		delay_10us(1); 
		IIC_SCL=0;	
		delay_10us(1);
    }	 
}

/*******************************************************************************
* 函 数 名         : iic_read_byte
* 函数功能		   : IIC读一个字节 
* 输    入         : ack=1时,发送ACK,ack=0,发送nACK 
* 输    出         : 应答或非应答
*******************************************************************************/
u8 iic_read_byte(u8 ack)
{
	u8 i=0,receive=0;
   	
    for(i=0;i<8;i++ )	//循环8次将一个字节读出,先读高再传低位
	{
        IIC_SCL=0; 
        delay_10us(1);
		IIC_SCL=1;
        receive<<=1;
        if(IIC_SDA)receive++;   
		delay_10us(1); 
    }					 
    if (!ack)
        iic_nack();
    else
        iic_ack();  
		  
    return receive;
}

IIC.H文件

在使用不同单片机的时候连接的IO口模拟通信的管脚不同

#ifndef _iic_H
#define _iic_H

#include "public.h"

//定义EEPROM控制脚
sbit IIC_SCL=P2^1;//SCL时钟线
sbit IIC_SDA=P2^0;//SDA数据线


//IIC所有操作函数				 
void iic_start(void);			//发送IIC开始信号
void iic_stop(void);	  		//发送IIC停止信号
void iic_write_byte(u8 txd);	//IIC发送一个字节
u8 iic_read_byte(u8 ack);		//IIC读取一个字节
u8 iic_wait_ack(void); 			//IIC等待ACK信号
void iic_ack(void);				//IIC发送ACK信号
void iic_nack(void);			//IIC不发送ACK信号

#endif

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值