12 .IIC协议(51单片机和C语言模拟I2C协议)

一:什么是i2c

1.1 协议概述

IIC全称Inter-Integrated Circuit (集成电路总线)
是由PHILIPS公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备。IIC属于半双工同步通信方式.

1.2 特点

简单性和有效性。

由于接口直接在组件之上,因此IIC总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。总线的长度可高达25英尺,并且能够以10Kbps的最大 传输速率支持40个组件

多主控(multimastering)

其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。

1.3 构成

IIC串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL,其时钟信号是由主控器件产生。所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。对于并联在一条总线上的每个IC都有唯一的地址。
在这里插入图片描述

二 如何实现I2C

I2C包括起始信号,终止信号,和应答信号 。其中起始信号是不可缺的

2.1 起始信号

在这里插入图片描述
通过起始信号时序图,我们可以看出。在虚线框之内,SCL始终为高电平。
而SDA是高到低一个电平的跳转。SDA高电平时间持续大于4.7us,低电平持续时间大于4us。

void IIC_start ()
{
   scl = 1;//首先将scl拉高
   sda = 1//拉高sda
   Delay5us();//SDA高电平时间持续大于4.7us
   sda = 0;//低电平持续时间大于4us。
   Delay5us();	
}

2.2 终止信号

在这里插入图片描述
通过终止信号时序图,我们可以看出。在虚线框之内,SCL始终为高电平。
而SDA是低到高一个电平的跳转。SDA高电平时间持续大于4.7us,低电平持续时间大于4us。

void IIC_stop ()
{
   scl = 1;//首先将scl拉高
   sda = 0//拉低sda
   Delay5us();//SDA高电平时间持续大于4.7us
   sda = 1;//低电平持续时间大于4us。
   Delay5us();	
}

2.3 应答信号 (ack)

在这里插入图片描述
发送器每发送一个字节(8个bit),就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。
应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字
节;
应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。

char IIC_ack()
{
   char flag;//建立一个标志位,来获取sda
   sda = 1;释放数据线
   Delay5us();
   scl = 1;
   Delay5us();
   flag = sda;
   Delay5us();
   scl = 0;
   Delay5us();   
}

2.4 发送字节

在这里插入图片描述

根据时序图可以看出,当scl为高电平时发送数据。sda发送的数据可以为0或1.但sda数据线高低电平变化不能发生在SCL高电平期间,否则设备将会认为终止信号或起始信号。

void IIC_send_byte (char sendata)
{
   int i;//没执行发送一位,发送八次为一个字节
   for(i=0;i<8;i++){
      scl = 0;
      _nop_();//调用一个空函数 时间为5微秒
      sda = sendata & 0x80;//获取最高位 1000 0000
      _nop_();
      scl = 1;
      _nop_();
      scl = 0;
      _nop_();
      sendata = sendata << 1;左移一位
   }
}

三 总结

经过三个函数的封装,就可以使用I2C协议。配合设备时序图,就可以完成IIC通信。下一节将IIC和oled配合使用.
oled部分:oled详细教程

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是51单片机完整的IIC读取和发送C语言程序的示例代码: ```c #include <reg52.h> sbit SDA = P2^0; //定义SDA数据线引脚 sbit SCL = P2^1; //定义SCL时钟线引脚 void delay() { int i = 1000; while(i--); } void IIC_Start() { SDA = 1; SCL = 1; delay(); SDA = 0; delay(); SCL = 0; } void IIC_Stop() { SDA = 0; SCL = 1; delay(); SDA = 1; delay(); } void IIC_Ack() { SDA = 0; delay(); SCL = 1; delay(); SCL = 0; delay(); SDA = 1; } void IIC_NAck() { SDA = 1; delay(); SCL = 1; delay(); SCL = 0; delay(); } unsigned char IIC_WriteByte(unsigned char dat) { unsigned char i; for(i=0; i<8; i++) { SDA = dat & 0x80; delay(); SCL = 1; delay(); SCL = 0; dat <<= 1; } delay(); SDA = 1; delay(); SCL = 1; delay(); i = SDA; SCL = 0; return i; } unsigned char IIC_ReadByte() { unsigned char i; unsigned char dat = 0; SDA = 1; for(i=0; i<8; i++) { SCL = 1; delay(); dat <<= 1; dat |= SDA; SCL = 0; delay(); } return dat; } void IIC_Init() { SDA = 1; SCL = 1; delay(); } void main() { unsigned char dat; IIC_Init(); IIC_Start(); IIC_WriteByte(0xA0); IIC_Ack(); IIC_WriteByte(0x00); IIC_Ack(); IIC_Stop(); IIC_Start(); IIC_WriteByte(0xA1); IIC_Ack(); dat = IIC_ReadByte(); IIC_NAck(); IIC_Stop(); while(1); } ``` 这段代码实现了51单片机通过IIC总线读取和发送数据的功能。其中,IIC_Start()函数用于产生起始信号,IIC_Stop()函数用于产生停止信号,IIC_Ack()和IIC_NAck()函数分别用于产生应答和非应答信号,IIC_WriteByte()和IIC_ReadByte()函数分别用于发送和接收一个字节的数据。在main函数中,我们首先初始化IIC总线,然后发送一个写命令,接着发送一个要写入的地址,再停止总线,接着再发送一个读命令,最后接收一个字节的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pg_hj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值