学习STM32第十五天

SPI外设

一、简介

STM32F4XX内部集成硬件SPI收发电路,可以由硬件自动执行时钟生成、数据收发等功能,减轻CPU负担,可配置8位/16位数据帧,高位(最常用)/低位先行,三组SPI接口,支持DMA

SPI框图
由上图可知SPI是通过接收/发送缓冲区移位寄存器进行通信,其中SPI1是在APB2总线,SPI2、SPI3在APB1总线。发送和接收共用一个SR,即SPI是同步通信接口。SS引脚一般用GPIO口指定从机,硬件NSS引脚一般是用来配置多主机模式。
发送:数据先进入TDR,经SR通过MOSI向从机输出
接收:数据由MISO进入SR,然后经过RDR向地址数据总线输出
由此可对上面SPI框图进行简化,基本结构如下
SPI基本结构
这里给出SPI主模式全双工连续传输模式下的时序图,SPI主模式全双工
上图选择的是模式3,SCK高电平为空闲状态,在SCK第一个边沿移出数据,第二个编译移入数据。上面时序图采用小端模式,低位先行,这里对进行分析
发送:

  • SS置低电平,开始时序,选中从机。此时TXE = 1,TDR为空;RXNE = 0,RDR为空。BSY = 1
  • 软件写入0xF1到SPI_DR,即要发送的第一个数据,此时TXE = 0,RXNE = 0,TDR非空
  • TDR中的0xF1会立刻转入到SR中,TDR清空,MOSI开始发送同时TXE = 1
  • 软件等待TXE = 1,然后写入0xF2到SPI_DR,即要发送的第二个数据,此时TXE = 0,RXNE = 0
  • TDR中的0xF2会随后自动进入SR,MOSI在发送完第一个数据会自动发送第二个数据
  • TDR发送完所有数据,TXE会自动置1,SR发送完所有数据后,BSY = 0

接收:

  • SS置低电平,开始时序,选中从机。此时TXE = 1,TDR为空;RXNE = 0,RDR为空。BSY = 1
  • MISO依次接收从机的数据,输出到SR
  • SR中的数据以小端模式进入到SPI_DR中
  • 软件等待RXNE = 1,然后数据总线读取RDR中的数据0xA1,同时RXNE = 0,RDR变为空
  • MISO接收第二个数据,输出到SR
  • SR中的第二个数据以小端模式进入到SPI_DR中
  • 软件等待RXNE = 1,然后数据总线读取RDR中的第二个数据,同时RXNE = 0,RDR变为空
  • RDR接收完所有数据,RXNE = 0

由上图可知,SPI全双工连续通信是交叉进行的,发送数据1,发送数据2,再接收数据1;发送数据3,再接收数据2;在时序上要求操作之间的间隙非常小。
SPI非连续全双工通信
非连续传输模式,只需要四行代码。上图是SPI模式3,SCK高电平为空闲状态,分析如下

  • SS置低电平,选中从机,开始时序此时TXE = 1,RXNE = 0,TDR为空
  • 软件写入0xF1到SPI_DR,此时TDR = 0xF1,TXE = 0
  • TDR中的0xF1立即进入SR中,MOSI开始发送0xF1,TDR清空,TXE = 1
  • 等待MOSI将第一个字节数据发送完毕,此时接收第一个字节数据的时序也完成,即RXNE = 1
  • 读取接收到的第一个字节数据,然后将第二个字节数据写入TDR,开始发送第二个数据
  • 等待MOSI发送完第二个字节数据,此时接收到了第二个字节数据
  • 读取完第二个字节数据,然后将第三个字节数据写入TDR,开始发送第三个数据

整体流程就是:等待TXE = 1,写入数据到TDR,等待RXNE = 1,读取RDR数据。这样实现发送数据1接收数据1,发送数据2接收数据2。但是字节之间存在一定的间隙,降低传输效率。

二、实验案例

进行STM32F4XX对板载W25Q16读写,代码如下

#include "stm32f4xx.h"                  // Device header//硬件SPI通信,采用非连续传输方案
/*PB0引脚模拟SS输出*/
void MySPI_W_SS(uint8_t BitValue)
{GPIO_WriteBit(GPIOB, GPIO_Pin_0, (BitAction)BitValue);//片选引脚输出
}/*SS->PB0,MISO->PB4,MOSI->PB5,SCK->PB3,板载W25Q16支持SPI模式0和模式3*/
/*
*	SPI1是在APB2总线,SPI2、SPI3在APB1总线
*	PB3: SPI1_SCK、SPI3_SCK
*	PB4: SPI1_MISO、SPI3_MISO
*	PB5: SPI1_MOSI、SPI3_MOSI
*	PB0: 使用GPIO模拟SS
*/
void MySPI_Init()
{RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;	//PB3复用为SPI1_SCK,PB4复用为SPI1_MISO,PB5复用为SPI1_MOSIGPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;				//使用GPIO模拟片选信号SSGPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI1);	//GPIO引脚复用GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_SPI1);GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI1);//SPI配置SPI_InitTypeDef SPI_InitStructure;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;SPI_InitStructure.SPI_CRCPolynomial = 7;				//CRC校验根据实际需求填写SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;		//数据帧大小SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//全双工SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;		//高位先行SPI_InitStructure.SPI_Mode = SPI_Mode_Master;			//这里选择主机SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;				//软件模拟片选SSSPI_Cmd(SPI1, ENABLE);//	MySPI_W_SS(1);											//默认是终止条件
}/*起始条件*/
void MySPI_Start()
{MySPI_W_SS(0);
}
/*终止条件*/
void MySPI_End()
{MySPI_W_SS(1);
}
/*交换一个字节,这里选择模式0*/
/*			SCK低电平为空闲状态
*	SS下降沿启动,主机移出高位数据到MOSI
*	SCK上升沿,主机移入高位数据MISO
*	SCK下降沿,主机移出高位数据MOSI
*			非连续传输需要四步
*/
uint8_t MySPI_SwapByte_Mode0(uint8_t ByteSend)
{while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != SET);	//等待TXE = 1SPI_I2S_SendData(SPI1, ByteSend);								//将数据写入到DR中while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != SET);	//等待RXNE = 1return SPI_I2S_ReceiveData(SPI1);								//读取RDR的数据
}

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

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

相关文章

《AI编程类工具之四——GitHub copiot》

一.简介 官网:https://github.com/features/copilot GitHub Copilot是由GitHub和OpenAI合作开发的一款人工智能编程助手。这款工具基于OpenAI的GPT-3模型进行训练,旨在帮助开发者更高效地编写代码。 二.功能介绍 智能代码补全:GitHub Cop…

.NetCore——自定义筛选器

【异常筛选器】 在 ASP.NET Core Web API 中,异常处理是一个非常重要的环节,如果程序中出现未处理异常,就会生成响应报文。通过捕获和处理异常,我们可以确保应用程序的健壮性,并向用户提供友好的错误响应。ASP.NET Core 提供了一种机制,即异常筛选器(Exception Filters…

第一篇【传奇开心果系列】我和AI面对面聊编程:深度比较PyQt5和tkinter.ttk

传奇开心果系列博文 系列博文目录我和AI面对面聊编程系列 博文目录前言一、今天我们面对广大读者选择PyQt5和tkinter.ttk做比较这个话题目的是什么?二、举一个最简单的pyqt5信号和插槽的例子三、这和tkinter的点击事件有什么区别?四、如何选择&#xff1…

MySQL Explan执行计划详解

Explan执行计划 首先我们采用explan执行计划 执行一条sql,发现返回了12个列,下面会详细解释每一列 1、ID列 id列的值是代表了select语句执行顺序,是和select相关联的;id列的值大的会优先执行,如果id列为空最后执行&a…

数据库的创建

数据库分类 通过查看对象资源管理器来区分数据库类型 数据库物理文件的组成 : 数据库文件 日志文件 创建一个主数据文件和一个日志文件

上线流程及操作

上节回顾 1 搜索功能-前端:搜索框,搜索结果页面-后端:一种类型课程-APIResponse(actual_courseres.data.get(results),free_course[],light_course[])-搜索,如果数据量很大,直接使用mysql,效率非常低--》E…

kafka安装与相关配置详解

一、安装 1、下载与解压 tar -xzf kafka_2.13-3.7.0.tgz cd kafka_2.13-3.7.02、启动 bin/kafka-server-start.sh config/server.properties3、后台启动 bin/kafka-server-start.sh -daemon config/server.properties4、zookeeper [admin, brokers, cluster, config, con…

淘宝商品数据抓取新策略:API接口助力获取标题、分类与店铺名

随着电子商务的迅猛发展,淘宝作为中国最大的网络购物平台,其商品数据对于众多商家、研究者和市场分析师来说具有极高的价值。然而,如何高效、准确地抓取淘宝商品数据,尤其是商品标题、分类和店铺名等关键信息,一直是一…

nginx部署上线

1. windows配置nginx 打包命令 npm run build:prod 1. 安装 nginx mac windows 2. mac / windows 环境下ngnix部署启动项目 2. nginx 解决 history 的 404 问题 3. nginx配置代理解决生产环境跨域问题

极速、易用、高度定制化的开源社区交流平台:Flarum

Flarum:轻盈高效,引领未来社区互动新风尚的革命性论坛平台- 精选真开源,释放新价值。 概览 Flarum是一款精心打造的现代网站讨论平台,以其精炼高效而著称。作为 esoTalk 和 FluxBB 的理念和技术的集大成者,Flarum 致力…

Ubuntu 20.04 LTS 在3588安卓主板上测试yolov8-1.0版本的yolov8n-seg模型

0. 创建虚拟环境 #!< 创建虚拟环境yolov8 $ sudo pip install virtualenv $ sudo pip install virtualenvwrapper $ mkvirtualenv yolov8 -p /usr/bin/python3.81. 将yolov8n-seg.pt转换为yolov8n-seg.onnx文件 #!< 创建项目目录yolov8-rknn并下载yolov8n-seg.pt模型文…

Asp.Net Core中的进程内托管与进程外托管模型

在ASP.NET Core中&#xff0c;托管模型决定了应用程序如何运行及其与Web服务器交互的方式。主要有两种托管模式&#xff1a;进程内托管&#xff08;In-Process Hosting&#xff09;和进程外托管&#xff08;Out-of-Process Hosting&#xff09;。每种模式都有自己的优势和使用场…

FlinkSQL State的生命周期

FlinkSQL未显示配置state生命周期 FlinkSQL默认没有配置state 的过期时间。也就是说默认情况是FlinkSQL从不清除状态。如果状态后端保存在rocksdb中&#xff0c;直到本地磁盘被打满&#xff0c;服务挂掉&#xff0c;报错如下&#xff1a; java.io.IOException: [bf3ba881614e…

Python中的异步编程如何工作? —— 理解asyncio库和异步IO的原理

在Python中&#xff0c;异步编程是通过asyncio库和异步IO实现的。异步编程的目的是可以同时执行多个任务&#xff0c;而不需要等待任务完成。 asyncio库是Python 3.4版本引入的标准库&#xff0c;提供了一种基于协程的异步编程模型。协程是一种可以暂停和恢复执行的函数&#…

虚拟机vm桥接模式linux(centos,ubuntu)联网

台式机网线 查看宿主机网络 编辑虚拟机—>虚拟网络编辑器–>更改设置 选择&#xff0c;确定 进入linux系统 输入ip addr找到自己的网卡 我的是eno16777736 centos&#xff1a; 编辑 HWADDR"00:0C:29:54:CE:B8" TYPE"Ethernet" BOOTPROTO"…

公网IP多少钱可以购买?

公网IP是指可以在全球范围内访问和识别的唯一IP地址。对于许多企业和个人用户来说&#xff0c;公网IP是实现远程访问、搭建服务器、建立安全连接等重要需求的基础。公网IP的获取并不是免费的&#xff0c;并且价格因供应商和地区而异。 现有公网IP市场 当前&#xff0c;市场上有…

博弈论和sg函数

Nim游戏 题目链接&#xff1a;Nim游戏 先说结论&#xff1a;假设n堆石子&#xff0c;石子数分别为a1,a2,a3.....&#xff0c;则当a1^a2^a3^...^an0时先手必败&#xff0c;否则先手必胜。 因为所表示的二进制位必定是成对出现的&#xff0c;根据性质 1 ^ 1 0 &#xff0c;0 …

对 Seata 的理解

在微服务架构下&#xff0c;由于数据库和应用服务的拆分&#xff0c;导致原本一个事务单元中的多个DML操作&#xff0c;变成了跨进程或者跨数据库的多个事务单元的多个 DML 操作&#xff0c;而传统的数据库事务无法解决这类的问题&#xff0c;所以就引出了分布式事务的概念。 …

Linux命令-dstat命令(通用的系统资源统计工具)

说明 dstat命令 是一个用来替换vmstat、iostat、netstat、nfsstat和ifstat这些命令的工具&#xff0c;是一个全能系统信息统计工具。与sysstat相比&#xff0c;dstat拥有一个彩色的界面&#xff0c;在手动观察性能状况时&#xff0c;数据比较显眼容易观察&#xff1b;而且dsta…

Pytorch:张量的形状操作

文章目录 一、维度改变1.flatten展开a.函数的基本用法b.示例 2.unsqueeze增维a.函数的基本用法b.示例 3.squeeze降维a.函数的基本用法b.示例 二、张量变形1.view()a.函数的基本用法b.参数&#xff1a;c.注意事项d.示例 2.reshape()a.注意事项b.示例 3.reshape_as()a.函数的基本…