首页 > 其他分享 >STM32的SPI接口详解

STM32的SPI接口详解

时间:2024-07-11 22:30:35浏览次数:11  
标签:SCK SPI5 STM32 SPI Init Handler GPIO 详解

目录

1.SPI简介

2.SPI工作原理

3.SPI时序

3.1 CPOL(Clock Polarity,时钟极性):

3.2 CPHA(Clock Phase,时钟相位):

3.3  四种工作模式

4.相关代码

4.1使能片选信号

4.2使能通讯线

4.3初始化SPI

4.4设置SPI速度

4.5读写数据


1.SPI简介

STM32 的SPI(Serial Peripheral Interface)是一个串行外设接口,它允许STM32微控制器与其他设备(如传感器、存储器等)进行高速、全双工、同步的串行通信。通常包含SCK(串行时钟)、MOSI(主设备输出/从设备输入)、MISO(主设备输入/从设备输出)和NSS(片选信号)这4条线,支持多个从设备连接到一个主设备上。

2.SPI工作原理

MISO   主设备数据输入,从设备数据输出。
MOSI   主设备数据输出,从设备数据输入。
SCLK   时钟信号,由主设备产生。
CS       从设备片选信号,由主设备控制。

主机和从机都存在一个移位寄存器,主机将要传输的数据保存到移位寄存器上,然后通过MOSI发送到从机的移位寄存器上,从机同时也将自己移位寄存器保存的数据通过MISO发送到主机的移位寄存器中,这样就完成了一次主机和从机的数据交换,如果是进行写操作,主机只要无视从机返回的数据就可以了,如果是进行读操作,那么主机就要发送对应字节的空字节来推动从机的数据传输

3.SPI时序

SPI通过CS片选设备以后开启数据传输,数据传输根据主机CPHA(Clock Phase,时钟相位)和CPOL(Clock Polarity,时钟极性)配置的不同衍生出了不同的工作模式。

3.1 CPOL(Clock Polarity,时钟极性):

CPOL决定了SPI通信中空闲状态的时钟电平。

当CPOL=0时,空闲状态下SCK(Serial Clock,串行时钟)为低电平。
当CPOL=1时,空闲状态下SCK为高电平。

3.2 CPHA(Clock Phase,时钟相位):

CPHA决定了数据是在SCK的第一个边沿还是第二个边沿被采样。

当CPHA=0时,数据在SCK的第一个边沿被采样(对于MOSI是上升沿,对于MISO可能是下降沿,取决于具体实现)。
当CPHA=1时,数据在SCK的第二个边沿被采样(对于MOSI是下降沿,对于MISO可能是上升沿)。

CPHA的选择影响数据传输的时序和稳定性。

3.3  四种工作模式

通过CPOL和CPHA的不同值组合,可以实现SPI的四种模式:

模式1 (CPOL=0, CPHA=0):空闲时SCK为低电平,数据在SCK的第一个上升沿被主设备发送,并在第一个下降沿被从设备接收。
模式2 (CPOL=0, CPHA=1):空闲时SCK为低电平,数据在SCK的第二个上升沿被采样。
模式3 (CPOL=1, CPHA=0):空闲时SCK为高电平,数据在SCK的第一个下降沿被主设备发送,并在第一个上升沿被从设备接收。
模式4 (CPOL=1, CPHA=1):空闲时SCK为高电平,数据在SCK的第二个下降沿被采样。

4.相关代码

本文基于STM32F429的HAL库为例讲解一下相关代码。

4.1使能片选信号

#define	W25QXX_CS 		PFout(6)  		//W25QXX的片选信号


GPIO_InitTypeDef GPIO_Initure;
    
 __HAL_RCC_GPIOF_CLK_ENABLE();           //使能GPIOF时钟
    
//PF6
GPIO_Initure.Pin=GPIO_PIN_6;            //PF6
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽输出
GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
GPIO_Initure.Speed=GPIO_SPEED_FAST;     //快速         
HAL_GPIO_Init(GPIOF,&GPIO_Initure);     //初始化
    
W25QXX_CS=1;			                //SPI 不选中

使能GPIO_PF6为SPI的片选信号,默认拉高不选中。

4.2使能通讯线

 GPIO_InitTypeDef GPIO_Initure;
    
 __HAL_RCC_GPIOF_CLK_ENABLE();       //使能GPIOF时钟
 __HAL_RCC_SPI5_CLK_ENABLE();        //使能SPI5时钟
    
 //PF7,8,9
 GPIO_Initure.Pin=GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
 GPIO_Initure.Mode=GPIO_MODE_AF_PP;              //复用推挽输出
 GPIO_Initure.Pull=GPIO_PULLUP;                  //上拉
 GPIO_Initure.Speed=GPIO_SPEED_FAST;             //快速            
 GPIO_Initure.Alternate=GPIO_AF5_SPI5;           //复用为SPI5
 HAL_GPIO_Init(GPIOF,&GPIO_Initure);

使能SPI5,GPIO_F7/F8/F9推挽输出,默认上拉,快速,复用为SPI5。

4.3初始化SPI

void SPI5_Init(void)
{
    SPI5_Handler.Instance=SPI5;                         //SP5
    SPI5_Handler.Init.Mode=SPI_MODE_MASTER;             //设置SPI工作模式,设置为主模式
    SPI5_Handler.Init.Direction=SPI_DIRECTION_2LINES;   //设置SPI单向或者双向的数据模式:SPI设置为双线模式
    SPI5_Handler.Init.DataSize=SPI_DATASIZE_8BIT;       //设置SPI的数据大小:SPI发送接收8位帧结构
    SPI5_Handler.Init.CLKPolarity=SPI_POLARITY_HIGH;    //串行同步时钟的空闲状态为高电平
    SPI5_Handler.Init.CLKPhase=SPI_PHASE_2EDGE;         //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
    SPI5_Handler.Init.NSS=SPI_NSS_SOFT;                 //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
    SPI5_Handler.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_256;//定义波特率预分频的值:波特率预分频值为256
    SPI5_Handler.Init.FirstBit=SPI_FIRSTBIT_MSB;        //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
    SPI5_Handler.Init.TIMode=SPI_TIMODE_DISABLE;        //关闭TI模式
    SPI5_Handler.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE;//关闭硬件CRC校验
    SPI5_Handler.Init.CRCPolynomial=7;                  //CRC值计算的多项式
    HAL_SPI_Init(&SPI5_Handler);//初始化
    
    __HAL_SPI_ENABLE(&SPI5_Handler);                    //使能SPI5
	
    SPI5_ReadWriteByte(0Xff);                           //启动传输
}

设置SPI为主机工作模式,双线模式,空闲状态为高电平,数据为8位帧结构,二个跳变沿(上升或下降)数据被采样,片选信号由软件控制,数据传输从MSB位开始,关闭硬件CRC校验,最后启动传输。

我们把 SPI5 的频率设置成了最低的256 分频,后面我们可以随时通过函数 SPI5_SetSpeed 来设置 SPI5 的速度。

4.4设置SPI速度

void SPI5_SetSpeed(u8 SPI_BaudRatePrescaler)
{
    assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));//判断有效性
    __HAL_SPI_DISABLE(&SPI5_Handler);            //关闭SPI
    SPI5_Handler.Instance->CR1&=0XFFC7;          //位3-5清零,用来设置波特率
    SPI5_Handler.Instance->CR1|=SPI_BaudRatePrescaler;//设置SPI速度
    __HAL_SPI_ENABLE(&SPI5_Handler);             //使能SPI
    
}

SPI_BaudRatePrescaler 可以设置 2/4/8/16/32/64/128/256分频,例如STM32F429的APB1为90MHz,设置2分频就是45MHz。

4.5读写数据

void read(){

    W25QXX_CS=0;//拉低片选信号      
    SPI5_ReadWriteByte(0XFF);
    W25QXX_CS=1; //拉高片选信号      
}

u8 SPI5_ReadWriteByte(u8 TxData)
{
    u8 Rxdata;
    HAL_SPI_TransmitReceive(&SPI5_Handler,&TxData,&Rxdata,1, 1000);       
 	return Rxdata;          		    //返回收到的数据		
}

读写数据都是用SPI5_ReadWriteByte这个函数,不同的是,如果是写入数据,不用管接收到的从机数据是什么,如果是读取数据,则可以发送0XFF,读取从机返回的对应数据

标签:SCK,SPI5,STM32,SPI,Init,Handler,GPIO,详解
From: https://blog.csdn.net/qq_38072731/article/details/140259069

相关文章

  • Windows Server Core 详解
    1、为什么使用WindowsCore1.1、提升效能精简系统服务和组件减少系统存储,降低无用IO,提示读写效能系统精简后可以切换在Thick存储模式提示IO1.2、增加安全系统缩减,减少攻击面减少无用组件,降低感染风险微软MSDN调查超过%70的病毒不能运行增加离职&恶意人......
  • Spring Boot项目Jar包加密详解
    目录引言Jar包加密的基础知识为什么需要加密Jar包Jar包加密的基本原理常用的Jar包加密工具ProGuardJavaguardJavaAgentSpringBoot项目Jar包加密实战使用ProGuard对SpringBoot项目进行加密集成Javaguard到SpringBoot项目中通过JavaAgent实现动态加密Jar包加密的......
  • 请详述ppo和dpo的区别和优劣|详解ppo原理|
    请详述ppo和dpo的区别和优劣AnswerPPO(ProximalPolicyOptimization)和DPO(DirectPreferenceOptimization)是两种用于大型语言模型对齐的算法,它们有以下主要区别和各自的优缺点:主要区别:训练流程:PPO采用多阶段训练:先训练奖励模型,再使用强化学习优化策略。DPO将......
  • STM32中断(NVIC和EXIT)
    CM3内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。但STM32并没有使用CM3内核的全部东西,而是只用了它的一部分。STM32有76个中断,包括16个内核中断和60个可屏蔽中断,具有16级可编程的中断优先级。而常用的就是这60个......
  • 广度(宽度)优先搜索(遍历)bfs详解
    简介    广度优先搜索(遍历)是一种在图的搜索遍历中较常见的算法。它的时间复杂度通常要比深度优先搜索(遍历)要低很多,尤其是最短路。这是因为深度优先的思想是走一条路要把它走到底再去考虑别的路,如果一开始走错了,后面会浪费很多时间在死胡同上,而且递归的方法本来就需要......
  • C# Winform之propertyGrid控件使用详解和分组设置
    PropertyGrid控件在WinForms中是一个非常有用的工具,它允许用户查看和编辑一个对象的属性。这个控件非常适合用于配置对话框或任何需要动态显示对象属性的地方。下面我会详细介绍PropertyGrid的使用方法和如何对属性进行分组。使用详解1.添加 PropertyGrid 控件在Vi......
  • 加密算法详解:对称加密、非对称加密、Hash算法
    对称加密、非对称加密和哈希算法是信息安全中的三种主要加密技术,它们各自有不同的特点和用途:对称加密(SymmetricEncryption)工作原理:使用相同的密钥进行加密和解密。速度:通常非常快,适合大量数据的加密。密钥管理:参与通信双方必须安全地共享密钥,密钥泄露会导致安全风险。主......
  • 归并排序详解
    文章目录归并排序原理排序演示1排序演示2代码实现递归方式迭代方式复杂度分析时间复杂度空间复杂度稳定性归并排序原理归并排序,也是应用了分治的思想。将原数组分为两个子数组,左子数组和右子数组,两个子数组排好序后,通过拷贝的方法将两个数组边排序边合并。子数组可......
  • vue中的插槽详解
    插槽(slot)插槽在vue中是一种很常见的写法,让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式一共有三种分类:默认插槽、具名插槽、作用域插槽,下面一一根据案例改造说明1基本案例首先编写一个基本的案例,三个组件展示不同的数据类型 页面进行展示 现在要......
  • stm32f429iDisc AD规则组多通道+DMA转运
    扫描模式+非连续触发uint16_tAdc_Value[5]={0};DMA_InitTypeDefDMA_InitStructure;voidAD_Init(void){ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph......