IIC协议的C语言编程详解

文章介绍了IIC协议的基本概念,包括它是半双工同步通信方式,使用两根信号线SDA和SCL。内容详细讲解了起始信号、终止信号和应答信号的生成代码,以及如何在单片机中实现数据的稳定传输。同时,文中提供了IIC协议的基础代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述:
学单片机很怕碰到所谓啥协议,理论上不好理解,说到底是时序比较难理解。这不这次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();
}

有问题欢迎留言讨论,当然需要了解更多还需要查阅相关数据手册,只是全英文的也令人头大。但相对而言,你的英文阅读水平或许可以提高一下。哈哈哈!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值