当前位置: 代码迷 >> 综合 >> IIC协议原理(24C02 , MCP4017)
  详细解决方案

IIC协议原理(24C02 , MCP4017)

热度:57   发布时间:2023-11-26 12:46:27.0

文章目录

  • 前言
  • 一、IIC简介
  • 二、协议层
    • 1.开始/停止动作
    • 2.应答动作
    • 3.写/读字节
    • 4.空闲状态
  • 三、AT24C02
    • 1.概况
    • 2.写操作
    • 3.读操作
  • 四、MCP4017可编程电阻
    • 1.概况
    • 2.读\写动作
  • 总结


前言


提示:以下是本篇文章正文内容

一、IIC简介

I2C(IIC,Inter-Integrated Circuit), 两线式串行总线, 由PHILIPS公司开发用于连接微控制器及其外围设备

在这里插入图片描述

它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。IIC是半双工通信方式

在这里插入图片描述

IIC总线是不同的IC或模块之间的双向两线通信,这两条线是串行数据线(SDA)和串行时钟线(SCL)。这两条线必须通过上拉电阻连接正电源。数据传输只能在总线不忙时启动。

二、协议层

有效数据:在时钟的高电平周期内,SDA线上的数据必须保持稳定,数据线仅可以在时钟SCL为低电平时改
在这里插入图片描述

1.开始/停止动作

开始动作:当SCL为高电平的时候,SDA线上由高到低的跳变

在这里插入图片描述

void I2CStart(void)
{
    SDA_Output(1); // SDA_Output只是一个输出电平函数delay1(DELAY_TIME);SCL_Output(1);delay1(DELAY_TIME);SDA_Output(0);   // SDA拉低delay1(DELAY_TIME);SCL_Output(0); //为了下一步动作SDA,只能在SCL低地电平期间,电平反转delay1(DELAY_TIME);
}

结束动作:当SCL为高电平的时候,SDA线上由低到高的跳变
在这里插入图片描述

void I2CStop(void)
{
    SCL_Output(0);delay1(DELAY_TIME);SDA_Output(0);delay1(DELAY_TIME);SCL_Output(1);delay1(DELAY_TIME);SDA_Output(1);delay1(DELAY_TIME);
}

注意起始和终止信号都是由主机发出的,总线在起始条件之后,视为忙状态,在停止条件之后被视为空闲状态

2.应答动作

每当主机向从机发送完一个字节的数据,主机总是需要等待从机给出一个应答信号,以确认从机是否成功接收到了数据

从机应答主机所需要的时钟仍是主机提供的,应答出现在每一次主机完成8个数据位传输后紧跟着的时钟周期,低电平0表示应答, 接收器成功地接收了该字节,1表示非应答,接收器没有成功接收该字节
在这里插入图片描述

等待从机发送应答或者非应答

unsigned char I2CWaitAck(void)
{
    unsigned short cErrTime = 5;SDA_Input_Mode();delay1(DELAY_TIME);SCL_Output(1);delay1(DELAY_TIME);while(SDA_Input()){
    cErrTime--;delay1(DELAY_TIME);if (0 == cErrTime){
    SDA_Output_Mode();I2CStop();return ERROR;}}SCL_Output(0);delay1(DELAY_TIME);SDA_Output_Mode();return SUCCESS;
}

注:若采用官方给的参考,需做如下修改:将SDA放在他们最后
在这里插入图片描述

主机或者从机产生应答

void I2CSendAck(void)
{
    SDA_Output(0);delay1(DELAY_TIME);delay1(DELAY_TIME);SCL_Output(1);delay1(DELAY_TIME);SCL_Output(0);delay1(DELAY_TIME);}

主机或者从机产生非应答

void I2CSendNotAck(void)
{
    SDA_Output(1);delay1(DELAY_TIME);delay1(DELAY_TIME);SCL_Output(1);delay1(DELAY_TIME);SCL_Output(0);delay1(DELAY_TIME);}

3.写/读字节

数据传输过程中,数据传输保持稳定(在SCL高电平期间,SDA一直保持稳定,没有跳变),只有当SCL被拉低后,SDA才能被改变在SCL为高电平期间(有效数据时间段),发送数据,发送8次数据,如果数据为1,显然SDA是被拉高;如果数据为0,那么SDA被拉低

输出到SDA线上的每个字节必须是8位,数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)

在这里插入图片描述
写一个字节:

void I2CSendByte(unsigned char cSendByte)
{
    unsigned char  i = 8;while (i--){
    SCL_Output(0);delay1(DELAY_TIME);SDA_Output(cSendByte & 0x80);delay1(DELAY_TIME);cSendByte += cSendByte;delay1(DELAY_TIME);SCL_Output(1);delay1(DELAY_TIME);}SCL_Output(0);delay1(DELAY_TIME);
}

读一个字节

unsigned char I2CReceiveByte(void)
{
    unsigned char i = 8;unsigned char cR_Byte = 0;SDA_Input_Mode();while (i--){
    cR_Byte += cR_Byte;SCL_Output(0);delay1(DELAY_TIME);delay1(DELAY_TIME);SCL_Output(1);delay1(DELAY_TIME);cR_Byte |=  SDA_Input();}SCL_Output(0);delay1(DELAY_TIME);SDA_Output_Mode();return cR_Byte;
}

这里数据的移位采用的是cSendByte += cSendByte,每次最高位刚好等于次高位,从而达到左移效果

4.空闲状态

I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态

此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高

三、AT24C02

1.概况

在这里插入图片描述
引脚和封装
在这里插入图片描述
注意:A0、A1、A2、三个脚不同的电平可以形成不同的地址,最多8种

从机地址组成
在这里插入图片描述

硬件原理图
在这里插入图片描述
所以,前面固定为1010 000(r/w)
24C02的芯片地址为1010 (A2 A1 A0) (R=1,W=0)
0xA0写
0xA1读

2.写操作

在这里插入图片描述
AT24C02存储器写操作需要给出开始状态,器件地址和确认之后,紧跟着给出一个8为数据地址。一经收到该地址,EEPROM就通过SDA发出确认信号,并随时钟输入8位数据。在收到8位数据之后,EEPROM将向SDA确认,数据传输设备必须用停止状态来终止写操作。

EEPROM进入一个内计时固定存储器写周期,在该写周期,所以的输入被禁止,EEPROM直到写完才应答。

连续写

1KB/2KB EEPROM能进行8字节页面写入,4KB、8KB和16KB设备能进行16字节页面写入。激发写页面与激发写字节相同,只是数据传送设备无须在第一个字节随时钟输入之后,发出一个停止状态。在EEPROM确认收到第一个数据之后,数据传送设备能再传送7个(1KB、2KB)或15个(4KB、8KB、16KB)数据,每一个数据收到之后,EEPROM都将通过SDA回送一个确认信号,最后数据传送设备必须通过停止状态终止页面写序列。写页面时序如图3.18所示。
在这里插入图片描述

void iic_24c02_write(unsigned char *pucBuf,unsigned char ucAddr,unsigned char ucNum)
{
    I2CStart();I2CSendByte(0xa0); // 器件地址I2CWaitAck();I2CSendByte(ucAddr);  // 写数据地址I2CWaitAck();while(ucNum--){
    I2CSendByte(*pucBuf++);I2CWaitAck();}I2CStop();delay1(500);
}

数据字地址的低3位(1KB、2KB)或低4位(4KB、8KB、16KB)在收到每个数据字后,内部自动加1数据字地址的高位字节保持不变,以保持存储器页地址不变

如果传送到EEPROM中的数据字超过8(1KB、2KB)或16 (4KB、8KB、16KB)字节,数据字地址将重复滚动,以前的数据将被覆盖

3.读操作

除了器件地址码中的读/写选择位置1,读操作与写操作是一样的。读操作有三种:立即地址读取,随机地址读取和顺序读取

立即地址读取
在这里插入图片描述
内部数据字地址指针保持在读写操作中最后访问的地址,按“1”递增

只要芯片保持上电,该地址在两个操作之间一直有效,如果最后一个操作是在地址n处读取,则立即地址是n+1;如果最后操作是在地址n处写入,则立即地址也是n+1。

随机地址读取:
在这里插入图片描述
随机地址读取时序如图所示。随机读取需要一个空字节写序列来载入数据地址,一旦器件地址码和数据码地址码时钟输入,并被EEPROM确认,数据传送设备就必须产生另一个开始条件

读/写选择位处于高电平时,通过送出一个器件地址,数据传送设备激发出一个立即寻址读取,EEPROM确认器件地址,并随时钟串行输出数据。器件读数据不通过确认(使SDA总线处于高电平)应答,而通过产生一个停止条件应答。

顺序读取
在这里插入图片描述

顺序读取时序如图所示。顺序读取由立即地址读取或随机地址读取激发,在读数据器件收到一数据码之后,通过确认应答,只要EEPROM收到确认之后,便会继续增加数据码地址及串行输出数据码。当达到存储器地址极限时,数据码地址将重复滚动,顺序读取将继续。当读数据器件不通过确认(使SDA总线处于高电平)应答,而通过产生一个停止条件应答时,顺序读取操作被终止。

随机读取程序


// 开始是以写的方式,传入从机地址(假写)
void iic_24c02_read(unsigned char *pucBuf,unsigned char ucAddr,unsigned char ucNum)
{
    I2CStart();I2CSendByte(0xa0); // 器件地址(写)I2CWaitAck();I2CSendByte(ucAddr);  // 写数据地址I2CWaitAck();I2CStart();I2CSendByte(0xa1); // 读数据while(ucNum--){
    *pucBuf++ = I2CReceiveByte();if(ucNum) // 没有接收完I2CSendAck();elseI2CSendNotAck();}I2CStop();
}

注:只有随机读取过程有一个假写过程

四、MCP4017可编程电阻

1.概况

内部结构
在这里插入图片描述
电阻的计算:Rs的阻值为 AB之间的总电阻除以127,其中Rw的阻值几乎为零,可以忽略不计。N为我们写入的数据。RAB为常量,可以根据数据手册查找
在这里插入图片描述
相当于每增加一个数,电阻增加787.402欧

从机器件的地址
在这里插入图片描述
前面几位都是固定的:0101 111(r/w)

原理图:
在这里插入图片描述

2.读\写动作

读一个字节
在这里插入图片描述

void write_resistor(uint8_t value)
{
    I2CStart();I2CSendByte(0x5E);I2CWaitAck();I2CSendByte(value);I2CWaitAck();	I2CStop();	
}

写一个字节
在这里插入图片描述

uint8_t read_resistor(void)
{
    uint8_t value;I2CStart();I2CSendByte(0x5F);I2CWaitAck();value = I2CReceiveByte();I2CSendNotAck();	I2CStop();	return value;
}

注:读写时地址不一样
写进去的一个数字(0-127),读出来也是一个数字
转化为电阻阻值:R = 787.4 * read_resistor 欧
电压:3.3*(R/(R+10k)) (假设外接的电压为3.3)


总结

提示:这里对文章进行总结: