251单片机——I2C 总线

Posted 叫我谢布斯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了251单片机——I2C 总线相关的知识,希望对你有一定的参考价值。

本人使用的51开发板为 郭天祥C51 TX-1C开发板 ;
本笔记根据B站up主:江科大自化协的教学视频 整理得到
参照博客 https://zouchanglin.cn/2458978170.html

I2C 总线


I2C 是Inter-Integrated Circuit 的简称,I2C 是由 Philips 公司开发的一种通用数据总线,其中包括两根通信线:串行数据线:SDA,及串行时钟线:SCL。I2C 通信的主要特征是同步、半双工,并且带数据应答。通用的 I2C 总线,可以使各种设备的通信标准统一,对于厂家来说,使用成熟的方案可以缩短芯片设计周期、提高稳定性,对于应用者来说,使用通用的通信协议可以避免学习各种各样的自定义协议,降低了学习和应用的难度。

I2C主要应用场景就是SOC和周边外设间的通信(如:EEPROM,电容触摸芯片,各种Sensor等)。

I2C 电路规范


所有 I2C 设备的 SCL 连在一起,SDA 连在一起;设备的 SCL 和 SDA 均要配置成开漏输出模式;SCL 和 SDA 各添加一个上拉电阻,阻值一般为 4.7KΩ 左右;开漏输出和上拉电阻的共同作用实现了“线与”的功能,此设计主要是为了解决多机通信互相干扰的问题。下面是 I2C 总线挂接多个设备示意图:

I2C 总线内部结构图:

I2C 使用一个 7bit 的设备地址,一组总线最多和 112 个节点通信。最大通信数量受限于地址空间及 400pF 的总线电容。常见的 I2C 总线以传输速率的不同分为不同的模式:标准模式(100Kbit/s)、低速模式(10Kbit/s)、快速模式(400Kbit/s)、高速模式(3.4Mbit/s),时钟频率可以被下降到零,即暂停通信。

该总线是一种多主控总线,即可以在总线上放置多个主设备节点,在停止位(P)发出后,即通讯结束后,主设备节点可以成为从设备节点。主设备节点 就是产生时钟并发起通信的设备节点;从设备节点 就是接收时钟并响应主设备节点寻址的设备节点。

总的来说 I2C 通信的主要特点如下:

1、I2C 通信双方地位不对等,通信由主设备发起,并主导传输过程,从设备按 I2C 协议接收主设备发送的数据,并及时给出响应。

2、主设备、从设备由通信双方决定,既能当主设备,也能当从设备(需要软件进行配置)。

3、主设备负责调度总线,决定某一时刻和哪个从设备通信。在同一时刻,I2C 总线上只能有一对主设备、从设备通信。

4、每个 I2C 从设备在 I2C 总线通讯中有一个 I2C 从设备地址,该地址具有唯一性,是从设备的固有属性,通信中主设备通过从设备地址来找到从设备,可以理解为网卡Mac地址。

I2C 时序结构


起始条件:SCL 高电平期间,SDA 从高电平切换到低电平。

终止条件:SCL 高电平期间,SDA 从低电平切换到高电平。

发送一个字节:SCL 低电平期间,主机将数据位依次放到 SDA 线上(高位在前),然后拉高 SCL,从机将在 SCL 高电平期间读取数据位,所以 SCL 高电平期间 SDA 不允许有数据变化,依次循环上述过程 8 次,即可发送一个字节。

接收一个字节:SCL 低电平期间,从机将数据位依次放到 SDA 线上(高位在前),然后拉高 SCL,主机将在 SCL 高电平期间读取数据位,所以 SCL 高电平期间 SDA 不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放 SDA)。

发送应答:在接收完一个字节之后,主机在下一个时钟发送一位数据,数据 0 表示应答,数据 1 表示非应答

接收应答:在发送完一个字节之后,主机在下一个时钟接收一位数据,判断从机是否应答,数据 0 表示应答,数据 1 表示非应答(主机在接收之前,需要释放 SDA)。

I2C 数据帧


发送一帧数据,解决的问题是向谁发什么:

接收一帧数据,向谁收什么:

先发送再接收数据帧(复合格式),解决的问题是向谁收指定的什么:

C51 的 I2C 操作封装

// I2C.h

#ifndef _I2C_H_
#define _I2C_H_

void I2C_Start(void);
void I2C_Stop(void);
void I2C_SendByte(unsigned char Byte);
unsigned char I2C_ReceiveByte(void);
void I2C_SendAck(unsigned char AckBit);
unsigned char I2C_ReceiveAck(void);

#endif
//I2C.c

#include "I2C.h"
#include <REGX52.H>

sbit I2C_SCL = P2^1;
sbit I2C_SDA = P2^0;

//起始条件:SCL高电平期间,SDA从高电平切换到低电平
void I2C_Start(void)

    I2C_SDA = 1;
    I2C_SCL = 1;
    I2C_SDA = 0;
    I2C_SCL = 0;


//终止条件:SCL高电平期间,SDA从低电平切换到高电平
void I2C_Stop(void)

    I2C_SDA = 0;
    I2C_SCL = 1;
    I2C_SDA = 1;


void I2C_SendByte(unsigned char Byte)

    unsigned char i;
    for(i = 0; i < 8; i++)
    
        I2C_SDA = Byte & (0x80 >> i);   //高电平期间不允许有电平变化
        I2C_SCL = 1;            
        I2C_SCL = 0;
    


unsigned char I2C_ReceiveByte(void)

    unsigned char i, Byte = 0x00;
    
    I2C_SDA = 1;
    
    for(i = 0; i < 8; i++)
    
        I2C_SCL = 1;                    //高电平才能读取
        if(I2C_SDA)     
        
            Byte |= (0x80 >> i);
        
        I2C_SCL = 0;
    
    
    return Byte;


void I2C_SendAck(unsigned char AckBit)

    I2C_SDA = AckBit;
    I2C_SCL = 1;
    I2C_SCL = 0;


unsigned char I2C_ReceiveAck()

    unsigned char AckBit;
    I2C_SDA = 1;
    I2C_SCL = 1;
    AckBit = I2C_SDA;
    I2C_SCL = 0;
    return AckBit;

AT24C02存储器


存储器分类


AT24C02简介


AT24C02 是一种可以实现掉电不丢失的存储器,可用于保存单片机运行时想要永久保存的数据信息,其存储介质:E2PROM。通讯接口是 I2C 总线,容量 256 字节。

存储器简化模型:

AT24C02 引脚及应用电路:

AT24C02 数据帧


字节写:在WORD ADDRESS处写入数据DATA

随机读:读出在WORD ADDRESS处的数据DATA

AT24C02 的固定地址为 1010,可配置地址本开发板上为 000。所以 SLAVE ADDRESS+W为0xA0,SLAVE ADDRESS+R为0xA1。

字节写:在”字地址”处写入”数据”

随机读:读出在”字地址”处的”数据”

I2C操作AT24C02示例


依托于之前封装的I2C的代码,下面是AT24C02.h

//AT24C02.h

#ifndef _AT24C02_H_
#define _AT24C02_H_

#include "I2C.h"

void AT24C02_WriteByte(unsigned char WordAddress, unsigned char Data);
unsigned char AT24C02_ReadByte(unsigned char WordAddress);

#endif
//AT24C02.c

#include <REGX52.H>
#include "AT24C02.h"


#define AT24C02_ADDRESS  0xA0

void AT24C02_WriteByte(unsigned char WordAddress, unsigned char Data)

    I2C_Start();
    I2C_SendByte(AT24C02_ADDRESS);
    I2C_ReceiveAck();
    I2C_SendByte(WordAddress);
    I2C_ReceiveAck();
    I2C_SendByte(Data);
    I2C_ReceiveAck();
    I2C_Stop();


unsigned char AT24C02_ReadByte(unsigned char WordAddress)

    unsigned char Data;
    I2C_Start();
    I2C_SendByte(AT24C02_ADDRESS);
    I2C_ReceiveAck();
    I2C_SendByte(WordAddress);
    I2C_ReceiveAck();
    I2C_Start();
    I2C_SendByte(AT24C02_ADDRESS | 0x01);
    I2C_ReceiveAck();
    Data = I2C_ReceiveByte();
    I2C_SendAck(1);
    I2C_Stop();
    return Data;

//main.c

#include <REGX52.H>
#include "lcd1602.h"
#include "AT24C02.h"
#include "delay.h"
 
 unsigned char m_temp;
 
void main(void)

    LCD_Init();
    LCD_ShowString(1, 1, "Hello");
    AT24C02_WriteByte(2, 120);
    delay_ms(5);
    m_temp = AT24C02_ReadByte(2);
    LCD_ShowNum(2, 1, m_temp, 3);
    while(1)
    
        
    

以上是关于251单片机——I2C 总线的主要内容,如果未能解决你的问题,请参考以下文章

51单片机对I2C总线上挂接多个AT24C02的读写操作+Proteus仿真

51单片机基于I2C总线的秒表模拟应用

BMP280 driver对接单片机I2C或者SPI总线接口

I2C总线

I2C总线

E2PROM芯片的特点及作用,总线