概述:
学单片机很怕碰到所谓啥协议,理论上不好理解,说到底是时序比较难理解。这不这次IIC协议就来了。IIC全称Inter-Integraed Circuit(集成电路总线),属于半双工同步通信方式。IIC串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL,其时钟信号是由主控器件产生。所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。对于并联在一条总线上的每个IIC都有唯一的地址。如图所示:
协议的使用:
IIC作为一种通信方式,其实质上也就是对信号的“操纵”。IIC总线在传输数据的过程中一共有三种类型信号,分别为起始信号,终止信号和应答信号。下面将用代码进行逐一表示。
- 起始信号
在SCL 线是高电平时,SDA 线从高电平向低电平切换表示起始条件。如图:
所以,对于上图只需要将红框内的部分用代码表示即可
void IIC_Start()
{
scl=1;
sda=1;
_nop_();//大约执行一下它是5us
sda=0;
_nop_();
}
- 终止信号
当SCL 是高电平时,SDA 线由低电平向高电平切换表示停止条件。如图:
同理:
void IIC_Stop()
{
scl=1;
sda=0;
_nop_();
sda=1;
_nop_();
}
- 应答信号
发送器每发送一个字节(8个bit),就在时钟脉冲9期间释放数据线(高电平),由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。如图:
代码如下:
char IIC_ACK()
{
char flag;//定义一个标志位,接收应答信号为高电平还是低电平。
sda=1; //在时钟脉冲9期间释放数据线(高电平)
_nop_();
scl=1;
_nop_();
flag=sda;
_nop_();
scl=0;
_nop_();
return flag;
}
传输数据:
在传输数据的过程中,我们要保证数据的有效性:SDA 线上的数据必须在时钟的高电平周期保持稳定。数据线的高或低电平状态,只有在SCL 线的时钟信号是低电平时才能改变(如图所示)。而且,发送到SDA 线上的每个字节必须为8 位。每次传输可以发送的字节数量不受限制。每个字节后必须跟一个响应位。首先传输的是数据的最高位。
代码如下:
void IIC_Send_Data(char dataSend)
{
int i;
//经过8次循环,发送完一个字节
for(i=0; i<8; i++){
scl=0; //scl拉低,让sda做好数据准备
sda= dataSend & 0x80; //获得数据高位,给sda。
_nop_();//发送数据建立时间
scl = 1;//scl拉高开始发送
_nop_();//数据发送时间
scl = 0;//发送完毕拉低
_nop_();
dataSend = dataSend << 1;//左移一位,去掉第一位为高位,让下一位做高位
}
}
IIC协议基础代码:
#include "reg52.h"
#include "intrins.h"
sbit scl = P0^1;//引脚定义可变
sbit sda = P0^3;
void IIC_Start()
{
sda = 1;
scl = 1;
_nop_();
sda = 0;
_nop_();
}
void IIC_Stop()
{
sda = 0;
scl = 1;
_nop_();
sda = 1;
_nop_();
}
char IIC_ACK()
{
char flag;
sda = 1;
_nop_();
scl = 1;
_nop_();
flag = sda;
_nop_();
scl = 0;
_nop_();
return flag;
}
void IIC_Send_Byte(char dataSend)
{
int i;
for(i = 0;i<8;i++){
scl = 0;//scl拉低,让sda做好数据准备
sda = dataSend & 0x80;//1000 0000获得dataSend的最高位,给sda
_nop_();//发送数据建立时间
scl = 1;//scl拉高开始发送
_nop_();//数据发送时间
scl = 0;//发送完毕拉低
_nop_();
dataSend = dataSend << 1;
}
}
void main()
{
int a = 20;
IIC_Start();
}
有问题欢迎留言讨论,当然需要了解更多还需要查阅相关数据手册,只是全英文的也令人头大。但相对而言,你的英文阅读水平或许可以提高一下。哈哈哈!