I2C通信;UART(串口)通信

本文深入解析了I2C总线的工作原理,包括起始与停止信号、数据有效条件及字节读写操作。并通过具体实例介绍了如何使用I2C总线对EEPROM进行页写入(PageWrite)和随机读取(RandomRead),提供了详细的代码实现。

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

本文的原作者链接http://www.51hei.com/bbs/dpj-41478-1.html

概述

I2C总线是内部总线,用来连接系统内部的芯片,如MCU与存储器、按键、LCD等;采用MSB(先发送高位)

串行总线,只有两根双向信号线:时钟线SCL(标准I2C的SCL频率为100KHz)、数据线SDA。

I2C总线通过上拉电阻接正电源。总线空闲时,两根线为高电平,连接到总线上的任意器件输出低电平都能将总线的信号线变低,即各器件的SCL、SDA都是“线与”关系。

每个接到I2C总线上的器件都有唯一的地址。单主机与其他器件之间通信方向固定无需仲裁;而在多主机系统中,为避免几个主机启动总线时产生混乱,I2C需要总线仲裁。

时序图

起始信号:SCL线为高电平期间,SDA线由高电平向低电平变化。

void IIC_Start(void)
{
    IIC_SDA_Write(1);        //SDA引脚置1
    IIC_SCL_Write(1);        //SCL引脚置1
    Delay1Us(5);             //延时5us  
    IIC_Touch_SDA_Write(0);  //SDA引脚置0
    Delay1Us(5);             //延时5us 
    IIC_Touch_SCL_Write(0);  //SCL引脚置0
    Delay1Us(5);             //延时5us 
}

停止信号:SCL线为高电平期间,SDA线由低电平向高电平变化。

void IIC_Stop(void)
{
    IIC_SCL_Write(1);    //SCL引脚置1
    IIC_SDA_Write(0);    //SDA引脚置0
    Delay1Us(5);         //延时5us
    IIC_SDA_Write(1);    //SDA引脚置1
    Delay1Us(5);         //延时5us
}

数据有效:SCL线为高电平期间,数据线上的数据必须保持稳定,只有在SCL线为低电平期间,数据线上的数据才允许变化。

写字节操作

/***********字节写*************/
char IIC_WriteByte(char data)
{
    char i,ret;
    for(i=0; i<8; i++)
    {
        if((data << i) & 0x80)    //data循环左移8次与0x80相与
            IIC_SDA_Write(1);     //SDA引脚置1
        else
            IIC_SDA_Write(0);     //SDA引脚置0
        //数据线上的SDA只有SCL为低电平期间变化
        Delay1Us(4);
        IIC_SCL_Write(1);        //SCL引脚置1
        Delay1Us(5);
        IIC_SCL_Write(0);        //SCL引脚置0
        Delay1Us(4);
    }
    ret = IIC_SDA_Read();        //返回SDA引脚上的值,便于后期辨别从机发送的ACK,NACK
    Delay1Us(4);
    IIC_SCL_Write(1);
    Delay1Us(4);
    IIC_SCL_Write(0);
    Delay1Us(4);
    return ret;
}

读字节操作

/***********字节读*************/
char IIC_ReadByte(void)
{
    char i ,ret=0;
    IIC_SDA_Write(1);
    IIC_SCL_Write(0);
    Delay1Us(4);
    
    for(i=0; i<8; i++)
    {
        IIC_SCL_Write(0);
        Delay1Us(4);
        IIC_SCL_Write(1);
        ret <<= 1;                //先左移1位
        ret += IIC_SDA_Read();    //后加SDA引脚的数值
        Delay1Us(4);
        
    }
    IIC_SCL_Write(0);
    Delay1Us(4);
    return ret;    //返回读取的字节
}

字节传送

传送的每一个字节后必须跟随一位应答位(即一帧共有9位)。

应答:ACK,低电平"0"

非应答:NACK,高电平"1"

 

/******************************************************************************************************/

2020.3.1补充  :只关注其原理而不去尝试敲代码实现,留下的只有空白。

EEPROM的IIC读写应用

EEPROM是在单片机开发中常用到的存储设备,其用到的读写通信方式就是IIC,这里针对其常用的读写方式Page Write & Random Read进行代码编写。

Page Write

/*****************************************************************
****函数变量介绍: *buf  --写数据指针
                  addr  --EEPROM地址
                  reg   --指定EEPROM的内部地址
                  cnt   --写数据的长度                      
******************************************************************/
void IIC_Tx(char *buf, char addr, char reg, char cnt)
{
    char i;
    IIC_Start();
    //发送device address
    if(IIC_WriteByte(addr<<1)==IIC_NACK)
    {

    }
    Delay1Us(4);
    //发送word address
    if(IIC_WriteByte(reg)==IIC_NACK)
    {

    }
    Delay1Us(4);
    //发送写数据
    for(i=0; cnt>0; i++,cnt--)
    {
	    if(IIC_WriteByte(*(buf+i))==IIC_NACK);//发送完最后一个字节后,从机发送NACK信号
	        Delay1Us(4);
    }
    IIC_Stop();
}

Random Read

/*********************************************************
******变量说明   *buf  --读数据指针
                 addr  --EEPROM地址
                 reg   --word address
                 cnt   --要读数据的长度
*********************************************************/
void IIC_Rx(char *buf, char addr, char reg, char cnt)
{
    IIC_Start();
    //发送device address
    if(IIC_WriteByte(addr<<1)==IIC_NACK)
    {

    }
    Delay1Us(4);
    //发送word address
    if(IIC_WriteByte(reg)==IIC_NACK)
    {

    }
    Delay1Us(4);
    IIC_Start();
    //发送device address
    if(IIC_WriteByte(addr<<1|1)==IIC_NACK)
    {

    }
    Delay1Us(4);
    //读取数据
    for(; cnt>0; buf++,cnt--)
    {
        *buf = IIC_ReadByte();
        if(cnt==1)
            IIC_SDA_Write(IIC_NACK);//读到最后一个字节,MCU发送NACK信号
        else
            IIC_SDA_Write(IIC_ACK);
	Delay1Us(4);
    }
    IIC_Stop();
}

UART(串口通信)

起始位:"0"

数据位:有多种选择,常用的是8位(8bit=1byte)

奇偶校验位:奇校验或者偶校验

停止位:"1"

停止位:"1"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值