I2c驱动与SPI驱动

今天说一下单片机的I2C SPI通信,可能说不清楚,因为这毕竟要做实验才可完全理解。
I2C和SPI是两种不同的通信协议。
听到协议,似乎高不可攀,其实协议就是人们定义的一个标准而已,我们只要遵照这个标准去做事,就可以。比如公司规定早上9点上班,我们就9点上班,不然就会扣薪水,这就是个协议。
用I2C通信的芯片最常用的就是EEPROM芯片,如Atmel的AT24CXX系列,此外,还有一些其它功能的芯片。用SPI通信的芯片有外置FLASH芯片,同样,还有其他功能的一些芯片。
I2C通信需要用到两个引脚:SDA SCL。SCL是时钟引脚,SDA是数据引脚。


(这是EEPROM芯片)


(这是时钟芯片)
SPI通信需要3个引脚或者4个引脚:CS SCK MOSI MISO。SPI通信芯片的引脚名称不一定都是这几个名称,可能还有会别的名称,但是意思是一样的,例如MOSI引脚的意思是“主机输出从机输入”,某个SPI接口的芯片就有可能会写成SDI,因为这个SPI器件是作为从机的,所以它的SDI的意思就是“从机数据输入引脚”。
SPI通信过程为:把CS引脚拉低,然后SCK输出时钟,然后就可以在MOSI引脚上输出数据,同时可以在MISO上获得数据了。


(这是一个SPI FLASH芯片,DO是MISO,DI是MOSI,CLK是SCK,功能一样,叫法不一样而已)


(这是一个SPI接口的ADC芯片,Dout是MISO,DCLOCK就是SCK,这个芯片有3个SPI引脚)
大部分单片机上面都会带有I2C口和SPI口,有可能还会有好几个I2C口和SPI口。不过,不带I2C口和SPI口的单片机,也可以通过普通引脚的模拟他们的时序来进行通信。
而且,如果是初学者的话,一定要学习一下用普通引脚模拟,对他们的通信本质理解更深刻。
通信全程,其实就是控制引脚高低电平和检测引脚高低电平的过程,话说,控制单片机的引脚高低电平和检测引脚的高低电平,第一天学单片机就会了,所以,I2C通信和SPI通信也没什么难的地方。
给大家讲一个最简单的通信过程,例如我们称下面的通信名称为KJLWT,名字是不是看起来很吊,其实是“科技老顽童”的拼音首字母,因为接下来的协议是我刚刚发明的,所以以此命名^_^。主要是让大家理解,名称就是用来吓唬人的。
我们用两条线来通信,一条时钟线,一条数据线。时钟线,其实就是用来产生一个脉冲波形,再说的直接一点,就是把引脚变高变低的信号,如下图:


(这就是个时钟信号)
例如我们规定,在时钟引脚为高电平的时候,读取数据引脚的电平,连续8个时钟,就可以读到一个字节了。那给数据的那一端,要怎么给数据呢?也很简单,给数据的那一端,在检测到低电平的时候,就把要发送的数据按照位体现在数据引脚上面。例如一个数据:0x88,写成二进制以后就是1000 1000。我们来看一下传输这个数据的过程:从机检测时钟引脚,检测到一个下降沿(就是从高电平落到了低电平),就把要发送的数据的bit7体现在数据引脚上,例如1000 1000的bit7是1,就把数据引脚变高电平,主机在时钟引脚的高电平,检测这个数据引脚,把这个位记录下来,从机再次发现时钟引脚的下降沿后,再把数据的bit6体现在数据引脚上,由于1000 1000 的bit6是0,所以从机把数据引脚拉低,然后当时钟引脚为高电平的时候,主机检测数据引脚的高低电平,再把bit6记录下来,……以此8次,就可以把一个字节由从机传输到主机了。是不是很简单呢?
时钟的速率,就是传输数据的快慢,以上面讲的为例,如果脉冲的周期为1秒钟,也就是1Hz,那么传输一个字节就需要8秒钟;如果脉冲的周期为1毫秒,也就是1KHz,那么输出一个字节只需要8毫秒。这下你就理解通信的速率是什么意思了吧?
I2C通信,SPI通信,只不过是在我刚才讲的例子上面,又多了一些协议内容。具体的协议,你们随便找一个I2C和SPI通信接口的芯片看一下时序图就可以了。我们要做的,就是用单片机的引脚,把它的时序做出来。

希望能够帮助到大家。

1、什么是SPI?

SPI是串行外设接口(Serial Peripheral Interface)的缩写。是 Motorola 公司推出的一 种同步串行接口技术,是一种高速的,全双工,同步的通信总线。

2、SPI优点
支持全双工通信
通信简单数据传输速率块

3、缺点
没有指定的流控制,没有应答机制确认是否接收到数据,所以跟IIC总线协议比较在数据 可靠性上有一定的缺陷。

4、特点
1):高速、同步、全双工、非差分、总线式2):主从机通信模式

5、协议通信时序详解
1):SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多
个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共
有的,它们是SDI(数据输入)、SDO(数据输出)、SCLK(时钟)、CS(片选)。
(1)SDO/MOSI – 主设备数据输出,从设备数据输入;
(2)SDI/MISO – 主设备数据输入,从设备数据输出;
(3)SCLK – 时钟信号,由主设备产生;
(4)CS/SS – 从设备使能信号,由主设备控制。当有多个从设备的时候,因为每个从设
备上都有一个片选引脚接入到主设备机中,当我们的主设备和某个从设备通信时将需 要将从设备对应的片选引脚电平拉低或者是拉高。

2):需要说明的是,我们SPI通信有4种不同的模式,不同的从设备可能在出厂是就是配
置为某种模式,这是不能改变的;但我们的通信双方必须是工作在同一模式下,所以我们
可以对我们的主设备的SPI模式进行配置,通过CPOL(时钟极性)和CPHA(时钟相位)来
控制我们主设备的通信模式,具体如下:
Mode0:CPOL=0,CPHA=0
Mode1:CPOL=0,CPHA=1
Mode2:CPOL=1,CPHA=0Mode3:CPOL=1,CPHA=1

时钟极性CPOL是用来配置SCLK的电平出于哪种状态时是空闲态或者有效态,时钟相位CPHA
是用来配置数据采样是在第几个边沿:
CPOL=0,表示当SCLK=0时处于空闲态,所以有效状态就是SCLK处于高电平时
CPOL=1,表示当SCLK=1时处于空闲态,所以有效状态就是SCLK处于低电平时
CPHA=0,表示数据采样是在第1个边沿,数据发送在第2个边沿CPHA=1,表示数据采样是在第2个边沿,数据发送在第1个边沿

例如:
CPOL=0,CPHA=0:此时空闲态时,SCLK处于低电平,数据采样是在第1个边沿,也就是 SCLK由低电平到高电平的跳变,所以数据采样是在上升沿,数据发送是在下降沿。

CPOL=0,CPHA=1:此时空闲态时,SCLK处于低电平,数据发送是在第1个边沿,也就是 SCLK由低电平到高电平的跳变,所以数据采样是在下降沿,数据发送是在上升沿。

CPOL=1,CPHA=0:此时空闲态时,SCLK处于高电平,数据采集是在第1个边沿,也就是 SCLK由高电平到低电平的跳变,所以数据采集是在下降沿,数据发送是在上升沿。

CPOL=1,CPHA=1:此时空闲态时,SCLK处于高电平,数据发送是在第1个边沿,也就是 SCLK由高电平到低电平的跳变,所以数据采集是在上升沿,数据发送是在下降沿。

需要注意的是:我们的主设备能够控制时钟,因为我们的SPI通信并不像UART或者IIC通信
那样有专门的通信周期,有专门的通信起始信号,有专门的通信结束信号;所以我们的
SPI协议能够通过控制时钟信号线,当没有数据交流的时候我们的时钟线要么是保持高电平要么是保持低电平。

6、内部工作机制


SSPSR 是 SPI 设备内部的移位寄存器(Shift Register). 它的主要作用是根据 SPI
时钟信号状态, 往 SSPBUF 里移入或者移出数据, 每次移动的数据大小由 Bus-Width 以 及 Channel-Width 所决定.

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你好,以下是使用B13和B15单独发送SPI2的驱动代码示例: ```c #include "stm32f4xx.h" void SPI2_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; SPI_InitTypeDef SPI_InitStruct; // 使能SPI2和GPIOB的时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); // 配置B13和B15为SPI2模式 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; // 复用模式 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; // 推挽输出 GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOB, &GPIO_InitStruct); // 将B13和B15复用到SPI2上 GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2); GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2); // 配置SPI2 SPI_InitStruct.SPI_Direction = SPI_Direction_1Line_Tx; // 单向发送 SPI_InitStruct.SPI_Mode = SPI_Mode_Master; // 主模式 SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low; SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStruct.SPI_NSS = SPI_NSS_Soft; // 软件控制NSS信号 SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB; // 高位先发 SPI_Init(SPI2, &SPI_InitStruct); // 使能SPI2 SPI_Cmd(SPI2, ENABLE); } void SPI2_SendByte(uint8_t byte) { // 等待发送缓冲区为空 while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); // 发送数据 SPI_SendData8(SPI2, byte); // 等待发送完成 while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET); } ``` 以上是使用B13和B15单独发送SPI2的驱动代码示例,供参考。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值