STM32学习笔记——SPI串行通讯(向原子哥学习)SMT32大面积通信协议。

有 SPI 接口,在时钟信号的控制下传输数据

 一、SPI  简介

串行通信的几乎独名词:

全双工:数据线有2漫长,分别用来发送和接收。
半双工:数据线只来1修,用来发送和收受,分时复用。
并:时钟线1久,在钟信号的支配下传数据。

  SPI是 Serial Peripheral interface 的缩写,就是串行外围设备接口。SPI
接口主要运用在  EEPROM, FLASH,实时时钟,AD
转换器,还有数字信号处理器以及数字信号解码器之间。SPI,是一样种植高效的,全双工,同步的通信总线,并且于芯片的管脚上只是占四根线,节约了芯片的不论脚,同时也
PCB
的布局上省空间,提供方便,正是出于这种概括好用底特性,现在更加多的芯片集成了这种通信协议,STM32
有 SPI 接口。下面是 SPI 的内简明图:

(1)IIC

IIC(Inter-Integrated Circuit)总线是同栽由 PHILIPS
公司支付之两线式串行总线,用于连接微控制器及其外围配备。它是由数据线 SDA
和时钟 SCL 构成的串行总线,SDA 可发送和接收数据,因此是一律种植半双工通信。

lovebet爱博 1

I2C 总线在传送数据过程遭到共有三种植类型信号,
它们分别是:开始信号、结束信号与报信号。
  开始信号:SCL 为高电平时,SDA 由大电平向没有电平跳变,开始传送数据。
  结束信号:SCL 为高电平时,SDA 由没有电平向高电平跳变,结束传送数据。
  应答信号:接收数据的 IC 在收受及 8bit 数据后,向发送数据的 IC
发出特定的低位电平脉冲,表示已经收取数额。CPU
向受控单元有一个信号后,等待受控单元有一个报信号,CPU
接收至回信号后,根据实际状况作出是否持续传递信号的判断。若不接受回复信号,由判也受控单元出现故障。
  这些信号中,起始信号是不可或缺的,结束信号与回复信号,都可不用。

 lovebet爱博 2

①空闲状态

IIC总线的SDA和SCL两久信号线同时处于高电平,称为总线的空余状态。两长长的信号线各自的上拉电阻把电平拉大。

希冀1 SPI 内部结构简明图

②从头信号和了信号

开始信号:SCL 为高电平时,SDA 由大电平向亚电平跳变,开始传送数据。
利落信号:SCL 为高电平时,SDA 由小电平向强电平跳变,结束传送数据。

lovebet爱博 3

  SPI 接口一般采取 4 长长的线通信:

③许答信号

发送器每发送一个字节,就在时钟脉冲9期间保释数据线,由接收器反馈一个回答信号。应答信号吧低电平时,规定为中应答位(ACK简称应答位),表示接收器已经成地吸收了该字节;应答信号呢高电平时,规定呢无承诺答位(NACK),一般代表接收器接收该字节没有水到渠成。对于举报中应答位ACK的渴求凡,接收器在第九只时钟脉冲之前的小电平期间以SDA线拉低,确保于拖欠时钟的赛电平期间为平安的不比电平。
如接收器是主控器(即单片机接收数据),则在它接受最后一个配节后,发送一个NACK信号,以通知为控发送器结束数据发送,并释放SDA线,以便主控接收器发送一个休信号P。

lovebet爱博 4

    MISO  主设备数据输入,从设备数量输出。

④数额传

数量的灵光:SCL为强电平期间,SDA必须维持安澜(1或0),即数据以SCL的腾沿到来前如果准备好,在SCL的跌沿到来前若安静。
当IIC总线上传递的各国一样各数据还产生一个时钟脉冲信号相对应,即于SCL串行时钟的匹配下,在SDA上逐位地串行传送每一样位数据。数据位的传导是边触发。

    MOSI  主设备数据输出,从设备数量输入。

程序代码

参考实验23 IIC代码。

//单片机向IIC设备上写数据

IIC_Start(); 

IIC_Send_Byte(0XA0);       //一般要先发送IIC设备的地址、工作模式等等
IIC_Wait_Ack();  //等待IIC设备发出ACK
IIC_Send_Byte(0X11);   //写数据,IIC_Send_Byte()和IIC_Wait_Ack()成对出现
IIC_Wait_Ack(); 

IIC_Stop();//产生一个停止条件       

//单片机从IIC设备上读取数据

IIC_Start(); 

IIC_Send_Byte(0XA0);       //一般还需要先对设备的地址、工作模式进行配置。可能用到几组的IIC_Send_Byte()和IIC_Wait_Ack()。
IIC_Wait_Ack();  //等待IIC设备响应

X = IIC_Read_Byte(0);  //单片机接收一个字节,单片机发出ACK信号
Y = IIC_Read_Byte(1);   //单片机接收一个字节,单片机发出NACK信号
//ACK信号还是NACK信号,要参照IIC设备的datasheet
IIC_Stop();//产生一个停止条件   

    SCLK 时钟信号,由主设备产生。

(2)SPI

SPI 是英语 Serial Peripheral interface
的缩写,顾名思义就是串行外围设备接口。
SPI,是均等栽高效的,全双工,同步的通信总线,并且于芯片的管脚上单独占四根线,节约了芯片的不论脚,同时也
PCB 的布局上省空间,提供方便。
SPI 接口一般以 4 漫漫线通信:
MISO 主设备数据输入,从设备数据输出。
MOSI 主设备数量输出,从设备数据输入。
SCLK 时钟信号,由主设备产生。
CS 于设备片选信号,由主设备控制。

lovebet爱博 5

长机及从机都有一个串行移位寄存器,主机通过向它的 SPI
串行寄存器写副一个字节来倡导一涂鸦传输。寄存器通过 MOSI
信号线将许节传送给从机,从机也将自己之移动寄存器中的内容通过 MISO
信号线返回给主机。这样,两只活动寄存器中的情就是为换成。外设的勾操作以及朗诵操作是联合完成的。如果只是进行摹写操作,主机才待忽略接收至的字节;反之,若主机要读取从机的一个字节,就得发送一个空字节来吸引从机的传。

SPI 总线四种工作办法 SPI
模块为了跟外设进行数据交换,根据外设工作要求,其出口串行同步时钟极性和相位可以展开配备,时钟极性(CPOL)对传输协议没有重要的影响。如果
CPOL=0,串行同步时钟的空闲状态吧低电平;如果
CPOL=1,串行同步时钟的闲暇状态也大电平。时钟相位(CPHA)能够配置用于选择个别种不同之传协议之一进行数量传。如果CPHA=0,在串行同步时钟的率先个过变沿(上升要降低)数据被采样;如果
CPHA=1,在串行同步时钟的次独超变沿(上升还是回落)数据给采样。SPI
主模块和和的通信的异设施时钟相位和极性应该同。

lovebet爱博 6

lovebet爱博 7

lovebet爱博 8

此间我们使用的凡 PB13、14、15 这 3 单(SCK.、MISO、MOSI,CS
使用软件管理措施),所以设置这三独为复用 IO。

lovebet爱博 9

硬件连接图

①布置相关引脚的复用功能,使能SPIx时钟。

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能 
RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2,  ENABLE );//SPI2时钟使能   

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PB13/14/15复用推挽输出 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB
GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);  //PB13/14/15上拉

lovebet爱博 10

实在经历,在MISO中,也可一如既往用推挽复用输出,而未用浮空、上拖累输入。
②初始化SPIx,设置SPI工作模式

SPI_InitTypeDef  SPI_InitStructure;

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;       //设置SPI工作模式:设置为主SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;       //设置SPI的数据大小:SPI发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;     //串行同步时钟的空闲状态为高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;    //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;       //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;        //定义波特率预分频的值:波特率预分频值为256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;  //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7;    //CRC值计算的多项式

SPI_Init(SPI2, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器

结构体成员变量比较多,这里我们挑取几单第一的分子变量讲解一下:
率先只参数 SPI_Direction 是为此来装 SPI
的通信方式,可以选取啊半双工,全双工,以及串行发和串行收方式,这里我们捎都双工模式
SPI_Direction_2Lines_FullDuplex。
第二单参数 SPI_Mode 用来安 SPI 的骨干模式,这里我们设置也主机模式
SPI_Mode_Master,当然发要而也可挑选吗从机模式 SPI_Mode_Slave。
老三独参数 SPI_DataSiz 为 8 位还是 16 位帧格式选择项,这里我们是 8
位传输,选择SPI_DataSize_8b。
季独参数 SPI_CPOL
用来安装时钟极性,我们安串行同步时钟的空状态为高电平所以我们选取
SPI_CPOL_High。
第五个参数 SPI_CPHA
用来安时钟相位,也就是选以串行同步时钟的第几个超过变沿(上升要降低)数据让采样,可以呢第一独或第二独漫长边沿采集,这里我们捎第二个超过变沿,所以选择
SPI_CPHA_2Edge
第六只参数 SPI_NSS 设置 NSS 信号由硬件(NSS
管脚)还是软件控制,这里我们通过软件控制 NSS
关键,而休是硬件自动控制,所以选择 SPI_NSS_Soft。
第七个参数 SPI_BaudRatePrescaler 很重点,就是安 SPI
波特率预分频值也就算是决定 SPI 的钟表的参数,从不分频道 256 分频 8
单可选值,初始化的上咱们选取 256 分频值SPI_BaudRatePrescaler_256,
传输速度为 36M/256=140.625KHz。
第八单参数 SPI_FirstBit 设置数据传顺序是 MSB 位在前边还是 LSB
位在前头,,这里我们选取SPI_FirstBit_MSB 高位以前方。
第九只参数 SPI_CRCPolynomial 是用来装 CRC
校验多项式,提高通信可靠性,大于 1 即可。
③使能SPIx

SPI_Cmd(SPI2, ENABLE); //使能SPI外设

④然后即便能经过SPI进行读写操作,状态各判断。

void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);

uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx) ; 

SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE);   // 发送完成标志位

    CS 从设备片选信号,由主设备控制。

  从图被得看看,主机与从机都出一个串行移位寄存器,主机通过为它们的 SPI
串行寄存器写副一个字节来倡导一差传输。寄存器通过 MOSI
信号线将许节传送给从机,从机也拿团结之移位寄存器中之始末通过 MISO
信号线返回给主机。这样,两只运动寄存器中之情节就是给换成。外设的形容操作以及朗诵操作是联合到位的。如果只有进行勾勒操作,主机才待忽略接收到的字节;反之,若主机要读取从机的一个字节,就得发送一个空字节来吸引从机的传导。

二、

  SPI
主要特色发生:可以以起与接纳串行数据;可以用作主机或从机工作;提供频率可编程时钟;发送完中断标志;写冲突保护;总线竞争保护等。

  SPI 总线四种植工作措施  SPI 
模块为了与外设进行数据交换,根据外设工作要求,其出口串行同步时钟极性和相位可以拓展布局,时钟极性(CPOL)对传输协议没有重大的震慑。如果CPOL=0,串行同步时钟的空余状态为小电平;如果
CPOL=1,串行同步时钟的悠闲状态呢胜电平。时钟相位(CPHA)能够配置用于选择个别栽不同的传输协议之一进行数量传。如果CPHA=0,在串行同步时钟的第一只跨变沿(CPOL位为0时就是下降沿,CPOL位也’1’时就是是稳中有升沿)数据被采样;如果
CPHA=1,在串行同步时钟的次独超变沿(CPOL位为0时就算是下跌沿,CPOL位也’1’时即便是上升沿)数据让采样。SPI
主模块和及的通信的外设施时钟相位和极性应该一致。

  不同时钟相位下之总线数据传时先后如图 2 所示:

lovebet爱博 11

lovebet爱博 12

图2  不同时钟相位下的总线传输时序(CPHA=0/1)

  STM32 的 SPI 功能很有力,SPI 时钟最多得到 18Mhz,支持
DMA,可以安排也 SPI 协议要 I2S 协议(仅大容量型号支持) 。

  使用 STM32 的 SPI2 的主模式,下面就是来探望 SPI2 片段的设置步骤吧。SPI
相关的库函数和定义分布在文件 stm32f10x_spi.c 以及头文件
stm32f10x_spi.h 中。

老三、STM32 的主模式配置步骤如下:

  1)配置相关引脚的复用功能,使能 SPI2 时钟

  用 SPI2,第一步就是如而能 SPI2 的钟。其次要设置 SPI2
的相干引脚为复用输出,这样才见面一连到 SPI2 上再不这些 IO
口还是默认的状态,也不怕是正式输入输出口。这里以的是 PB13、14、15 这 3
单(SCK.、MISO、MOSI,CS 使用软件管理办法),所以设置这三独为复用 IO。

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(  RCC_APB2Periph_GPIOB, ENABLE );        //PORTB 时钟使能

RCC_APB1PeriphClockCmd(  RCC_APB1Periph_SPI2, ENABLE );        //SPI2 时钟使能  

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;             //PB13/14/15 复用推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);                  //初始化 GPIOB

  2)初始化 SPI2,设置 SPI2 工作模式

  接下要初始化 SPI2,设置 SPI2 也主机模式,设置数据格式为 8
位,然设置 SCK 时钟极性及采样方式。并安装 SPI2 的钟表频率(最要命
18Mhz),以及数的格式(MSB 在头里还是LSB 在头里)。这在库函数中是透过
SPI_Init 函数来促成之。

    void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef*
SPI_InitStruct);

  第一只参数是 SPI 标号,这里我们是使用的
SPI2。下面我们来看望第二个参数结构体类型 SPI_InitTypeDef 的定义:

typedef struct

{

uint16_t SPI_Direction;

uint16_t SPI_Mode;

uint16_t SPI_DataSize;

uint16_t SPI_CPOL;

uint16_t SPI_CPHA;

uint16_t SPI_NSS;

uint16_t SPI_BaudRatePrescaler;

uint16_t SPI_FirstBit;

uint16_t SPI_CRCPolynomial;

}SPI_InitTypeDef;

结构体成员变量比较多,这里我们挑取几独关键的分子变量讲解一下:

  第一个参数 SPI_Direction 是故来安 SPI
的通信方式,可以选择啊半双工,全双工,以及串行发和串行收方式,这里我们摘都双工模式 SPI_Direction_2Lines_FullDuplex。

  第二只参数 SPI_Mode 用来装 SPI 的着力模式,这里我们装为主机模式
SPI_Mode_Master,当然有得您为堪选也从机模式 SPI_Mode_Slave。

  第三个参数 SPI_DataSiz 也 8 位还是 16 位帧格式选择项,这里我们是 8
位传输,选择 SPI_DataSize_8b。

  第四个参数 SPI_CPOL
用来设置时钟极性,我们设置串行同步时钟的悠闲状态也高电平所以我们选取 SPI_CPOL_High。

  第五单参数 SPI_CPHA
用来装时钟相位,也即是择在串行同步时钟的第几只跨变沿(上升要降)数据为采样,可以吗第一个或第二单漫长边沿采集,这里我们捎第二只跨变沿,所以选择
SPI_CPHA_2Edge

  第六独参数 SPI_NSS 设置 NSS 信号由硬件(NSS
管脚)还是软件控制,这里我们透过软件控制 NSS
关键,而无是硬件自动控制,所以选择 SPI_NSS_Soft。

  第七单参数 SPI_BaudRatePrescaler 很要紧,就是装 SPI
波特率预分频值也就是决定 SPI 的时钟的参数 , 从不分频道 256 分频 8
只可挑选值,初始化的时候咱们选择 256 分频值 SPI_BaudRatePrescaler_256,  传输速度为
36M/256=140.625KHz。

  第八独参数 SPI_FirstBit 设置数据传顺序是 MSB 位在前还是 LSB
位在前面, ,这里我们选取SPI_FirstBit_MSB 高位以前边。

  第九lovebet爱博个参数 SPI_CRCPolynomial 是故来设置 CRC
校验多项式,提高通信可靠性,大于 1 即可。

装好点 9 个参数,就可初始化 SPI 外设了。初始化的范例格式为:

SPI_InitTypeDef SPI_InitStructure;

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;     //双线双向全双工

SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                  //主 SPI

SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;               // SPI 发送接收 8 位帧结构

SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                 //串行同步时钟的空闲状态为高电平

SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                //第二个跳变沿数据被采样

SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                   //NSS 信号由软件控制
  
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;   //预分频 256

SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;              //数据传输从 MSB 位开始

SPI_InitStructure.SPI_CRCPolynomial = 7;                    //CRC 值计算的多项式

SPI_Init(SPI2, &SPI_InitStructure);                       //根据指定的参数初始化外设 SPIx 寄存器

  3)使能 SPI2

  初始化完成之后接下来是要使能 SPI2 通信了,在使能 SPI2 之后,我们就可以开始 SPI 通讯了。使能 SPI2 的方法是:
     SPI_Cmd(SPI2, ENABLE); //使能 SPI 外设

  4)SPI 传输数据

  通信接口当然要来发送数据和领多少的函数,固件库提供的发送数据函数原型为:

    void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t
Data);//往 SPIx 数据寄存器写副数据 
Data,从而实现殡葬。

  固件库提供的纳多少函数原型为:

    uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx)  ;//从
SPIx 数据寄存器读来受到之多少。

  5)查看 SPI 传输状态

  以 SPI
传输过程被,我们经常要判数是否传输就,发送区是否为空等等状态,这是经函数
SPI_I2S_GetFlagStatus
实现的,这个函数很粗略就非详细讲解,判断发送是否就的方是:

    SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE);