【嵌入式】串行通信协议总结:UART,SPI,IIC,CAN

文章目录

  • 前言
  • 参考链接
  • UART
  • SPI
    • 参考资料
    • 概述
  • IIC
    • 参考链接
    • 总结
    • C51实现
  • CAN

前言

  随着半导体技术的发展,数据传输速度逐渐增加,随之而来的是串行通信基本取代了并行通信,因此,了解常用的串行通信协议对于嵌入式开发来说非常有必要,这里总结一些用过的串行通信协议,重点在于其数据传输时序图

  由于看到很多CSDN大佬写的文章非常详细也非常全面,故而本文主要是总结链接,以及总结个人实践经验。

参考链接

  • 几个串口通信协议的整理 - CSDN
  • 【嵌入式物联网常用的通信协议UART、RS-232、RS-422、RS-485、CAN、IIC、SPI】- CSDN

UART

  所谓UART,即Universal Asynchronous Receiver / Transmitter,通用异步串行通讯,也就是我们日常说的串口。这种串口大部分的单片机都会有硬件支持,即可以很方便地传输数据。
  但是,如果外设数量较多,而且都是使用串口通讯的话,但单片机上内置的串口外设数量不够,怎么办呢?这个时候就需要用到模拟串口,也就是我们常说的软串口,所谓“软”,即没有硬件支持,而是通过一般的IO引脚模拟传输数据时的高低电平变化。然后按照设定的波特率来进行延时。
  具体参考参考这个链接,真的是讲得非常非常详细!

  附:UART接口与COM口的区别

SPI

参考资料

SPI通信协议(SPI总线)学习 - 博客园
SPI总线协议概述 - CSDN

概述

  简单来说,SPI传输协议就是通过主设备发生时钟,然后交换数据,不同的模式区别只在于数据是什么时候采样,什么时候锁存传输的,但是似乎目前大部分设备这一点都是设定好的,不能修改。

IIC

参考链接

  • 【STM32】IIC的基本原理(实例:普通IO口模拟IIC时序读取24C02)- CSDN
  • 浅谈I2C总线 - CSDN
  • [I2C]I2C总线协议图解 - 博客园

总结

  上面那几篇文章确实写得非常好,而且也非常详细,总结来说:

  • IIC协议为两线,属于半双工,即能发送接收数据,但不能同时进行。

  • IIC中的信号有三种:起始信号、停止信号、应答信号,分别对应不同的两线电平状态。

  • IIC协议传输数据时有起始位,停止位,其数据传输结构为:1位起始位、7位的器件地址(即向谁写入/读取数据)、1位读/写标识位、之后就是数据位(可以有多个字节)、1位停止位在最后,且每传输一个字节都有应答位
    【嵌入式】串行通信协议总结:UART,SPI,IIC,CAN_第1张图片
    在这里插入图片描述
    其中,深色代表主机发送的数据,浅色代表从机向主机发送的数据。

  • 高字节先写入

  • 数据的有效性:数据在时钟线SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。且要求数据传输过程中有一定的延时,如下图所示。
    【嵌入式】串行通信协议总结:UART,SPI,IIC,CAN_第2张图片

  • 有时候主机读入数据时,如果从机没有读入应答位的需求,则可以不加应答位。

C51实现

#include 

sbit SCL=P2^1;
sbit SDA=P2^0;

/*******************************************************************************
* 函数名         : Delay10us()
* 函数功能		   : 延时10us
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
void Delay10us()
{
	unsigned char a,b;
	for(b=1;b>0;b--)
		for(a=2;a>0;a--);

}

/*******************************************************************************
* 函数名         : I2cStart()
* 函数功能		 : 起始信号:在SCL时钟信号在高电平期间SDA信号产生一个下降沿
* 输入           : 无
* 输出         	 : 无
* 备注           : 起始之后SDA和SCL都为0
*******************************************************************************/
void I2cStart()
{
	SDA=1;
	Delay10us();
	SCL=1;
	Delay10us();//建立时间是SDA保持时间>4.7us
	SDA=0;
	Delay10us();//保持时间是>4us
	SCL=0;			
	Delay10us();		
}

/*******************************************************************************
* 函数名         : I2cStop()
* 函数功能		 : 终止信号:在SCL时钟信号高电平期间SDA信号产生一个上升沿
* 输入           : 无
* 输出         	 : 无
* 备注           : 结束之后保持SDA和SCL都为1;表示总线空闲
*******************************************************************************/
void I2cStop()
{
	SDA=0;
	Delay10us();
	SCL=1;
	Delay10us();//建立时间大于4.7us
	SDA=1;
	Delay10us();		
}

/*******************************************************************************
* 函数名         : I2cSendByte(unsigned char dat)
* 函数功能		 : 通过I2C发送一个字节。在SCL时钟信号高电平期间,保持发送信号SDA保持稳定
* 输入           : num
* 输出         	 : 0或1。发送成功返回1,发送失败返回0
* 备注           : 发送完一个字节SCL=0,SDA=1
*******************************************************************************/
unsigned char I2cSendByte(unsigned char dat)
{
	unsigned char a=0,b=0;//最大255,一个机器周期为1us,最大延时255us。		
	for(a=0;a<8;a++)//要发送8位,从最高位开始
	{
		SDA=dat>>7;	 //起始信号之后SCL=0,所以可以直接改变SDA信号
		dat=dat<<1;
		Delay10us();
		SCL=1;
		Delay10us();//建立时间>4.7us
		SCL=0;
		Delay10us();//时间大于4us		
	}
	SDA=1;
	Delay10us();
	SCL=1;
	while(SDA)//等待应答,也就是等待从设备把SDA拉低
	{
		b++;
		if(b>200)	 //如果超过2000us没有应答发送失败,或者为非应答,表示接收结束
		{
			SCL=0;
			Delay10us();
			return 0;
		}
	}
	SCL=0;
	Delay10us();
 	return 1;		
}

/*******************************************************************************
* 函数名         : I2cReadByte()
* 函数功能		   : 使用I2c读取一个字节
* 输入           : 无
* 输出         	 : dat
* 备注           : 接收完一个字节SCL=0,SDA=1.
*******************************************************************************/
unsigned char I2cReadByte()   //不产生应答位
{
	unsigned char a=0,dat=0;
	SDA=1;			//起始和发送一个字节之后SCL都是0
	Delay10us();
	for(a=0;a<8;a++)//接收8个字节
	{
		SCL=1;
		Delay10us();
		dat<<=1;
		dat|=SDA;
		Delay10us();
		SCL=0;
		Delay10us();
	}
	return dat;		
}

CAN

  

  

  

你可能感兴趣的:(嵌入式专栏,串行通信,UART,SPI,IIC,CAN)