STM32的串行外设接口SPI

news2024/11/28 10:43:32

一、SPI简介

1.SPI总线特点

        (1)四条通信线

        SPI需要SCK、MISO、MOSI、NSS四条通信线来完成数据传输 ,每增加一个从机,多一条NSS通信线。

        (2)多主多从

        SPI总线允许有多个主机和多个从机。

        (3)传输速率

        比常见的I2C协议要快,通常为Mbit级别。

        (4)通信方式 

         是同步全双工串行通信,每次交换一个字节(8bit)或者两个字节(16bit),可选择高位先行或者低位先行。

2.SPI总线术语

  • SCK:串行时钟线,作为主设备的输出、从设备的输入。

  • MISO:主机输入/从机输出数据线,该引脚在主模式下接收数据,在从模式下发送数据。

  • MOSI:主机输出/从机输入数据线,该引脚在主模式下发送数据,在从模式下接收数据。

  • NSS:低电平有效的从机选择线。NSS引脚是可选的,一般选择用软件管理。

3.SPI硬件构成

        所有SPI设备的SCKMOSIMISO分别连在一起,主机另外引出多条NSS控制线,分别接到各从机的NSS引脚,输出引脚配置为推挽输出,输入引脚配置为浮空或上拉输入。

 4.位传输

        (1)起始信号 

                SS引脚从高电平切换到低电平 。

        (2)终止信号 

                SS引脚从低电平切换到高电平 。

5.数据传输模式 

        在使用STM32的SPI外设时,需要设置时钟相位(CPHA)和时钟极性(CPOL)。 

 (1)模式0
  • CPOL=0:空闲状态时,SCK为低电平 
  • CPHA=0:SCK第一个边沿移入数据,第二个边沿移出数据

(2)模式1
  • CPOL=0:空闲状态时,SCK为低电平 
  • CPHA=1:SCK第一个边沿移出数据,第二个边沿移入数据

(3)模式2
  • CPOL=1:空闲状态时,SCK为高电平 
  • CPHA=0:SCK第一个边沿移入数据,第二个边沿移出数据

 (4)模式3
  • CPOL=1:空闲状态时,SCK为高电平 
  • CPHA=1:SCK第一个边沿移出数据,第二个边沿移入数据

 二、STM32的SPI外设

1.STM32的SPI外设的特性:

  • 8位或16位传输帧格式
  • 可选的时钟频率、高/低位先行
  • 支持多主模式
  • 可触发中断的专用发送和接收标志、主模式故障、过载以及CRC错误标志
  • SPI总线忙状态标志
  • 支持DMA功能的1字节发送和接收缓冲器,产生发送和接收请求
  • 兼容I2S协议

2.STM32 SPI外设的基本结构:

 3.状态标志

        应用程序可以通过TXE、RXNE和BUSY三个状态标志来完全监控SPI总线的状态。

        (1)发送缓冲器空闲标志(TXE) 

        此标志为1时表示发送缓冲器为空,可以写下一个待发送的数据进入缓冲器中。 

         (2)接收缓冲器非空标志(RXNE)

        此标志为1时表示接收缓冲器中包含有效的接收数据。 

        (3)忙标志(BUSY)

        此标志为1时表示SPI正忙于通信,但有一个例外:在主模式下的双向接收模式下,在接收期间BUSY标志保持为低。

三、STM32 SPI外设的通信方式 

 1.主模式

        在SPI主模式下,MOSI引脚是数据输出,而MISO是数据输入,SCK引脚产生串行时钟。 

 2.从模式

        在 SPI从模式下,MOSI引脚是数据输入,而MISO是数据输出,SCK引脚用于接收来自主机的串行时钟。

四、STM32 SPI外设使用流程 

        虽然不同器件实现的功能不同,但是只要遵循SPI协议,其通信方式都是一样的,配置流程也基本相同。对于STM32,首先要对SPI进行配置,使其能够正常工作,再结合不同器件的驱动程序,完成STM32与不同器件的数据传输。这里只介绍STM32作为主机的使用流程,使用流程和参考代码如下:

  1. 配置GPIO
  2. 配置SPI
  3. 写一个产生起始条件的函数
  4. 写一个产生终止条件的函数
  5. 写一个交换数据的函数
void SPI_W_SS(uint8_t Bit)          //根据Bit设置SS引脚的电平
{
	GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)Bit);		
}



void SPI_Init(void)                 //配置GPIO和SPI
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
	

	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);					
    //将PA4引脚初始化为推挽输出,作为NSS片选引脚
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);					
    //将PA5和PA7引脚初始化为复用推挽输出,即配置SCK和MOSI
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);					
    //将PA6引脚初始化为上拉输入,即配置为MISO
	



	SPI_InitTypeDef SPI_InitStructure;						
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;			//模式,选择为SPI主模式
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
                                                            //方向,选择2线全双工
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;		//数据宽度,选择为8位
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;		//先行位,选择高位先行
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;	
                                                            //波特率分频,选择128分频
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;				//SPI极性,选择低极性
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;			
                                //SPI相位,选择第一个时钟边沿采样,极性和相位决定选择SPI模式0
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;				//NSS,选择由软件控制
	SPI_InitStructure.SPI_CRCPolynomial = 7;				//CRC多项式,暂不用,给默认值7
	SPI_Init(SPI1, &SPI_InitStructure);						
	

	SPI_Cmd(SPI1, ENABLE);									//使能SPI1,开始运行
	

	MySPI_W_SS(1);											//NSS默认高电平
}




void MySPI_Start(void)                          //产生起始信号
{
	MySPI_W_SS(0);	//拉低SS
}



void MySPI_Stop(void)                           //产生终止信号
{
	MySPI_W_SS(1);	//拉高SS
}




uint8_t MySPI_SwapByte(uint8_t ByteSend)        //交换一个字节数据
{

	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != SET);	
    //等待发送数据寄存器空
	
	SPI_I2S_SendData(SPI1, ByteSend);								
    //写入数据到发送数据寄存器,开始产生时序
	
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != SET);	
    //等待接收数据寄存器非空
	
	return SPI_I2S_ReceiveData(SPI1);								
    //读取接收到的数据并返回
}

 代码仅供参考,具体使用需要结合相关从机器件的开发文档。

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

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

相关文章

再见 ESNI,你好 ECH!—— ECH的前世今生

译者注:2024 年 9 月 25 日,Cloudflare 宣布再次推出 ECH 功能。借此契机,本人翻译了 Cloudflare 介绍 ECH 的博文 Good-bye ESNI, hello ECH! ,以便科普ECH的发展历程。 现代互联网上的大多数通信都经过加密,以确保其…

Flink源码剖析

写在前面 最近一段时间都没有更新博客了,原因有点离谱,在实现flink的两阶段提交的时候,每次执行自定义的notifyCheckpointComplete时候,好像就会停止消费数据,完成notifyComplete后再消费数据;基于上述原因…

在Stable Diffusion WebUI中安装SadTalker插件时几种错误提示的处理方法

SD中的插件一般安装比较简单,但也有一些插件安装会比较难。比如我在安装SadTalker时,就遇到很多问题,一度放弃了,后来查了一些网上攻略,自己也反复查看日志,终于解决,不吐不快。 一、在Stable …

ElasticSearch高级功能详解与读写性能调优

目录 1. ES数据预处理 1.1 Ingest Node Ingest Node VS Logstash 1.2 Ingest Pipeline Pipeline & Processor 创建pipeline 使用pipeline更新数据 借助update_by_query更新已存在的文档 1.3 Painless Script Painless的用途: 通过Painless脚本访问字…

(17)MATLAB使用伽马(gamma)分布生成Nakagami-m分布的方法1

文章目录 前言一、使用伽马分布生成Nakagami分布随机变量的方法一二、MATLAB仿真代码后续 前言 MATLAB在R2013a版本中引入Nakagami分布对象,可以用来生成Nakagami随机变量。但是在更早的MATLAB版本中,并没有可以直接生成 Nakagami分布的随机变量的内置的…

C++之多态篇(超详细版)

1.多态概念 多态就是多种形态,表示去完成某个行为时,当不同的人去完成时会有不同的形态,举个例子在车站买票,可以分为学生票,普通票,军人票,每种票的价格是不一样的,当你是不同的身…

【JAVA开源】基于Vue和SpringBoot的旅游管理系统

本文项目编号 T 063 ,文末自助获取源码 \color{red}{T063,文末自助获取源码} T063,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析5.4 用例设计 六、核…

【STM32开发之寄存器版】(二)-USART

一、前言 串口作为STM32的重要外设,对程序调试具有不可替代的作用。通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换。USART利用分数波特率发生器提供宽范围的波特率选择。其主要具备以下特性&am…

Nacos入门指南:服务发现与配置管理的全面解析

Nacos 是一个用于动态服务发现、配置管理和服务管理的平台。它由阿里巴巴开源,旨在帮助开发者更轻松地构建云原生应用。Nacos 支持多种环境下的服务管理和配置管理,包括但不限于 Kubernetes、Docker、虚拟机等。 一、Nacos的主要功能 1. **服务发现与健康…

GS-SLAM论文阅读笔记-CaRtGS

前言 这篇文章看起来有点像Photo-slam的续作,行文格式和图片类型很接近,而且貌似是出自同一所学校的,所以推测可能是Photo-slam的优化与改进方法,接下来具体看看改进了哪些地方。 文章目录 前言1.背景介绍GS-SLAM方法总结 2.关键…

认知杂谈97《兼听则明,偏听则暗》

内容摘要: 在信息爆炸的时代,我们被各种信息包围,这些信息往往经过精心设计以吸引注意力和影响观点。为了避免被操控,我们需要从多个渠道获取信息,并培养批判性思维来分析信息的真实性和偏见。 提高信息素养&#xff0…

读数据湖仓07描述性数据

1. 描述性数据 1.1. 基础数据中包含不同类型的数据,而不同类型数据的描述性数据也存在显著的差异 1.2. 尽管这些描述性数据存在根本性的差异,但通过描述性数据,我们可以全面了解基础数据中的数据 1.3. 通过分析基础设施中提供的描述性数据…

基于CAN总线的STM32G4 Bootloader设计说明

1 设计目的 根据芜湖铂科新能源自身企业发展需要,开发一款基于ST公司STM32G4系列MCU(具体开发用型号STM32G473和STM32G431微处理器)的CAN总线bootloader,方便应用程序的刷写。CAN设备采用周立功CAN卡(USBCAN-II、CAN-…

Docker安装人大金仓(kingbase)关系型数据库教程

人大金仓数据库(KingbaseES)是由中国人民大学金仓公司研发的一款自主知识产权的关系型数据库管理系统。 官网地址:https://www.kingbase.com.cn/ 本章教程,主要介绍如何用Docker安装启动人大金仓(kingbase)关系型数据库。 一、下载镜像 下载地址:https://www.kingbase.c…

【黑马软件测试三】web功能测试、抓包

阶段三,内容看情况略过 Web功能测试链接测试表单测试搜索测试删除测试cookies/session测试数据库测试抓包工具的使用一个APP的完整测试流程熟悉APP业务流程功能测试APP专项测试兼容性安装、卸载和升级交叉测试(干扰测试)push消息测试用户体验测试 Web功能测试 通过…

Python画笔案例-075 绘制趣味正方形

1、绘制趣味正方形 通过 python 的turtle 库绘制 趣味正方形,如下图: 2、实现代码 绘制趣味正方形,以下为实现代码: """趣味正方形.py画个正方形后,单击它会移动,并且碰到边缘就反弹。这个版本采用画布的move命令让当前线条项目移动实现的。也可以用纯动画…

华夏ERP账号密码泄露漏洞

漏洞描述 华夏ERP账号密码泄露漏洞 漏洞复现 FOFA "jshERP-boot" POC IP/jshERP-boot/user/getAllList;.ico

解决 IntelliJ IDEA 中 JSP 页面无法识别 getParameter() 方法的问题

目录 背景: 过程: getParameter优点&#xff1a; 背景: 在IDEA中&#xff0c;我正在编写一个.jsp文件&#xff0c;想要测试一下数据是否能够从HTTP请求中成功获取到userId参数的数据&#xff0c;下面代码是我用来测试的&#xff0c;但是出现了错误。 <% String userId …

【EXCEL数据处理】000016案例 vlookup函数。

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 【EXCEL数据处理】000016案例 vlookup函数。使用的软件&#xff1a;off…

SpringBoot整合QQ邮箱

SpringBoot可以通过导入依赖的方式集成多种技术&#xff0c;这当然少不了我们常用的邮箱&#xff0c;现在本章演示SpringBoot整合QQ邮箱发送邮件.... 下面按步骤进行&#xff1a; 1.获取QQ邮箱授权码 1.1 登录QQ邮箱 1.2 开启SMTP服务 找到下图中的SMTP服务区域&#xff0c;…