当前位置: 首页 > news >正文

嵌入式软件--STM32 SPI通信(上)

类似于串口、IIC,SPI也是一种通信协议。全称Serial Peripheral interface,串行外围设备接口。

一、SPI概念

1.1物理层

SPI:串行外围设备接口

Motorola(摩托罗拉)首先在其MC68HCXX系列处理器上定义的。

SPI接口主要应用于EEPROM,FLASH,各种传感器,AD转换器等。扩展各种外设,传感器,转换器。

高速的全双工同步的串行通信总线。同时发同时收。 

物理层有四条线,时钟 片选 输入 输出

SCK时钟线,用于通讯的数据同步。由主机产生决定通讯的通讯速率。STM32的SPI时钟频率最大为fpclk/2。两个设备通讯,速率受限于低速设备。

MOSI:主设备输出/从设备输入引脚

MISO:主设备输入/从设备输出

SS:片选线或者使能线。主机要连接多条从设备就需要多条片选线。因为SPI通信时,各设备没有地址,不需要地址码,就是费片选线,有几个从设备就要设置多少片选线。主机的片选线只需要任意决定状态的IO口,从设备有决定状态的片选线,被选定时是固定状态。

1.2协议层

1.2.1数据交换过程

物理层多线,协议层就方便了好多,不需要地址码,基本上就是主从机之间的数据交换。甚至连移位寄存器都可以共用。

主机寄存器左移一位发出去,低位会空出来,从机高位左移一位发出去,正好填补主机寄存器空出来的低位。

移位寄存器临时存储要交换的数据(来自发送缓冲区)。

接收缓冲区存储最终得到的值。

所谓交换,就是一个循环传递。时钟上升沿,主从机左移一位,将高位的值发出,一般高位先行。时钟下降沿,主从机将低位读取接收,存储到低位寄存器的低位。经过8次交换,就能完成一个字节交换,最后从接收缓冲区读取字节。

1.2.2时钟的极性与相位

数据采样和设置时钟的极性和相位有关。

通信的整个过程分为空闲时刻和通信时刻。CPOL:Clock Polarity

空闲状态SCK是低电平,CPOL=0;空闲状态SCK是高电平,CPOL=1

CPHA:clock phase,时钟的相位,直接决定SPI总线从哪个跳变沿开始采样数据。

CPHA=0:表示从第一个跳变沿开始采样;CPHA=1:表示从第2个跳变沿开始采样

通过极性和相位,SPI有四种工作模式。

mode0:空闲状态时为低电平,且在第一个跳变沿采样。就是第一个上升沿采样。

mode1:空闲状态为低电平,且在第二个跳变沿采样。第一个下降沿采样。

mode2:第一个下降沿采样。

mode3:第一个上升沿采样。

下面是模式0和模式2的时序图:

模式3和模式1

很多设备喜欢上升沿采样,也就是模式0和模式3.大多选择模式0.

二、SPI通信_W25Q32芯片

2.1介绍

SPI与IIC一样,可以拓展各种各样的外设。我们可以用SPI扩展一种名为W25Q32的存储器(NOR FLASH:基于或非门构建的flash)

DI:FLASH的输入,连接的是stm32的输出,主设备输出,从设备输入,也就是写入数据。

DO:flash的输出,连接的是stm32的输入,主设备输入,从设备输出,也就是主机在读取flash的数据。

SPI-NSS是从设备选择,主设备连接从设备时,不需要连接自己的片选线,随便用一个IO口连接从设备的片选线。

flash作为从设备,CS连接主机stm32的一个IO口。

flash芯片只支持模式0和模式3;写的时候必须是先擦除,擦除后再写入;移位是高位优先。

这个flash有32M bit,也就是4M字节. 

2.2读写要求与存储结构

2.2.1状态寄存器

Status Register 状态寄存器表示当前能不能写入。他有一个关键的位叫Busy,置一时不允许写入和读写,只能查询。

和EEprom一样,也需要页写地址,字节地址。那么4M字节需要多少位来表示?一个字节8位,三个位可以表示其字节,像000 111 010 110 101 100……,三位地址可以表示8这个字节,而8是2的立方,所以可以三位表示。4M字节是2的22次方,所以需要22位来表示极限。22个1位写成十六进制就是0x3fffffh,这个地址线太大了。我们可以划分区块,一块64kB可以划分64块。64k=2^6*2^10=2^16.

block 0范围:0x000000h~0x00ffffh

block 1范围:0x010000h~0x01ffffh

22位地址:前六位块号 4位段号 4位页号 8位页内地址

2.2.2写入操作和读取操作

写入注意事项:

(1)写入操作前,必须先进行写使能。

(2)每个数据位只能由1改写为0,不能由0改写为1.

(3)写入数据前必须先擦除,擦除后,所有数据位变为1,擦除必须按最小擦除单元进行。

(4)连续写入多字节时,最多写入一页的数据,超过页尾位置的数据,会回到页首覆盖写入。

(5)写入操作结束后,芯片进入忙状态(busy),不响应新的读写操作。

读取注意事项:

(1)直接调用读取时序,无需读使能,无需额外操作,没有页的限制。

(2)读取操作结束后不会进入忙状态,但不能在忙状态时读取。

三、W25Q32芯片读写指令

READ DATA:

四、通信案例1——软件模拟SPI读写flash_框架搭建和读取ID

4.1交换数据时序(核心)

一般使用模式0

ss低电平状态开始工作,时序结束后高电平结束工作。

4.2软件模拟SPI读写flash

4.2.1需求描述

基于寄存器操作,使用软件模拟SPI协议,并完成读写FLash。

4.2.2硬件电路设计

主机的PC13gpio口执行电平状态选择要通信的从设备flash.

GPIO口 PA5模拟时钟线SCK,PA6模拟MISO,PA7模拟MOSI.

4.2.3软件设计(寄存器)

因为时软件模拟,这个工程与IIC相似,所以可以复制之前的IIC软件模拟工程。

在硬件层文件夹里创建SPI文件夹,里面创建spi.c和spi.h文件。接口层里创建FLASH文件夹,里面创建w25q32.c和w25q32.h文件。

#include "spi.h"// 初始化
void SPI_Init(void)
{// 1.开启时钟RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;// 2.GPIO工作模式// 2.1cs-pc13,通用推挽输出,CNF=00,MODE=11GPIOC->CRH |= GPIO_CRH_MODE13;GPIOC->CRH &= ~GPIO_CRH_CNF13;// 2.2SCK-PA5,通用推挽输出,CNF=00,MODE=11GPIOA->CRL |= GPIO_CRL_MODE5;GPIOA->CRL &= ~GPIO_CRL_CNF5;// 2.3MOSI-PA7,通用推挽输出,CNF=00,MODE=11GPIOA->CRL |= GPIO_CRL_MODE7;GPIOA->CRL &= ~GPIO_CRL_CNF7;// 2.4MISO-PA6,浮空输入,CNF=01,MODE=00GPIOA->CRL &= ~GPIO_CRL_MODE6;GPIOA->CRL &= ~GPIO_CRL_CNF6_1;GPIOA->CRL |= GPIO_CRL_CNF6_0;// 3.SCK 保持空闲状态,模式0-低电平空闲SCK_LOW;// 4.片选初始不选中CS_HIGH;// 5.延时SPI_DELAY;
}// SPI通信的开启和关闭(通过片选信号控制)
void SPI_Start(void)
{CS_LOW;
}
void SPI_Stop(void)
{CS_HIGH;
}// 一个时钟周期内,主从交换一个字节数据
uint8_t SPI_SwapByte(uint8_t byte)
{// 定义变量接收数据uint8_t rByte = 0x00;// 用循环依次读写每一位for (uint8_t i = 0; i < 8; i++){// 1.判断当前最高位,将MOSI拉至对应电平if (byte & 0x80){MOSI_HIGH;}else{MOSI_LOW;}//2.左移一位byte <<= 1;//3.拉高时钟,在第一个上升沿采样数据SCK_HIGH;SPI_DELAY;//4.先左移,空出最低位来存放读取的数据rByte <<= 1;// 2.在MISO上采样读取数据if (MISO_READ){
rByte |= 0x01;//读到高电平,最后一位置1}//6.拉低时钟,为下次传输做准备SCK_LOW;SPI_DELAY;}return rByte;
}
#ifndef __SPI_H_
#define __SPI_H_
#include "stm32f10x.h"
#include "delay.h"
// 宏定义引脚线的操作
// CS -PC13
#define CS_HIGH (GPIOC->ODR |= GPIO_ODR_ODR13)
#define CS_LOW (GPIOC->ODR &= ~GPIO_ODR_ODR13)//SCK -PA5
#define SCK_HIGH (GPIOA->ODR |= GPIO_ODR_ODR5)
#define SCK_LOW (GPIOA->ODR &= ~GPIO_ODR_ODR5)//MOSI -PA7
#define MOSI_HIGH (GPIOA->ODR |= GPIO_ODR_ODR7)
#define MOSI_LOW (GPIOA->ODR &= ~GPIO_ODR_ODR7)//MISO -PA6,读取数据线
#define MISO_READ (GPIOA->IDR & GPIO_IDR_IDR6)//定义标准延迟时间 100khz 10us
#define SPI_DELAY Delay_us(5)//初始化
void SPI_Init(void);//SPI通信的开启和关闭
void SPI_Start(void);
void SPI_Stop(void);//一个时钟周期内,主从交换一个字节数据
uint8_t SPI_SwapByte(uint8_t byte);
//SPI
#endif
#include "w25q32.h"//初始化
void W25Q32_Init(void)
{SPI_Init();
}//读取JEDEC ID,进行测试
void W25Q32_ReadID(uint8_t *pMID,uint16_t *pDID)
{
//1.开启SPI通信,片选使能
SPI_Start();
//2.发送9fh指令
SPI_SwapByte(0x9f);
//3.依次读取三个字节的ID
//3.1第一个字节,生产商ID
*pMID = SPI_SwapByte(0xff);
//3.2第二个字节,设备ID
*pDID = 0;
*pDID |= SPI_SwapByte(0xff) << 8;
*pDID |= SPI_SwapByte(0xff)& 0xff;
//4.关闭SPI通信
SPI_Stop();
}
#ifndef __W25Q32_H
#define __W25Q32_H
#include "spi.h"//初始化
void W25Q32_Init(void);//读取JEDEC ID,进行测试
void W25Q32_ReadID(uint8_t *pMID,uint16_t *pDID);
//写使能和关闭使能
void W25Q32_WriteEnable(void);
void W25Q32_WriteDisable(void);//等待直到状态不为Busy
void w25q32_wait4NotBusy(void);//段擦除,传入块号和段号
void W25Q32_EraseSector(uint8_t block,uint8_t sector);//页写,地址以块号-段号-页号 形式表示
void W25Q32_WritePage(uint8_t block,uint8_t sector,uint8_t page,uint8_t *data,uint16_t len);
//读取
void w25q32_Read(uint32_t addr,uint8_t *buffer,uint16_t len);
#endif
/** @Author: wushengran* @Date: 2024-09-13 16:29:39* @Description:** Copyright (c) 2024 by atguigu, All Rights Reserved.*/#include "usart.h"
#include "delay.h"
#include "w25q32.h"int main(void)
{// 初始化USART_Init();W25Q32_Init();printf("软件模拟实验...\n");//读取JEDEC IDuint8_t mID=0;uint16_t dID=0;W25Q32_ReadID(&mID, &dID);printf("mID = %x, dID = %#x\n", mID, dID);while (1){}
}

到时候用一个串口调试工具,查看输出的值。

http://www.dtcms.com/a/486616.html

相关文章:

  • PHP “真异步“ TrueAsync SAPI 与 NGINX Unit 集成
  • ARCGIS国土超级工具集1.7更新说明
  • 网站如何做信息表美图在线图片编辑器
  • 分布式专题——45 ElasticSearch基础数据管理详解
  • SQLBot:基于大模型与 RAG 的智能问数系统架构
  • 网站系统维护要多久福清市建设工程交易网站好像
  • 在Linux系统上执行 setenv CDS_XVNC_TENBASE + 后重启Virtuoso的作用
  • SpringBoot用户登录注册系统设计与实现
  • 杭州余杭做网站公司秦皇岛 网站建设
  • 并查集-990.等式方程的可满足性-力扣(LeetCode)
  • Jmeter是如何实现接口关联的?
  • 企业网站做seo的必要性关于网站开发人员的薪资
  • 【Qt】6.Qt对象树
  • 使用Scanpy的基本操作
  • openssl s_client 命令——测试、调试和诊断 SSL/TLS 连接
  • 深度学习中的RNN与LSTM:原理、差异与应用
  • 湖南智能网站建设报价广西南宁网站排名优化
  • 广州网站建设十年乐云seo北京东直门网站建设
  • h5游戏免费下载:卡通飞行
  • IntelliJ IDEA 配置 Gitee 私人令牌完整指南(2025 年最新版)
  • 智尚招聘求职小程序v1.0.23
  • 网站快照历史代发新闻稿的网站
  • [数据抓取-1]beautifulsoup
  • 分形:曼德布洛特集合
  • 克拉玛依建设局网站外贸整合推广
  • 哪家网站推广好网站备案 办公室电话
  • 金蝶KIS报表系统:全场景数据可视化解决方案
  • 轻量安全、开箱即用:0 成本开启数据实时同步
  • webpack实现常用plugin
  • abap 操作 excel