I²C通信

文章介绍了I²C通信协议的基本原理,包括由NXP公司开发的两线式串行总线特点,如主从通信、数据传输和冲突检测功能。详细阐述了起始信号、地址码传输、数据收发的时序,并给出了与AT24C02芯片结合的应用示例,涉及初始化、读写操作及中断服务函数。
摘要由CSDN通过智能技术生成

I²C通信

1.1简介

IIC(Inter-Integrated Circuit)总线是一种由NXP(原PHILIPS)公司开发的两线式串行总线,用于连接微控制器及其外围设备。多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距离短,任意时刻只能有一个主机等特性。

在 CPU 与被控 IC 之间、IC 与 IC 之间进行双向传送,高速 IIC 总线一般可达 400kbps 以上。

当总线上有多个主机同时启用总线时,IIC也具备冲突检测和仲裁的功能来防止错误产生。

1.2硬件层

在这里插入图片描述

IIC一共有且仅有两条总线: 一条是数据线SDA,一条是时钟线SCL。
注:IIC采用漏极开路即高阻状态,适用于输入/输出,其可独立输入/输出低电平和高阻状态,若需要产生高电平,则需使用外部上拉电阻

1.3通信

1.3.1总时序图

在这里插入图片描述
在这里插入图片描述

1.3.2起始信号

SCL保持高电平,SDA完成一个下降沿。

在这里插入图片描述

1.3.3传送地址码

SCLSDA均为高电平表示逻辑1,SCL为高电平SDA为低电平表示逻辑0。

需要注意的是在每传送一个字节数据后,需要从机返回一个应答信号(SDA下降沿)。

在这里插入图片描述

1.3.3.1如何更改发送数据

拉低SCL,此时允许发送器更改SDA信号,更改结束重新拉高SCL信号。

1.3.4结束

SCL为高电平时SDA完成上升沿,这与起始信号相反。表示一次通信结束。

在这里插入图片描述

1.3.5收发数据

在这里插入图片描述

注:若两个设备之间已建立连接,想改变数据传送方向,可不发送停止信号而重新发送一次起始信号(即不交出总线的使用权)。
在这里插入图片描述

2、应用实例(与AT24C02结合)

#include <reg51.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char

unsigned char sec; //定义计数值,每过 1 秒,sec 加 1
unsigned int tcnt; //定时中断次数
bit write = 0; //写 24C08 的标志;
sbit sda = P2 ^ 0; 
sbit scl = P2 ^ 1; 
sbit dula = P2 ^ 6;
sbit wela = P2 ^ 7;
unsigned char j, k;

void delay(unsigned char i) { //延时程序
	for (j = i; j > 0; j--)
		for (k = 125; k > 0; k--);
}

uchar code table[] = {
	//数码管编码
	0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
	0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71
};

void display(uchar bai_c, uchar sh_c) { 
	dula = 0;
	P0 = table[bai_c];
	dula = 1;
	dula = 0;
	wela = 0;
	P0 = 0x7e;
	wela = 1;
	wela = 0;
	delay(5);
	dula = 0;
	P0 = table[sh_c];
	dula = 1;
	dula = 0;
	wela = 0;
	P0 = 0x7d;
	wela = 1;
	wela = 0;
	delay(5);
}

/24C02 读写驱动程序
void delay1(unsigned char x) { //延时子函数
	unsigned int i;
	for (i = 0; i < x; i++);
}

void flash() //延时子函数
{ ; ; }
void x24c08_init() { //24c02 初始化子程序
	scl = 1;
	flash();
	sda = 1;
	flash();
}
void start() { //启动 I2C 总线
	sda = 1;
	flash();
	scl = 1;
	flash();
	sda = 0;
	flash();
}
void stop() { //停止 I2C 总线
	sda = 0;
	flash();
	scl = 1;
	flash();
	sda = 1;
	flash();
}
void writex(unsigned char j) { //写一个字节
	unsigned char i, temp;
	temp = j;
	for (i = 0; i < 8; i++) {
		temp = temp << 1;
		scl = 0;
		flash();
		sda = CY;
		flash();
		scl = 1;
		flash();
	}
	scl = 0;//释放
	flash();//
	sda = 1;//为了读取应答信号(低电平)
	flash();//
}
unsigned char readx() { //读一个字节
	unsigned char i, j, k = 0;
	scl = 0;
	flash();
	sda = 1;//释放
    flash();
	for (i = 0; i < 8; i++) {
		scl = 1;//读总线
		flash();
        j = sda;
		k = (k << 1) | j;
		scl = 0;
        flash();
	}
	flash();
	return (k);
}
void clock() { //I2C 总线应答子函数
	uchar i = 0;
	scl = 1;//高电平可以读取信号
	flash();
	while ((sda == 1) && (i < 255))//没有收到应答信号
		i++;
	scl = 0;//第九个时钟拉低
	flash();
}
从 24c02 的地址 address 中读取一个字节数据/
unsigned char x24c08_read(unsigned char address) {
	unsigned char i;
	start();
	writex(0xa0);//高四位1010 低三位000 最后一位为0
	clock();
	writex(address);//寄存器地址
	clock();
	start();
	writex(0xa1);//最后一位的1为读数据信号
	clock();
	i = readx();
	stop();
	delay1(10);
	return (i);
}
//向 24c02 的 address 地址中写入一字节数据 info/
void x24c08_write(unsigned char address, unsigned char info) {
	start();
	writex(0xa0);
	clock();
	writex(address);
	clock();
	writex(info);
	clock();
	stop();
}
void t0(void) interrupt 1 using 0 { //定时中断服务函数
	TH0 = (65536 - 50000) / 256; //0.5s
	TL0 = (65536 - 50000) % 256; 
	tcnt++; 
	if (tcnt == 20) { //计满 20 次(1 秒)时
		tcnt = 0; 
		sec++;//读秒
		write = 1; //1 秒写一次 24C02
		if (sec == 100) { //定时 100 秒,在从零开始计时
			sec = 0;
		}
	}
}
void main() { 
	unsigned char i;
	TMOD = 0x01; 
	ET0 = 1;
	EA = 1;
	x24c08_init(); 
	sec = x24c08_read(2); //读出保存的数据赋于 sec
	TH0 = (65536 - 50000) / 256; 
	TL0 = (65536 - 50000) % 256; 
	TR0 = 1; //启动定时器
	while (1) {
		i = 10;
		while (i--) {
			display(sec / 10, sec % 10);
		}
		if (write == 1) { //判断计时器是否计时一秒
			write = 0; //清零
			x24c08_write(2, sec); //在 24c02 的地址 2 中写入数据 sec
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值