stm32—SPI

news2024/11/13 8:03:34

1. SPI

SPI (Serial Peripheral Interface):是由美国摩托罗拉公司(Motorala)最先推出的一种同步全双工串行传输规范,也是一种单片机外设芯片串行扩展接口

SPI 接口主要应用在 EEPROM,FLASH,实时时钟, AD转换器,数字信号处理器和数字信号解码器之间,等要求通讯速率较高的场合

SPI 是一种高速、全双工、串行、同步通信总线

        全双工意味着至少需要有两根数据线,串行意味着是按 bit 位一位一位的传输

        同步意味着通信双方共时钟线:

                SDO        Serial Data Output        串行数据输出

                SDI          Serial Data Input           串行数据输入

                SCLK       Serial Clock                   时钟线

SPI 采用的是主从架构,支持多 slave 模式:


Master:

        SCK  ---> 同时接所有的 Slave 的时钟线

        MOSI ---> 同时接所有的 Slave 的 MOSI 数据线

        MISO ---> 同时接所有的 Slave 的 MISO 数据线

        

        SS1 ---> 接第一个 Slave 的片选信号

        SS2 ---> 接第二个 Slave 的片选信号

        ......


当 Master 要和某个 Slave 通信时:

        enable 这个 Slave

        disable 其他的 Slave

2. SPI 物理层

SPI 总线上可以同时接多个 SPI 设备 (一主多从)

        那么总线上的时钟由谁产生呢?

                谁产生都可以,只要同一时刻没有多个设备同时控制总线就可以了

                同一时刻也只能有一个设备发送数据,但是可以有多个设备同时接收

        通过谁控制时钟线,我们人为的将 SPI 总线上的设备分为:

                Master        主设备:产生时钟信号的设备

                Slave          从设备:接收时钟信号的设备
一主一从:

一主多从:

根据主从设备的区别,有时候两个数据接口命名也会有所不同:

                MOSI:Master Output Slave Input    主设备发送,从设备接收线

                MISO:Master Input Slave Output    主设备接收,从设备发送线
        MOSI 和 MISO 只是 SDO 和 SDI 的不同叫法而已

 
        SCLK:即时钟信号线,用于通讯同步

        另外,SPI 还有一根 NSS(Slave Select)线。因为SPI总线上的设备不像 IIC 总线上的设备有地址,所以我们需要一根额外的线来确定到底与谁进行通信

        这个NSS就是片选信号线,用于选择通讯的从设备,也可用CS表示,每个从设备都有一条独立的NSS信号线,主机通过将某个设备的NSS线置低电平来选择与之通讯的从设备。所以 SPI 通讯以NSS线电平置低为起始信号,以NSS线电平被拉高为停止信号,此线可以利用任何一个GPIO引脚,发送0/1进行片选 (比如#SS表示低电平有效,则发送0表示与该设备通信)

所以 SPI 一般需要 4 根线:SDO / SDI / SCLK / CS (单向传输时可以不需要 CS 线)

3. SPI 协议

协议就是规定数据是如何收发的,SPI 协议定义了通讯的起始和停止信号、数据有效性、时钟同步等内容,无应答机制


(1) 通信起始信号和停止信号

        NSS 信号线由高变低,是 SPI 通讯的起始信号,当从机检测到自己的NSS线为起始信号时,就 知道主机要与自己进行通讯了

        NSS 信号线由低变高,是 SPI 通讯的停止信号

(2) 数据有效性
        SPI 使用 MOSI 及 MISO 信号线来传输数据,使用 SCK 信号线进行数据同步。MOSI 及 MISO 数据线在 SCLK 的每个时钟周期传输一位数据,且数据输入输出是同时进行的。数据传输时, MSB 先行或 LSB 先行并没有作硬性规定,但要保证两个 SPI 通讯设备之间使用同样的协定,一般都会采用 MSB 先行模式

(3) 通讯模式
      
  CPOL:Clock Polarity  时钟极性

                时钟极性决定不传任何数据时(SPI空闲时)时钟线的电平状态

                        CPOL = 1        不传数据(SPI空闲)时,时钟线保持高电平

                        CPOL = 0      不传数据(SPI空闲)时,时钟线保持低电平


        CPHA:Clock PHAse 时钟相位

                时钟相位决定 SPI 在何时锁定数据(决定数据采集的时刻)
                        CPHA = 1        在时钟线 SCLK 的第二个边沿锁存数据(数据采集)

                        CPHA = 0        在时钟线 SCLK 的第一个边沿锁存数据(数据采集)


也就是说CPOL和CPHA的组合决定数据采集和数据发送的时刻,共四种通讯模式


CPOL = 1,CPHA = 1 通讯模式:

(4) 数据帧格式
        SPI 数据的收发是按Frame为单位,那么一帧数据传送的 bit 位数由什么决定?

                DFF:Data Frame Format 数据帧格式

                        8bits        一帧数据 8 bits

                        16bits      一帧数据 16 bits

                        SPI 数据的收发是按 Frame 为单位

                那么一帧数据又是从LSB还是MSB开始发送?
                        LSBFIRST = 1     LSB(低bit)先发送

                        LSBFIRST = 0     MSB(高bit)先发送

(5) 传输速率
        传输速率由时钟频率决定,有一个原则:就低不就高

4. 模拟 SPI 时序收发数据

5. STM32 SPI 控制器

6. STM32 固件库 SPI 函数接口说明

SDO / SDI / SCLK都是复用自GPIO(无论是主从都没有区别)。如果作为从设备,则NSS(片选)也是复用自GPIO,如果是主设备,则不需要利用GPIO去复用为NSS


(1) 配置 SPI 的 GPIO 引脚
a. 使能 GPIO 时钟   RCC_APB1PeriphClockCmd();

b. GPIO_Init();  ---> AF

c. 配置具体的复用功能   GPIO_PinAFConfig();
(2) 配置 SPI 控制器
a. 使能 SPI 时钟
    
    RCC_APBxPeriphClockCmd();

b. 配置 SPI 控制器
    
void SPI_Init(SPI_TypeDef *SPIx, SPI_InitTypeDef *SPI_InitStruct);

@SPIx:指定要配置的SPI控制器编号
        SPI1, SPI2 ... SP6

@SPI_InitStruct:指向初始化信息结构体

    typedef struct
    {
        uint16_t SPI_Direction; 
		    设置SPI的通信方式
		    可以是半双工/全双工/串行发/串行收
		        SPI_Direction_2Lines_FullDuplex	  全双工
		        SPI_Direction_2Lines_RxOnly		  (两根线半双工)只收
		        SPI_Direction_1Line_Rx			  (一根线半双工)串行接收
		        SPI_Direction_1Line_Tx			  (一根线半双工)串行发

	    uint16_t SPI_Mode;
		    设置SPI的主从模式
		        SPI_Mode_Master		主设备
		        SPI_Mode_Slave		从设备

	    uint16_t SPI_DataSize; 
		    设置SPI传输的数据位长度(数据帧的bit位数)
		        SPI_DataSize_16b   	数据位 16
		        SPI_DataSize_8b		数据位 8
	    
        uint16_t SPI_CPOL;
		    设置SPI的时钟极性(在空闲时SCK时钟线的电平状态)
		        SPI_CPOL_Low		空闲时SCK为低电平
		        SPI_CPOL_High		空闲时SCK为高电平
        
        uint16_t SPI_CPHA;
		    设置SPI的时钟相位(决定在SCK时钟线的第几个边沿采集数据)
		        SPI_CPHA_1Edge	  在第一个边沿采集数据			
                SPI_CPHA_2Edge	  在第二个边沿采集数据
    
            CPOL和CPHA的组合决定数据采集和数据发送的时刻
            需要看从设备支持哪种模式,主模式和从模式必须统一
	
        uint16_t SPI_NSS;
		    设置SPI的NSS信号是由硬件(NSS引脚)还是软件控制,可以理解为片选信号
		        SPI_NSS_Hard   	由硬件NSS引脚控制
		        SPI_NSS_Soft	由用户软件代码控制

        uint16_t SPI_BaudRatePrescaler;
		    设置SPI波特率的预分频值
	        SPI波特率(传输速率) = 
                        SPI输入时钟频率(APBx时钟) / SPI_BaudRatePrescaler

                SPI_BaudRatePrescaler_2		2分频
		        SPI_BaudRatePrescaler_4     4分频
		        ...
		        SPI_BaudRatePrescaler_256	256分频

	    uint16_t SPI_FirstBit;
		    指定SPI传输数据顺序是高位先发还是低位先发
		        SPI_FirstBit_MSB		高位先发
		        SPI_FirstBit_LSB		低位先发

        uint16_t SPI_CRCPolynomial; 
		    指定CRC(循环冗余校验)校验多项式
		    这个系数只需要大于1就可以了,为了提高通信可靠性

    } SPI_InitTypeDef;
(3) 使能 SPI
SPI_Cmd();
(4) 收发 SPI 数据,以及一些状态标志位
a. 读数据:只有 RXNE == 1 时才能读(可以利用中断去读也可以轮询)
    
怎么去获取标志位:
FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef *SPIx, uint16_t SPI_I2S_FLAG);

返回值:SET ->1 /  RESET -> 0

    标志位有:
        #define SPI_I2S_FLAG_RXNE       ((uint16_t)0x0001)
        #define SPI_I2S_FLAG_TXE       	((uint16_t)0x0002)
        #define SPI_FLAG_CRCERR         ((uint16_t)0x0010)
        #define SPI_FLAG_MODF          	((uint16_t)0x0020)
        #define SPI_I2S_FLAG_OVR        ((uint16_t)0x0040)
        #define SPI_I2S_FLAG_BSY        ((uint16_t)0x0080)
        ....

怎么读:uint16_t SPI_I2S_ReceiveData(SPI_TypeDef *SPIx);
--------------------------------------------------------------------------
举例子:利用轮询去接收数据
unsigned char SPI1_Recv_Byte(void) {	
    while (SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE) != SET);
	return SPI_ReceiveData(SPI1);
}
----------------------------------------------------------------------------
b. 发数据:只有 TXE == 1 时才能发送数据

如何发:void SPI_I2S_SendData(SPI_TypeDef *SPIx, uint16_t Data);
-----------------------------------------------------------------------------
举例子:
Void SPI1_Send_Byte(unsigned char ch) {
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != SET);
	SPI_I2S_SendData(SPI1, ch);
}

7. W25Q128

W25Q128 是一款 SPI 接口的 flash 存储器芯片

实现 在 SPI 串行Flash W25Q128 存储芯片的任意地址读写任意字节的数据
 

(1) 接口说明(见原理图)

引脚:        W25Q128                  MCU

                        CS       ----------     PB14

                       CLK      ----------     PB3
                        SO       ----------     PB4
                        SI         ----------     PB5

                        

        CS:片选引脚(低电平有效)

                当CS管脚为高电平时,芯片处在不选择的状态

                当CS管脚为低电平时,芯片处于被选择的状态(此时才能够与MCU通信)


(2) W25Q128 内部存储结构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2064307.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ORM底层的原理

2.3.面试题3:请介绍什么是ORM思想: a.什么是ORM: 1.所谓的ORM是Dao层的一种思想,意思就是对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping…

【回文数判断】输入一个5位数,判断它是不是回文数

输入一个5位数&#xff0c;判断它是不是回文数。例如12321是回文数&#xff0c;个位和万位相同&#xff0c;十位与千位相同 使用C语言实现&#xff0c;具体代码&#xff1a; #include<stdio.h>int main(){int a,b,c,d,x;printf("输入一个5位数&#xff1a;")…

ACCESS 注入实战

简介 Access数据库注入攻击是一种常见的网络安全&#xff0c;通过注入SQL代码来获取未授权的数据访问权限。这种攻击利用了应用程序与数据库之间的交互漏洞&#xff0c;攻击者通过输入特定的SQL代码片段来操纵数据库查询&#xff0c;从而绕过应用程序的安全机制&#xff0c;获取…

中移动集团SRE人员能力提升培训圆满结课

前言&#xff1a; ​在数字化转型的浪潮中&#xff0c;中移动作为通信行业的领军企业&#xff0c;面临着日益复杂的运维挑战。SRE&#xff08;Site Reliability Engineering&#xff09;作为一种新兴的运维理念&#xff0c;为中移动提供了解决这些问题的新思路。2024年7月下旬…

OpenCV几何图像变换(7)重映射函数 remap()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 应用一个通用的几何变换到图像上。 remap 函数使用指定的地图对源图像进行变换&#xff1a; dst ( x , y ) src ( m a p x ( x , y ) , m a p …

VulnStack2-主机不出网-黄金票据-SID History

网络结构 kali192.168.20.145DC10.10.10.10PC192.168.20.201/10.10.10.201WEB192.168.20.80/10.10.10.80 WEB登录时&#xff0c;切到V1.3快照 且不登录默认用户 开启weblogic服务 漏洞利用 访问Weblogic默认的console路由http://192.168.20.80:7001/console 直接用工具打一…

深信服研发面试经验分享

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330#rd 《网安面试指南》http://mp.weixin.qq.com/s?…

新手友好:易于上手的10款项目管理工具推荐

国内外主流的 10 款轻量级项目管理软件对比&#xff1a;PingCode、Worktile、Coding、致远OA、Gitee、Wrike、ClickUp、Notion、Airtable、Basecamp。 在快节奏的工作环境中&#xff0c;有效的项目管理是成功的关键&#xff0c;尤其是对于资源有限的小型团队和初创公司而言。轻…

golang实现一个简单的rpc框架

前言 RPC在分布式系统中经常使用&#xff0c;这里写一个简单的demo实践一下。 code 先生成 go.mod 文件 go mod init rpc-try01定义方法 package model// Args 是 RPC 方法的参数结构体 type Args struct {A, B int }// Arith 定义了一个简单的算术服务 type Arith struct{…

解锁 Vue 3 Teleport 的魔力

偶然遇到一个场景&#xff0c;在项目开发中蒙层是很常见的一个组件&#xff0c;我们期望它会在 body 下显示&#xff0c;但有时候代码逻辑结构很合理&#xff0c;组件结构不是很合理&#xff0c;也就是说蒙层组件不在 body 下&#xff0c;比如说&#xff1a; 蒙层组件 <te…

初识网络--网络基础概念

目录 1 网络的发展 2 协议 ​编辑 3 网络传输的流程 局域网 跨网络通信 1 网络的发展 计算机是被人设计出来&#xff0c;为人提供计算服务的&#xff0c;而人是需要协作的&#xff0c;那么就注定计算机之间也必须要协作&#xff0c;计算机之间的协作就是靠互通数据来完成…

MySQL的源码安装

目录 1 编译前的准备 1.1 安装cmake 1.2 安装gcc 2 源码编译安装 2.1 使用cmake检查环境并指定路径 2.2 使用 make 进行源码编译 2.3 使用 make install 安装MySQL 3 MySQL源码安装环境配置 3.1 创建mysql 用户 3.2 编辑my.cnf 文件 3.3 conkconfig 创建开机自启服务 3.4 配置…

这 2 个 GitHub 项目,YYDS!

01 &#x1f9e0; 构建你的第二大脑&#xff1a;SuperMemory 在这个信息爆炸的时代&#xff0c;我们每天都在互联网上浏览和保存大量的信息&#xff0c;但往往这些宝贵的数据就像被扔进了黑洞&#xff0c;再也没有被回顾和利用。 SuperMemory 开源项目应运而生&#xff0c;旨在…

OLED(hal库)、OLED取模

目录 OLED&#xff08;hal库&#xff09; IIC通讯协议 软件IIC ​编辑 硬件IIC 移植OLED代码 代码测试 ​编辑 测试 这是我改好滴文件 OLED取模 软件 ​编辑文字 图片 OLED&#xff08;hal库&#xff09; IIC通讯协议 软件IIC 软件I2C&#xff08;或IIC&…

:class的用法及应用

参考小满视频 在同一个标签中&#xff0c;class只能有一个&#xff0c;:class也只能有一个 :class的用法 1. :class “非响应式的变量”&#xff08;一般不使用&#xff0c;和写死了一样&#xff09; const a "style1" <span :class"a"></spa…

JSONP实现跨域访问

JSONP实现跨域访问 课程目标 1、理解JSONP跨域访问的解决方案和实现原理 2、能够利用JavaScript后台和JQuery实现跨域处理 3、理解JavaScript后台代码回调的工作机制&#xff0c;并实现代码回调 4、综合上述&#xff0c;利用JSONP实现跨域访问 一、生成JSON响应 1、生成…

Nginx--监控

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 一、Nginx的基础监控 进程监控 端口监控 注意&#xff1a; 这两个是必须要加在zabbix监控&#xff0c;加触发器有问题及时告警。 nginx 提供了ngx…

8-9月强化速成|30天带刷《严选题》《660》

如果你的目标是90-100分&#xff0c;肯定是够了&#xff0c;但是像下面这样微调一下更好 你的基础阶段做的是辅导讲义上的题目&#xff0c;那么你的基础阶段的题量肯定是够了。 但是强化阶段如果只做660题和严选题&#xff0c;这个题量还有有一些薄弱的&#xff0c;建议可以把…

在线BLOG网

TOC springboot0785在线BLOG网 第1章 绪论 1.1课题背景 计算机的普及和互联网时代的到来使信息的发布和传播更加方便快捷。人们可以通过计算机上的浏览器访问多个应用系统&#xff0c;从中获取一些可以满足用户生活需求的管理系统。网站系统有时更像是一个大型“展示平台”…

【MySQL】半同步模式

1 半同步模式原理 1. 用户线程写入完成后 master 中的 dump 会把日志推送到 slave 端 2.slave 中的 io 线程接收后保存到 relaylog 中继日志 3. 保存完成后 slave 向 master 端返回 ack 4. 在未接受到 slave 的 ack 时 master 端时不做提交的&#xff0c;一直处于等待当收到…