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

一、总线

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

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

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

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

二、I2C总线

I2C总线概况

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

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

I2C总线典型接法

51单片机学习笔记——IIC和SPI总线_第1张图片
SDA和SCL两条线分别接了一个上拉电阻,说明闲时为高电平,有信号时为低电平。

I2C总线通信时序图

一次I2C总线通信的流程大致可分为:

  1. 发送启动信号
  2. 发送寻址信号
  3. 接收应答信号
  4. 发送数据信号
  5. 接收应答信号
  6. 发送结束信号
    51单片机学习笔记——IIC和SPI总线_第2张图片

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

1. 启动信号

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

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

I2C总线规定,在时钟信号位高电平期间,数据线要求必须保持稳定,在时钟信号在低电平期间,数据线上的电平才允许变化。
51单片机学习笔记——IIC和SPI总线_第3张图片
51单片机学习笔记——IIC和SPI总线_第4张图片

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

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。
通俗来说,在上述情景I2C通信中,CY暂存了temp=temp<<1这句中被位移出去的最高位;如果temp=temp>>1,那么CY位暂存被位移出去的最低位。而所谓的加法进位减法借位,与计算机的补码储存方式有关,通过CY位能实现相应的加减法算法。

3. 接收数据
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. 结束信号

51单片机学习笔记——IIC和SPI总线_第5张图片

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

void IIC_Stop()		//总线结束信号
{
	SDA=0;
	Delay();
	SCL=1;
	Delay();		//建立时间>4.7us
	SDA=1;
	Delay();		
}

AT24C02

几种常用I2C通信的模块有:

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

51单片机学习笔记——IIC和SPI总线_第6张图片

引脚 名称 解释
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. 字节写入模式流程

51单片机学习笔记——IIC和SPI总线_第7张图片

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

每次写入数据之后,地址指针会增加,因此可以连续写入。
51单片机学习笔记——IIC和SPI总线_第8张图片

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. 指定地址读取字节模式流程

51单片机学习笔记——IIC和SPI总线_第9张图片

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

51单片机学习笔记——IIC和SPI总线_第10张图片

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储存数据,使用I2C总线传输是为了节约IO口,而不是追求传输速率,为了数据稳定起见,尽量采用字节传输方式。

三、SPI总线

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

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

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

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

3. 发送和接收数据
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总线)