这篇文章主要介绍基本的驱动也是用的最多的协议类驱动中的SPI,I2C和UART。首先从最简单的UART也就是串口讲起:

1.UART

UART由两根线也就是TX,RX以及波特率产生器组成,操作比较简单,配置好后,就可以发送接收数据了,注意有的MCU需要接收数据时清除某些标记。如:

2.SPI

SPI一般有三根线组成即CLK,MOSI,MISO,数据输入和输出是单独的一根线。一般的操作都是先发控制指令,再发地址,接着才是数据。例:

3.I2C

I2C一般由两根线组成,即SDA,SCL,一根时钟线,一根数据线。关于I2C相关的开始信号,响应信号,停止信号时序见后面附录图片,这些信号一般都是通用封装好的,封装函数见附件(IO口模拟I2C)。

下面重点介绍I2C的使用操作,一般通信步骤是开始信号,从机地址+读或写标记,等待回应,发送数据,等待回应(接收数据,发送回应(最后一次接收则不发回应)),停止信号,代码示例:

最后,再总结与强调一下

SPI、I2C、UART三种串行总线协议的区别:

1,字面意思上:

SPI(Serial Peripheral Interface:串行外设接口); 
I2C(INTER IC BUS) 
UART(Universal Asynchronous Receiver Transmitter:通用异步收发器)

2.各总线的信号线:

SPI总线由三条信号线组成:串行时钟(SCLK)、串行数据输出(SDO)、串行数据输入(SDI)。SPI总线可以实现 多个SPI设备互相连接。提供SPI串行时钟的SPI设备为SPI主机或主设备(Master),其他设备为SPI从机或从设备(Slave)。主从设备间可以实现全双工通信,当有多个从设备时,还可以增加一条从设备选择线。

I2C总线是双向、两线(SCL、SDA)、串行、多主控(multi-master)接口标准,具有总线仲裁机制,非常适合在器件之间进行近距离、非经常性的数据通信。在它的协议体系中,传输数据时都会带上目的设备的设备地址,因此可以实现设备组网。一根数据线上传输的一条报文包括:开始信号+设备地址+命令+数据+(ACK)+停止信号

UART总线是异步串口,因此一般比前两种同步串口的结构要复杂很多,一般由波特率产生器(产生的波特率等于传输波特率的16倍)、UART接收器、UART发送器组成,硬件上由两根线,一根用于发送,一根用于接收。

从第二点明显可以看出,SPI和UART可以实现全双工,但I2C不行;

总结:I2C线更少,但是技术上也更加麻烦些,因为I2C需要有双向IO的支持,而且使用上拉电阻,抗干扰能力较弱,一般用于同一板卡上芯片之间的通信,较少用于远距离通信。SPI实现要简单一些,UART需要固定的波特率,就是说两位数据的间隔要相等,而SPI则无所谓,因为它是有时钟的协议。

个人学习笔记附录:

代码附件:

 /*****************************************************************************
* Copyright (C) 2014-2015 China Aerospace Telecommunications Ltd. All rights reserved.
------------------------------------------------------------------------------
* File Module : PT810 dev_I2C.c
* Description : I2C Drive operation center
* Created : 2016.10.13.
* Author : Yu Weifeng
* Function List :
* Last Modified :
* History :
******************************************************************************/
#include "stm32f4xx_hal.h"
#include "CBasicTools.h"
#include "Config.h"
#include "dev_LightDistanceSensor.h"
#include "core_CM4.h"
#include "ucos_ii.h" static void I2C_DevConfig(void);
static void I2C_Start();
static void I2C_SendByte(u8 i_ucData);
static u8 I2C_ReadByte(u8 i_ucAck);
static u8 I2C_WaitAck();
static void I2C_Stop(); static T_I2C_DevManage g_tI2C_Dev ={
.name="I2C_Dev",
.DevConfig =I2C_DevConfig,
.DevI2C_Start =I2C_Start,
.DevI2C_SendByte =I2C_SendByte,
.DevI2C_ReadByte =I2C_ReadByte,
.DevI2C_WaitAck =I2C_WaitAck,
.DevI2C_Stop =I2C_Stop,
};
//IO方向设置
#define SDA_IN() {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=0<<9*2;} //PB9输入模式
#define SDA_OUT() {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=1<<9*2;} //PB9输出模式 /*****************************************************************************
-Fuction : I2C_DevInit
-Description : I2C_DevInit
-Input :
-Output :
-Return : True/False
* Modify Date Version Author Modification
* -----------------------------------------------
* 2016/10/13 V1.0.0 Yu Weifeng Created
******************************************************************************/
void I2C_DevInit()
{
RegisterI2C_Dev(&g_tI2C_Dev);
} /*****************************************************************************
-Fuction : DelayUs
-Description : DelayUs
-Input :
-Output :
-Return : True/False
* Modify Date Version Author Modification
* -----------------------------------------------
* 2016/10/13 V1.0.0 Yu Weifeng Created
******************************************************************************/
static void DelayUs(u8 i_ucTime)
{
u16 wTime = *i_ucTime;
while(wTime--);
}
//延时nus
//nus:要延时的us数.
//nus:0~190887435(最大值即2^32/fac_us@fac_us=22.5)
void delay_us(u32 nus)
{
u32 ticks;
u32 told,tnow,tcnt=;
u32 reload=SysTick->LOAD; //LOAD的值
ticks=nus*; //系统时钟晶振为84M晶振
OSSchedLock(); //阻止OS调度,防止打断us延时
told=SysTick->VAL; //刚进入时的计数器值
while()
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<told)tcnt+=told-tnow; //这里注意一下SYSTICK是一个递减的计数器就可以了.
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break; //时间超过/等于要延迟的时间,则退出.
}
};
OSSchedUnlock(); //恢复OS调度
} /*****************************************************************************
-Fuction : I2C_SDA_SET
-Description : I2C_SDA_SET
-Input :
-Output :
-Return : True/False
* Modify Date Version Author Modification
* -----------------------------------------------
* 2016/10/13 V1.0.0 Yu Weifeng Created
******************************************************************************/
static u8 I2C_SDA_SET(u8 i_ucSetValue)
{
u8 ret=FALSE;
if(GPIO_PIN_SET==i_ucSetValue)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET); //对应引脚PB
ret=TRUE;
}
else if(GPIO_PIN_RESET==i_ucSetValue)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET); //对应引脚PB
ret=TRUE;
}
else
{
ret=FALSE;
DebugPrintf(ERR"I2C_SDA_SET format err\r\n");
}
return ret;
}
/*****************************************************************************
-Fuction : I2C_SDA_READ
-Description : I2C_SDA_READ
-Input :
-Output :
-Return :
* Modify Date Version Author Modification
* -----------------------------------------------
* 2016/10/13 V1.0.0 Yu Weifeng Created
******************************************************************************/
static u8 I2C_SDA_READ()
{
u8 ret=;
ret=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_9);
return ret;
}
/*****************************************************************************
-Fuction : I2C_SCL_SET
-Description : I2C_SCL_SET
-Input :
-Output :
-Return : True/False
* Modify Date Version Author Modification
* -----------------------------------------------
* 2016/10/13 V1.0.0 Yu Weifeng Created
******************************************************************************/
static u8 I2C_SCL_SET(u8 i_ucSetValue)
{
u8 ret=FALSE;
if(GPIO_PIN_SET==i_ucSetValue)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET); //对应引脚PB
ret=TRUE;
}
else if(GPIO_PIN_RESET==i_ucSetValue)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET); //对应引脚PB
ret=TRUE;
}
else
{
ret=FALSE;
DebugPrintf(ERR"I2C_SCL_SET format err\r\n");
}
return ret;
} /*****************************************************************************
-Fuction : I2C_DevConfig
-Description : I2C_DevConfig
-Input :
-Output :
-Return :
* Modify Date Version Author Modification
* -----------------------------------------------
* 2016/10/13 V1.0.0 Yu Weifeng Created
******************************************************************************/
static void I2C_DevConfig(void)
{
GPIO_InitTypeDef GPIO_Initure; __HAL_RCC_GPIOB_CLK_ENABLE(); //使能GPIOH时钟 //PB8,9初始化设置
GPIO_Initure.Pin=GPIO_PIN_8|GPIO_PIN_9;
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FAST; //快速
HAL_GPIO_Init(GPIOB,&GPIO_Initure); I2C_SDA_SET();
I2C_SCL_SET();
}
/*****************************************************************************
-Fuction : I2C_Start
-Description : I2C_Start//产生IIC起始信号
-Input :
-Output :
-Return :
* Modify Date Version Author Modification
* -----------------------------------------------
* 2016/09/23 V1.0.0 Yu Weifeng Created
******************************************************************************/
static void I2C_Start()
{
SDA_OUT(); //sda线输出
I2C_SDA_SET();
I2C_SCL_SET();
DelayUs();
I2C_SDA_SET();//START:when CLK is high,DATA change form high to low
DelayUs();
I2C_SCL_SET();//钳住I2C总线,准备发送或接收数据
}
/*****************************************************************************
-Fuction : I2C_Stop
-Description : I2C_Stop//产生IIC起始信号
-Input :
-Output :
-Return :
* Modify Date Version Author Modification
* -----------------------------------------------
* 2016/09/23 V1.0.0 Yu Weifeng Created
******************************************************************************/
static void I2C_Stop()
{
SDA_OUT();//sda线输出
I2C_SCL_SET();
I2C_SDA_SET();//STOP:when CLK is high DATA change form low to high
DelayUs();
I2C_SCL_SET();
I2C_SDA_SET();//发送I2C总线结束信号
DelayUs();
}
/*****************************************************************************
-Fuction : I2C_AckGenerate
-Description : I2C_AckGenerate////产生ACK应答
-Input :
-Output :
-Return :
* Modify Date Version Author Modification
* -----------------------------------------------
* 2016/10/13 V1.0.0 Yu Weifeng Created
******************************************************************************/
static void I2C_AckGenerate()
{
I2C_SCL_SET();
SDA_OUT();
I2C_SDA_SET();
DelayUs();
I2C_SCL_SET();
DelayUs();
I2C_SCL_SET();
}
/*****************************************************************************
-Fuction : I2C_AckGenerate
-Description : I2C_AckGenerate//////不产生ACK应答
-Input :
-Output :
-Return :
* Modify Date Version Author Modification
* -----------------------------------------------
* 2016/10/13 V1.0.0 Yu Weifeng Created
******************************************************************************/
static void I2C_AckNoGenerate()
{
I2C_SCL_SET();
SDA_OUT();
I2C_SDA_SET();
DelayUs();
I2C_SCL_SET();
DelayUs();
I2C_SCL_SET();
}
/*****************************************************************************
-Fuction : I2C_SendByte
-Description : I2C_SendByte////
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
-Input :
-Output :
-Return :
* Modify Date Version Author Modification
* -----------------------------------------------
* 2016/10/13 V1.0.0 Yu Weifeng Created
******************************************************************************/
static void I2C_SendByte(u8 i_ucData)
{
u8 c;
SDA_OUT();
I2C_SCL_SET();//拉低时钟开始数据传输
for(c=;c<;c++)
{
I2C_SDA_SET((i_ucData&0x80)>>);
i_ucData<<=;
DelayUs(); //对TEA5767这三个延时都是必须的
I2C_SCL_SET();
DelayUs();
I2C_SCL_SET();
DelayUs();
}
}
/*****************************************************************************
-Fuction : I2C_OnDev
-Description : I2C_OnDev
//等待应答信号到来
//返回值:0,接收应答失败
// 1,接收应答成功 -Input :
-Output :
-Return :
* Modify Date Version Author Modification
* -----------------------------------------------
* 2016/09/23 V1.0.0 Yu Weifeng Created
******************************************************************************/
static u8 I2C_WaitAck()
{
u8 ucErrTime=;
u8 ret=FALSE;
SDA_IN(); //SDA设置为输入
I2C_SDA_SET();
DelayUs();
I2C_SCL_SET();
DelayUs();
while(I2C_SDA_READ())
{
ucErrTime++;
if(ucErrTime>)
{
I2C_Stop();
ret=FALSE;
return ret;
}
}
I2C_SCL_SET();//时钟输出0
ret=TRUE;
return ret;
} /*****************************************************************************
-Fuction : I2C_ReadByte
-Description : I2C_ReadByte////
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
-Input :
-Output :
-Return :
* Modify Date Version Author Modification
* -----------------------------------------------
* 2016/10/13 V1.0.0 Yu Weifeng Created
******************************************************************************/
static u8 I2C_ReadByte(u8 i_ucAck)
{
u8 c;
u8 ucReceive=;
SDA_IN();//SDA设置为输入
for(c=;c<;c++ )
{
I2C_SCL_SET();
DelayUs();
I2C_SCL_SET();
ucReceive<<=;
if(I2C_SDA_READ())
ucReceive++;
DelayUs();
}
if (!i_ucAck)
I2C_AckNoGenerate();//发送nACK
else
I2C_AckGenerate(); //发送ACK
return ucReceive;
}

驱动之SPI,UART,I2C的介绍与应用20170118的更多相关文章

  1. SPI,UART,I2C都有什么区别,及其各自的特点

    区别: SPI:高速同步串行口.3-4线接口,收发独立.可同步进行 UART:通用异步串行口.按照标准波特率完成双向通讯,速度慢 I2C:一种串行传输方式,三线制,网上可找到其通信协议和用法的 3根线 ...

  2. 常用协议(SPI, UART, I2C)

    SPI: SPI是全双工的同步串行接口,数据速率可达几Mbps,在一般应用中有4根信号线:MOSI, MISO, SCK, SS. 根据时钟极性(CPOL)及相位(CPHA)不同可以组合成4种工作模式 ...

  3. SPI、I2C、UART三种串行总线协议的区别和SPI接口介绍(转)

    SPI.I2C.UART三种串行总线协议的区别 第一个区别当然是名字: SPI(Serial Peripheral Interface:串行外设接口); I2C(INTER IC BUS) UART( ...

  4. SPI、I2C、UART(转)

    UART与USART(转) UART需要固定的波特率,就是说两位数据的间隔要相等. UART总线是异步串口,一般由波特率产生器(产生的波特率等于传输波特率的16倍).UART接收器.UART发送器组成 ...

  5. I2S/PCM/IOM-2、I2C/SPI/UART/GPIO/slimbus

    概述 I2S,PCM,IOM-2都是数字音频接口,传数据的. I2C,SPI,UART,GPIO是控制接口,传控制信令的. I2S I2S(Inter-IC Sound Bus)是飞利浦公司为数字音频 ...

  6. Uart、SPI和I2C的区别

    串口通信:UART.SPI.I2C区别[引用]   1.UART就是两线,一根发送一根接收,可以全双工通信,线数也比较少.数据是异步传输的,对双方的时序要求比较严格,通信速度也不是很快.在多机通信上面 ...

  7. UART、SPI和I2C详解

    做单片机开发时UART,SPI和I2C都是我们最经常使用到的硬件接口,我收集了相关的具体材料对这三种接口进行了详细的解释. UART UART是一种通用串行数据总线,用于异步通信.该总线双向通信,可以 ...

  8. SPI、I2C、UART、I2S、GPIO、SDIO、CAN 简介

    转自http://sanwen.net/a/fmxnjoo.html SPI.I2C.UART.I2S.GPIO.SDIO.CAN,看这篇就够了 总线 总线,总要陷进里面.这世界上的信号都一样,但是总 ...

  9. SPI、I2C、UART、I2S、GPIO、SDIO、CAN

    总线,总线,总要陷进里面.这世界上的信号都一样,但是总线却成千上万,让人头疼. 总的来说,总线有三种:内部总线.系统总线和外部总线.内部总线是微机内部各外围芯片与处理器之间的总线,用于芯片一级的互连: ...

随机推荐

  1. 4.1 所有类型都从 System.Object 派生

    "运行时"要求各个类型最终都从 System.Object 派生.(显示继承/隐式继承) 提供公共方法(public): Equals 判断两个对象相等,true 表示相等. Ge ...

  2. div不设置高度背景颜色或外边框不能显示的解决方法

    在使用div+css进行网页布局时,如果外部div有背景颜色或者边框,而不设置其高度,在浏览时出现最外层Div的背景颜色和边框不起作用的问题. 大体结构<div class="oute ...

  3. 高可用Kubernetes集群-6. 部署kube-apiserver

    八.部署kube-apiserver 接下来3章节是部署Kube-Master相关的服务,包含:kube-apiserver,kube-controller-manager,kube-schedule ...

  4. Jenkins之Sonar 代码检查

    一.简介 SonarQube 是一个用于代码质量管理的开放平台.通过插件机制,Sonar 可以集成不同的测试工具,代码分析工具,以及持续集成工具.与持续集成工具(例如 Hudson/Jenkins 等 ...

  5. SQL判断是否存在

    判断数据库是否存在 ifexists(select*frommaster..sysdatabaseswherename=N’库名’) print’exists’ else print’notexist ...

  6. JavaScript/Jquery:Validform 验证表单的相关属性解释

    当我们写提交表单的时候往往需要验证表单是否填写了内容,是否正确,这个插件可以很方便的完成我们需要的验证! 使用方法: 1.先引用js <script type="text/javasc ...

  7. Hibernate:工作原理

    Hibernate的工作原理图如下所示:

  8. JAVA方法的重载(overload)和覆盖(override)

    方法的重载(overload)和覆盖(override) 有的时候,类的同一种功能有多种实现方式,到底采用哪种实现方式,取决于调用者给定的参数.例如我们最常用的System.out.println() ...

  9. Spring Boot(八)集成Spring Cache 和 Redis

    在Spring Boot中添加spring-boot-starter-data-redis依赖: <dependency> <groupId>org.springframewo ...

  10. Maven基本理解

    转 maven(一) maven到底是个啥玩意~ 我记得在搞懂maven之前看了几次重复的maven的教学视频.不知道是自己悟性太低还是怎么滴,就是搞不清楚,现在弄清楚了,基本上入门了.写该篇博文,就 ...