这篇文章主要介绍基本的驱动也是用的最多的协议类驱动中的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. 牛客网暑期ACM多校训练营(第一场):E-Removal(DP)

    链接:E-Removal 题意:给出序列 s1, s2, ..., sn ,1<=s[i]<=10.问删除m个数后,有多少种不同的序列. 题解:定义dp[i][j]代表长度为i,最末尾的数 ...

  2. JQuery点击打开再点击关闭

    $("#03").click(function() { $("#03").show(speed); $("#03").css("c ...

  3. Python Tkinter-Event

    1.点击 from tkinter import * root=Tk() def printCoords(event): print(event.x,event.y) bt1=Button(root, ...

  4. Bean的装配

    1.可以从ApplicationContext上下文获取和bean工厂获取容器,bean工厂只建议在移动端应用使用. 2.如果使用的是applicationContext配置的是bean,如果作用域是 ...

  5. BVT与冒烟测试

    [BVT的释义] BVT的全称是Build Verification Test.可以说这个全称就是BVT的定义了. BVT只验证build构建的成功与失败,不深入测试构建好的build的功能.性能等等 ...

  6. "Hello World"团队召开的第三周第六次会议

    今天是我们团队“Hello World!”团队召开的第三周的第六次会议.博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.todo list 六.会议照片 七.燃尽图 一.会议时 ...

  7. 404 Note Found队——现场编程

    目录 组员职责分工 github 的提交日志截图 程序运行截图 程序运行环境 GUI界面 基础功能实现 运行视频 LCG算法 过滤(降权)算法 算法思路 红黑树 附加功能一 背景 实现 附加功能二(迭 ...

  8. lintcode-221-链表求和 II

    221-链表求和 II 假定用一个链表表示两个数,其中每个节点仅包含一个数字.假设这两个数的数字顺序排列,请设计一种方法将两个数相加,并将其结果表现为链表的形式. 样例 给出 6->1-> ...

  9. java沙盒

    JAVA的安全模型不同于传统的安全方法,传统的安全方法中,大多数操作系统允许应用程序充分访问系统资源,在操作系统不提供安全保护的机器里,运行环境不能被信任.为了弥补这个缺陷,安全策略经常要求在应用程序 ...

  10. Struts2(四)

    以下内容是基于导入struts2-2.3.32.jar包来讲的 1.struts2配置文件加载的顺序 struts2的StrutsPrepareAndExecuteFilter拦截器中对Dispatc ...