51单片机学习笔记——IIC和SPI总线

一、总线

总线(Bus)是计算机各种功能部件之间传送信息的公共通信干线,它是由导线组成的传输线束, 按照计算机所传输的信息种类,计算机的总线可以划分为数据总线、地址总线和控制总线,分别用来传输数据、数据地址和控制信号。

内总线,又称系统总线或板级总线,它是计算机各功能部户之间的传输通路,微型计算机总线通常称为内总线。外总线,又称通信总线,它是计算机系统之间,或者是计算机主机与外围设备之间的传输通路。摘自总线_百度百科

通俗的说,总线是一种规定好的通信形式,内总线是指CPU与其他芯片的通信,如I^2^C,SPI,PCI-e;外总线是计算机与其他设备连接的通信,如SATA,USB。

当然,使用哪种总线形式需要根据使用场景来选择。根据不同的传输速率、传输距离、设备成本来选择总线。在51单片机与其他模块进行通信时,经常采用I^2^C和SPI两种串行通信方式传输数据。

二、I^2^C总线

I^2^C总线概况

I^2^C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。摘自I2C_百度百科

特征 参数 解释
线制 两线制 时钟线SCL,数据线SDA
传输速率 400k 快速模式最高可达400k
传输距离 小于5m 最好不要超过30cm,否则信号会被干扰
时钟信号 同步通信 收发双方具有同频同相的同步时钟信号
数据信号 串行通信 -
信号类型 单端输入 便宜,方便,抗干扰能力差
传送方向 半双工 数据可以在两个方向上传输,但是不能同时传输
  • I^2^C支持主从机之间双向通信,因此在数据传输之前要进行寻址。
  • I^2^C支持多主机通信,因此需要进行冲突检测和仲裁。

I^2^C总线典型接法

IIC总线结构图
SDA和SCL两条线分别接了一个上拉电阻,说明闲时为高电平,有信号时为低电平。

I^2^C总线通信时序图

一次I^2^C总线通信的流程大致可分为:

  1. 发送启动信号
  2. 发送寻址信号
  3. 接收应答信号
  4. 发送数据信号
  5. 接收应答信号
  6. 发送结束信号
    IIC总线通信格式

注:根据I^2^C总线规定,部分要求高电平/低电平持续时间在5us左右,因此以下代码中的Delay()函数都是延时10us。

1. 启动信号

I^2^C总线协议规定,在SCL为高电平期间,产生SDA下降沿为启动信号。

1
2
3
4
5
6
7
8
9
10
11
void IIC_Start()	//总线启动信号
{
SDA=1;
Delay(); //延时约10us左右即可
SCL=1; //时钟线为高电平期间
Delay(); //建立时间是SDA保持时间>4.7us
SDA=0; //数据线产生一个下降沿信号
Delay(); //保持时间是>4us
SCL=0; //时钟线拉低,准备发送数据
Delay();
}
2. 发送数据

I^2^C总线规定,在时钟信号位高电平期间,数据线要求必须保持稳定,在时钟信号在低电平期间,数据线上的电平才允许变化。
IIC总线有效性规定
应答信号

根据函数的封装规则(高内聚低耦合),可以把发送数据和接收应答信号两个功能防到一个函数中。以下为普中科技的I^2^C总线发送数据的源码,代码写的非常优美,仅略作修改方便理解。
该函数功能是向I^2^C总线上的设备发送一个字节数据,参数为需要发送的数据,返回值用于判断是否发送成功;发送成功为1,发送失败为0。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
unsigned char IIC_WriteByte(unsigned char dat)
{
unsigned char i=0; //循环变量
unsigned char count=0; //最大255,一个机器周期为1us,最大延时255us
for(i=0;i<8;i++) //要发送8位,从最高位开始
{
//起始信号之后SCL=0,所以可以直接改变SDA信号
SDA=dat>>7; //这里设计由char类型到bit类型的转换,SDA只能读取dat最低位 因此右移7
dat=dat<<1; //将下一次要发送的数据传到最高位
Delay();
SCL=1;
Delay(); //建立时间>4.7us
SCL=0;
Delay(); //建立时间>4us
}
SDA=1;
Delay();
SCL=1; //两个线都拉高,表示总线空闲,等待应答信号
while(SDA) //等待应答,也就是等待从设备把SDA拉低
{
count++;
if(count>200) //如果超过200us没有应答发送失败,或者为非应答,表示接收结束
{
SCL=0;
Delay();
return 0; //返回0,表示发送失败
}
}
SCL=0;
Delay();
return 1; //返回1,表示发送成功
}
  • 关于CY位的问题

在郭天祥的书中,是通过状态寄存器PSW来发送的信号。将要发送的数据左移(temp=temp<<1),会移入PSW寄存器的最高位CY,再将CY中的值赋给SDA(SDA=CY)。
在查阅了相关资料后发现,CY位来源于最近一次算术指令或逻辑指令执行时软硬件的改写,表示加法运算中有进位或减法运算中有借位则CY位置为1,否则为0。
通俗来说,在上述情景I^2^C通信中,CY暂存了temp=temp<<1这句中被位移出去的最高位;如果temp=temp>>1,那么CY位暂存被位移出去的最低位。而所谓的加法进位减法借位,与计算机的补码储存方式有关,通过CY位能实现相应的加减法算法。

3. 接收数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
unsigned char IIC_ReadByte()
{
unsigned char i=0; //循环变量
unsigned char dat=0;//用于接收传送的数据
SDA=1; //起始和发送一个字节之后SCL都是0
Delay();
for(i=0;i<8;i++) //接收8个字节
{
SCL=1;
Delay();
dat<<=1; //dat左移一位
dat|=SDA; //同样涉及bit类型与char类型的强转,最低位与SDA按位取与后赋值
Delay();
SCL=0;
Delay();
}
return dat;
}
4. 结束信号

IIC结束信号

I^2^C总线规定,SCL为高电平期间,SDA产生一个上升沿为终止信号。

1
2
3
4
5
6
7
8
9
void IIC_Stop()		//总线结束信号
{
SDA=0;
Delay();
SCL=1;
Delay(); //建立时间>4.7us
SDA=1;
Delay();
}

AT24C02

几种常用I^2^C通信的模块有:

  1. AT24C02,ATMEL公司生产2K位串行CMOS EEPROM,内部含有256个8位字节。EEPROM,是指带电可擦可编程只读存储器,一种掉电后数据不丢失的存储芯片,用户可以随意修改,擦写。
  2. ESP8266,WIFI模块,部分采用I^2^C通信。
  3. SSD1306,OLED模块,部分采用I^2^C通信。
1.AT24C02引脚图

AT24C02引脚图

引脚 名称 解释
1-3 A0-A2 可编程地址输入端
4 GND 接地端
5 SDA 数据信号线
6 SCL 时钟信号线
7 WP 写保护输入端
8 Vcc 电源端
2. 芯片总线寻址

AT24C02的芯片地址为1010, 其地址控制字格式为。

位序号 D7 D6 D5 D4 D3 D2 D1 D0
控制字格式 1 0 1 0 A2 A1 A0 R/W

其中A2,A1,A0为可编程地址选择位。A2,A1,A0引脚接高、低电平后得到确定的三位编码,与1010形成7位编码,即为该器件的地址码。R/W为读写控制位,该位为0,表示对芯片进行写操作;该位为1,表示对芯片进行读操作。
如果A2,A1,A0引脚接低电平时候,发送数据地址为A0,接收数据地址为A1。

3. 片内寻址

AT24C02的存储容量为2KB,内部分成32页,每页8B,共256B,芯片寻址可对内部256B中的任一个进行读/写操作,其寻址范围为00~FF,共256个寻址单元。

4. 读/写操作时序

串行EEPROM有字节写入,页写入,指定地址读操作,指定页读操作。

以下伪代码假设AT24C02地址为1010 000X。

  1. 字节写入模式流程

IIC字节写入模式

1
2
3
4
5
IIC_Start();//发送起始信号
IIC_WriteByte(0xA0);//发送寻址信号
IIC_WriteByte(addr);//发送需要写入的片内地址
IIC_WriteByte(date);//发送需要在addr写入的信息
IIC_Stop(); //结束本次发送
  1. 页写入模式流程

每次写入数据之后,地址指针会增加,因此可以连续写入。
IIC页写入模式

1
2
3
4
5
6
7
8
9
10
IIC_Start();//发送起始信号
IIC_WriteByte(0xA0);//发送寻址信号
IIC_WriteByte(addr);//发送需要写入的片内地址
IIC_WriteByte(date1);//发送需要在addr写入的信息
IIC_WriteByte(date2);//发送需要在addr+1写入的信息
.
.
.
IIC_WriteByte(dateN);//发送需要在addr+n写入的信息
IIC_Stop(); //结束本次发送

需要注意的是,n最大为7,因为单片机在一个数据周期内,只能访问一页(8个)储存单元。
相对于字节写入模式,速度较快。

  1. 指定地址读取字节模式流程

IIC字节读取模式

1
2
3
4
5
6
7
IIC_Start();		//发送起始信号
IIC_WriteByte(0xA0);//发送写命令
IIC_WriteByte(addr);//发送需要写入的片内地址
IIC_Start(); //发送起始信号
IIC_WriteByte(0xA1);//发送读命令
date=IIC_ReadByte();//接受数据
IIC_Stop(); //结束本次发送
  1. 指定地址读取页模式流程

IIC页读取模式

1
2
3
4
5
6
7
8
9
10
11
12
IIC_Start();		//发送起始信号
IIC_WriteByte(0xA0);//发送写命令
IIC_WriteByte(addr);//发送需要写入的片内地址
IIC_Start(); //发送起始信号
IIC_WriteByte(0xA1);//发送读命令
date1=IIC_ReadByte();//接受数据
date2=IIC_ReadByte();//接受数据
.
.
.
dateN=IIC_ReadByte();
IIC_Stop(); //结束本次发送

注:一般使用AT24C02储存数据,使用I^2^C总线传输是为了节约IO口,而不是追求传输速率,为了数据稳定起见,尽量采用字节传输方式。

三、SPI总线

1. 概况
特征 参数 解释
线制 四线制 MISO,MOSI,SCLK,CS
传输速率 1-25M不等 与主机晶振频率和收发双方的处理速度有关
传输距离 小于5m 最好不要超过30cm,否则信号会被干扰
时钟信号 同步通信 收发双方具有同频同相的同步时钟信号
数据信号 串行通信 -
信号类型 单端输入 便宜,方便,抗干扰能力差
传送方向 全双工 数据可以同时双向传输

需要注意的是,SPI总线没有应答机制,贸然提高传输速率可能会导致接收方缓冲区数据未处理,造成数据丢失。

传输线名称 解释
SCLK/CK/SLK 时钟信号,只能由主设备发出
MOSI/SDIN 主设备数据输出/从机输入端
MISO/SDOUT 主设备数据输入/从机输出端
CS/SS 使能信号/片选信号
2. 时序

简单概况SPI总线的时序为:时钟线上升沿发送、下降沿接收、高位先发送。

3. 发送和接收数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
typedef unsigned int u16;	  
typedef unsigned char u8;
sbit DOUT = P3^7; //输出
sbit SCLK = P3^6; //时钟
sbit DIN = P3^4; //输入
sbit CS = P3^5; //片选
void SPI_Write(u8 dat)//写数据
{
u8 i;
SCLK = 0;
for(i=0; i<8; i++)
{
DIN = dat >> 7; //放置最高位
dat <<= 1; //移位,把下一次需要写入的数据放到最高位
SCLK = 0; //上升沿放置数据
SCLK = 1;
}
}
u8 SPI_Read(void)
{
u8 i,dat=0; //存放需要接收的数据
SCLK = 0;
for(i=0; i<8; i++) //接收8位数据
{
dat <<= 1;
SCLK = 1;
SCLK = 0; //时钟信号下降沿读取数据
dat |= DOUT; //最低位赋值
}
return dat;
}
  • 关于片选CS
    在双机通信时,部分设备片选CS端可以接地。部分设备不允许接地,需要检测信号变化。在设计电路时,要仔细阅读芯片手册。多机通信时,可以拓展CS的IO口数量(如CS1,CS2,CS3等)进行多机通信。
4. 几种常用SPI通信的模块有:
  1. DS1302,时钟模块。
  2. SSD1306,OLED模块,部分使用SPI通信。
  3. SPI flash,flash储存设备。

51单片机学习笔记——IIC和SPI总线
http://blog.mingxuan.xin/2020/06/25/20200625/
作者
Obscure
发布于
2020年6月25日
许可协议