【SPI】硬件SPI驱动

一、SPI外设简介

  • STM32内部集成了硬件SPI收发电路,可以由硬件自动执行时钟生成、数据收发等功能,减轻CPU的负担
  • 可配置8位/16位数据帧、高位先行/低位先行
    • SPI最常用【8位数据帧】、【高位先行】
  • 时钟频率: fPCLK / (2, 4, 8, 16, 32, 64, 128, 256)
    • PCLK(Peripheral Clock)外设时钟——APB1的PCLK为36MHz,APB2的PCLK为72MHz
  • 支持多主机模型、主或从操作
  • 可精简为半双工/单工通信
  • 支持DMA
  • 兼容I2S协议
  • STM32F103C8T6 硬件SPI资源:SPI1【APB2】、SPI2【APB1】

二、SPI框图

大致可以将SPI框图分为两部分:
1、左上角——【数据寄存器】和【移位寄存器】相互配合进行传输,实现连续数据流
  • 移位寄存器(右移):右边的数据低位一位位从MOSI移出,MISO的数据一位位移入左边的数据高位——低位先行
    • LSBFIRST:控制【低位/高位先行】
  • 接收缓冲区(接收数据寄存器RDR):读取DR时,数据从【接收缓冲区】RDR读取
  • 发送缓冲区(发送数据寄存器TDR):写入DR时,数据从【地址和数据总线】写入到TDR
//TDR和RDR占用同一个地址,统一叫做【DR】
总结:发送数据先写入【TDR】,再转到【移位寄存器】发送(发送的同时接收数据,转到RDR,再从RDR读取数据)
2、右下角——配置寄存器以控制逻辑
  • 波特率发生器:产生SCK时钟(内部主要是分频器,将输入时钟PCLK=72MHz or 36MHz经过分频后输出到SCK引脚)
  • SPI_CR1
    • BR0、1、2:控制分频系数
    • LSBFIRST:控制【低位/高位先行】
    • SPE(SPI Enable):SPI使能
    • BR(Baud Rate):配置波特率(SCK时钟频率)
    • MSTR:配置主从模式
    • CPOL和CPHA:选择SPI的4种模式
  • SR状态寄存器
    • TXE:发送寄存器空
    • RXNE:接收寄存器非空
  • NSS引脚:从机选择(低电平有效——“N”)
    • 用于实现多主机模型

三、SPI基本结构

  • 流程
1、移位寄存器左移——移出数据高位通过GPIO移出到MOSI——移入数据从MISO进入通过GPIO到低位——如此循环8次主机和从机就能交换一个字节
2、发送数据寄存器TDR——整体移入【移位寄存器】的时刻置【TXE】标志位(发送寄存器空)
3、接收数据寄存器RDR——整体转入【RDR】的时刻置【RXNE】标志位(接收寄存器非空)
4、波特率发生器产生时钟输出到SCK引脚
5、开关控制(SPI使能)
//SS从机选择引脚通过普通的GPIO口模拟

主模式全双工连续传输示意图

//示例【CPOL=1,CPHA=1】使用的是SPI模式3
SPI模式3:
  • CPOL =1 :空闲状态时, SCK 为高电平
  • CPHA =1 SCK 第一个边沿移出数据,第二个边沿移入数据
  • 主模式全双工连续传输示意图——借助缓冲区实现连续数据流的过程
    • 优点:传输更快,性能较好
    • 缺点:流程稍微复杂,操作麻烦且不方便封装,数据的位置交叉较多,发送对应接收流程不连贯
  • 输出的流程和现象
第一行:SCK时钟线首先为高电平,在第一个下降沿MOSI和MISO移出数据,之后上升沿移入数据
第二行:MOSI和MISO输出波形,跟随SCK时钟变换,数据位依次出现
//此处从前到后依次出现【b0、b1……b7】——示例为【低位先行】(实际使用时高位先行更多)
第三行:TXE发送寄存器空标志位
第四行:发送缓冲器写入SPI_DR(发送数据寄存器TDR)
第五行:BSY(BUSY)由硬件自动设置和清除——当有数据传输时BUSY置1
首先SS置低电平开始时序,TXE为1(表示TDR空)表示可以写入数据开始传输
  • 指示1:软件写入【0xF1】到SPI_DR——【0xF1】就是要发送的第一个数据
写入后发送缓冲器(发送数据寄存器TDR)变为【0xF1】,同时TXE为0(表示TDR有数据)
//刚开始【移位寄存器】为空,因此在等候区的数据【0xF1】就会立刻转入【移位寄存器】开始发送
转入瞬间置TXE为1(表示TDR空)
移位寄存器开始有数据了——MISO/MOSI输出自动开始生成数据F1的波形
//示例中b0出现稍早
在移位产生F1波形的同时, 发送数据寄存器TDR为空,为了保证数据连续性,需要提前把下一个数据写入TDR等待
  • 指示2:写入【0xF1】后软件等待【TXE】为1,然后写入【0xF2】到SPI_DR——提前写入下一数据【0xF2】
写入后发送缓冲器(发送数据寄存器TDR)变为【0xF2】
【移位寄存器】完成上一个数据【0xF1】的发送之后为空,在等候区的数据【0xF2】就会立刻转入【移位寄存器】开始发送
//再重复之前操作,尽快将下一个数据【0xF3】 提前把下一个数据写入TDR等待
  • 指示4:写入【0xF2】后软件等待【TXE】为1,然后写入【0xF3】到SPI_DR——提前写入下一数据【0xF3】
写入后发送缓冲器(发送数据寄存器TDR)变为【0xF3】
//如果只想发送3个数据,F3转入【移位寄存器】之后【TXE】为1(表示TDR空),就不需要继续写入了
注意:在最后一个TXE=1后,还需要再继续等待一段时间以完整发送0xF3波形
波形全部完整发送之后,【BUSY】标志由硬件清除,表示波形发送完成
  • 输入的流程和现象
第六行:MISO和MOSI和输入数据
第七行:RXNE接收数据寄存器非空标志位
第八行:接收缓冲器读出SPI_DR(接收数据寄存器RDR)
SPI是全双工——发送的同时还有接收
在第一个字节【0xF1】发送完成后,第一个字节【0xA1】的接收也完成了
此时【移位寄存器】的数据整体移入【接收数据寄存器RDR】
移入RDR后读出的就是【0xA1】——转入的同时【RXNE】标志位置1(表示收到数据)
  • 指示3:软件等待RXNE=1,从SPI_DR读出【0xA1】
接收之后软件清除RXNE标志位
当下一个数据【0xA2】收到后RXNE标志位重新置1——监测到RXNE=1时就继续读出RDR(指示5)
在最后一个字节时序完全产生之后,数据3【0xF3】才能收到
注意:一个字节波形收到后,【移位寄存器】的数据自动转入【RDR】,会覆盖原有的数据
//读取RDR要及时(RDR里的数据不能待太久)
总结:对软件的配合要求较高,在每个标志位产生后,数据都要及时处理
——配合的好,时钟可以连续不间断地产生,每个字节之间没有任何空隙,传输效率最高

非连续传输示意图

//示例【CPOL=1,CPHA=1】使用的是SPI模式3
SPI模式3:
  • CPOL =1 :空闲状态时, SCK 为高电平
  • CPHA =1 SCK 第一个边沿移出数据,第二个边沿移入数据
  • 非连续传输示意图
    • 优点:使用简单,且容易封装,实际工作中仅需4行代码
    • 缺点:损失一些性能
图中只有发送的波形
  • 输出的流程和现象
第一行:SCK时钟线首先为高电平,在第一个下降沿MOSI和MISO移出数据,之后上升沿移入数据
第二行:MOSI和MISO输出波形,跟随SCK时钟变换,数据位依次出现
//此处从前到后依次出现【b0、b1……b7】——示例为【低位先行】(实际使用时高位先行更多)
第三行:TXE发送寄存器空标志位
第四行:发送缓冲器写入SPI_DR(发送数据寄存器TDR)
第五行:BSY(BUSY)由硬件自动设置和清除——当有数据传输时BUSY置1
首先SS置低电平开始时序,TXE为1(表示TDR空)表示可以写入数据开始传输
  • 指示1:软件写入【0xF1】到SPI_DR(发送数据寄存器TDR)
写入后发送缓冲器(发送数据寄存器TDR)变为【0xF1】,同时TXE为0(表示TDR有数据)
//刚开始【移位寄存器】为空,因此在等候区的数据【0xF1】就会立刻转入【移位寄存器】开始发送
转入瞬间置TXE为1(表示TDR空)
  • 区别
连续传输:一旦【TXE】为1(表示TDR空)——提前将下一个数据写到TDR里等待——数据衔接更紧密
非连续传输:【TXE】为1(表示TDR空)时——不着急把下一个数据写到TDR——一直等待至一个字节时序结束再写入下一个数据
  • 指示2:软件等待【TXE=1】,但是较晚写入【0xF2】至SPI_DR
一个字节【发送时序】结束,也意味着一个字节【接收时序】结束——接收的【RXNE】置1
接收的【RXNE】置1后,先把接收到的数据读出,再写入下一个字节数据
数据2开始发送,还是不着急写数据3,等到了发送时序结束,先接收数据2再写入数据3
总结:
1、等待TXE为1(表示TDR空)——可以往TDR写入数据
2、写入发送的数据至TDR
3、等待RXNE为1(表示RDR非空)——可以从RDR读取数据
4、读取RDR接收的数据
//将这4步封装到一个函数,调用一次就能交换一个字节
  • 缺点产生原因
TDR数据转入【移位寄存器】后(TXE由0置1——表示TDR空),没有及时将下一个数据提前写入TDR等待
因此第一个字节时序完成后,第二个字节还没有送过来,导致数据传输产生间隙,拖慢了整体数据传输的速度
//SCK频率高时影响明显

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值