SPI协议——读取外部SPI Flash ID

简介:

单片机型号:stm32l431rct6

SPI Flash型号:W25Q32JVSSIQ

使用软件:CubeIDE

1. W25Q32JVSSIQ简介 

        我们通过SPI协议来读取 SPI Flash的厂商ID和芯片独一无二的ID,查数据的芯片手册可以看到如下重要点:

1.1 芯片所支持的模式

我们知道SPI协议支持四种协议模式,该芯片手册中规定W25Q32JV的标准工作模式是 SPI模式 0(CPOL = 0,CPHA = 0)。

1.2 芯片具体ID

由下图可知芯片的厂商ID为0xEF,芯片ID为0x15。

由标准指令集我们可以看出 我们得到厂商和芯片ID需要发送六个字节的数据,分别是:0x90、Dummy_Byte、0x00以及两个其他数据;对于初学者来说,可能不解为什么接收数据前要发送一个任意数据到从机,那是因为在全双工模式下,发送和接收数据是同步进行的,即你发送数据给从机的同时,从机也会发送数据给你,而这个接收到的数据有效还是无效,完全是看相应芯片所制定的协议,但一定会发送,所以可以通过接收从机数据的方式来判断数据是否已发送完毕;而接收数据因为从机没有时钟信号,需要主机提供,所以通过给从机发送数据(任意数)的方式提供时钟信号,正如前面所述,发送一个数据意味着接收到一个数据,将接收到的数据保存即可。这就是两个“其他数据”存在的意义。

 

2. CubeIDE配置

2.1 使能SPI1,配置相关参数

我的硬件原理图是这样的:

      

 

我们进行简单的数据传输无需开启CRC校验 ,NSS即片选信号我们选择软件,不要通过硬件,否则会造成错误

 

 配置完成后,MISO、MOSI都已经自动配置完成,现在需要我们配置CS/SS片选信号,在我的原理图中他是PA4

 注意:PA4即CS片选信号要设置成输出模式。

我们在配置完成后,CubeIDE软件会自动帮我们生成代码,这里不做过多展示,如果大家用的不是自动生成那么可以自行到网上寻找资源查看具体的配置(网上资源很多的哦)

3. 代码编写

3.1 spi_flash.c代码编写

在spi_flash.c中我们主要做的三件事:

        1.定义片选,在低电平时候开始允许通信,高电平时候结束通信;

        2.编写发送一字节的函数(其实发送函数也相当于接收,因为SPI协议是同发同收的);

        3.编写读取ID的函数

3.1.1 片选定义

// 片选引脚定义
#define CS_PIN GPIO_PIN_4
#define CS_PORT GPIOA

// 拉低 CS 信号
#define cs_low()  HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_RESET)

// 拉高 CS 信号
#define cs_high() HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_SET)

3.1.2 发送一字节的函数

uint8_t SPI_FLASH_SendByte(uint8_t byte)
{
	uint8_t 						r_data = 0;
	HAL_StatusTypeDef 				status;
	if(  (status = HAL_SPI_TransmitReceive(&hspi1, &byte, &r_data, 1, SPI_TIMEOUT)) != HAL_OK )
	{
		if (status == HAL_ERROR)
	    {
		    printf("SPI transmission error!\n");
	    }
		else if (status == HAL_TIMEOUT)
		{
			 printf("SPI transmission timeout!\n");
		}
		else if (status == HAL_BUSY)
		{
			 printf("SPI is busy!\n");
	    }
		return 0;
	}
	return r_data;
}

3.1.3 编写读取ID的函数

uint32_t SPI_FLASH_ReadId(void)
{
	 uint32_t 			id = 0;
	 uint8_t 			idBytes[2] = {0};

	 cs_low(); // 拉低片选
	
	 SPI_FLASH_SendByte(0x90); // 发送读取ID命令
	

	 // 读取2个字节的数据
	 SPI_FLASH_SendByte(Dummy_Byte);//不在乎读到数据
	 SPI_FLASH_SendByte(Dummy_Byte);//不在乎读到数据
	 SPI_FLASH_SendByte(0x00);
	 idBytes[0] = SPI_FLASH_SendByte(Dummy_Byte);//厂商ID
	 idBytes[1] = SPI_FLASH_SendByte(Dummy_Byte);//芯片ID

	 cs_high(); // 拉高片选

	 id = (idBytes[0] << 8) | idBytes[1];
	 printf("ID Bytes: %02X %02X\n", idBytes[0], idBytes[1]);
	 printf("Combined ID: 0x%04X\n", id);
	 return id;
}

3.2 main()函数编写

 id = SPI_FLASH_ReadId();
 printf("id is 0x%04X\n", id);

4. 运行结果

上述代码烧录运行之后,就会打印出现在的效果,头文件只需添加相应的函数以及引入一些头文件即可,这里不做过多展示

5. 补充:

5.1 遇到的问题

5.1.1 HAL_SPI_TransmitReceive()函数返回超时

        返回超时代表通信没有建立成功,笔者在确定片选信号成功拉低、拉高之后,修改了时钟频率(改为了上面设置的32)、关闭了CRC校验(原来我是打开的),但是笔者认为CRC影响不大,应该是时钟频率的问题,如果有读者懂得这个的话,欢迎留言哦。

5.1.2 HAL_SPI_TransmitReceive()函数阻塞

函数原型:HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)

笔者最开始给的延时很大,就导致函数阻塞很久,大家在书写的时候可以适当给,需要注意的是延时的单位是毫秒。

5.2 补充知识点

5.2.1 SPI协议四个模式

模式0:CPOL=0,CPHA=0;SCK串行时钟线空闲时是低电平,数据在SCK时钟上升沿被采样,在时钟下降沿切换;

模式1:CPOL=1,CPHA=0;SCK串行时钟线空闲时是低电平,数据在SCK时钟下降沿被采样,在时钟上升沿切换;

模式2:CPOL=1,CPHA=0;SCK串行时钟空闲是高电平,数据在SCK时钟下降沿被采样,在上升沿切换;

模式3:CPOL=1,CPHA=1,SCK串行时钟线空闲是高电平,数据在SCK时钟的上升沿采样,在下降沿切换;

具体的可以看笔者关于SPI协议的具体介绍文章:单片机通信协议——SPI协议_主从设备 master设备 slave设备-CSDN博客

5.2.1 Dummy_Byte字节存在的意义

        Dummy_Byte我们通常定义其为0xFF或者0x00,意思是任意的数据,SPI协议在通信的时候 通过给从机高低电平来告诉他我们要进行的操作,想要的数据,以为动作有很多,所以要区分不同命令,所以就通过Dummy_Byte来区分。

以上就是笔者关于读取SPI Flash芯片ID的一些总结,如有错误还请指正,随时欢迎大家找我交流!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pytorch库 02 Anaconda、Jupyter常用命令及操作

文章目录 一、Anaconda Prompt1、conda常用命令2、pip常用命令 二、Jupyter1、Jupyter常用命令及基本操作2、Jupyter代码补全插件安装 一、Anaconda Prompt 1、conda常用命令 下列命令可以在Anaconda Prompt中输入。 清屏&#xff1a; cls 查看帮助&#xff1a; conda -h 查…

HTML静态网页成品作业(HTML+CSS)——手机电子商城网页(4个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有4个页面。 二、作品演示 三、代…

视频与音频的交响:探索达摩院VideoLLaMA 2的技术创新

一、简介 文章&#xff1a;https://arxiv.org/abs/2406.07476 代码&#xff1a;https://github.com/DAMO-NLP-SG/VideoLLaMA2 VideoLLaMA 2是由阿里巴巴集团的DAMO Academy团队开发的视频大型语言模型&#xff08;Video-LLM&#xff09;&#xff0c;旨在通过增强空间-时间建模…

分享:一个可爱的运行猫动画在你的窗口任务栏上

RunCat_for_windows&#xff1a;在 Windows 任务栏飞奔的“小猫”。这是一个用 C# 写的小工具&#xff0c;它会在 Windows 任务栏显示一只奔跑的小猫动画&#xff0c;CPU 使用率越高它跑得越快。 安装很简单 访问“发布”页面并下载 RunCat.exe。 或通过 Scoop&#xff08;x…

Android SurfaceFlinger——服务启动流程(二)

SurfaceFlinger 是 Android 系统中的一个核心服务&#xff0c;负责管理图形缓冲区的合成和屏幕显示&#xff0c;是 Android 图形系统的关键组件。 一、启动流程 SurfaceFlinger 作为一个系统服务&#xff0c;在 Android 启动早期由 init 进程通过 servicemanager 启动。它是作…

【漏洞复现】用友 NC NCFindWeb 任意文件读取漏洞

免责声明&#xff1a; 本文内容旨在提供有关特定漏洞或安全漏洞的信息&#xff0c;以帮助用户更好地了解可能存在的风险。公布此类信息的目的在于促进网络安全意识和技术进步&#xff0c;并非出于任何恶意目的。阅读者应该明白&#xff0c;在利用本文提到的漏洞信息或进行相关测…

数学建模基础:统计模型

目录 前言 一、概率与统计基础 二、统计模型 三、Matlab统计工具箱 四、实例示范&#xff1a;市场调查分析 步骤 1&#xff1a;数据导入 步骤 2&#xff1a;数据可视化 步骤 3&#xff1a;建立多元线性回归模型 步骤 4&#xff1a;模型验证 步骤 5&#xff1a;模型应…

开发人员不要嗨,B端系统颜值不过关,可能进不去客户选择范围。

市面上形形色色的B端管理系统非常多&#xff0c;大家近身搏杀&#xff0c;这个市场已经成为了红海。也就是随便某一个功能领域&#xff0c;都有N的系统可以选择&#xff0c;这个时候你坚持B端系统功能使用就行&#xff0c;那就是自嗨了。现在是个过剩的时代&#xff0c;不是供不…

MaxWell实时监控Mysql并把数据写入到Kafka主题中

配置mysql 启用MySQL Binlog MySQL服务器的Binlog默认是未开启的&#xff0c;如需进行同步&#xff0c;需要先进行开启 修改MySQL配置文件/etc/my.cnf sudo vim/etc/my.cof 增加如下配置 注&#xff1a;MySQL Binlog模式 Statement-based&#xff1a;基于语句&#xff0c;…

数据分析第十二讲 数据可视化入门(一)

数据可视化入门&#xff08;一&#xff09; 在完成了对数据的透视之后&#xff0c;我们可以将数据透视的结果通过可视化的方式呈现出来&#xff0c;简单的说&#xff0c;就是将数据变成漂亮的统计图表&#xff0c;因为人类对颜色和形状会更加敏感&#xff0c;然后再进一步解读…

三步问题00

题目链接 三步问题 题目描述 注意点 n范围在[1, 1000000]之间结果可能很大&#xff0c;需要对结果模1000000007 解答思路 动态规划的思想根据dp[i - 1]、dp[i - 2]、dp[i - 3]推出dp[i]需要注意的是结果可能很大&#xff0c;在计算的过程中需要模1000000007防止越界 代码…

宋仕强论道之华强北假货之四

宋仕强论道之华强北假货之四&#xff0c;华强北虚标货。在华强北顾名思义就是“以少充多、以小充大&#xff0c;把低级当高级卖”。同样品牌和型号的产品&#xff0c;用民用级冒充工业级&#xff0c;工业级当军用级&#xff0c;军用级再当航天级&#xff0c;品牌型号都不变&…

全面升级,票据识别新纪元:合合信息TextIn多票识别2.0

票据识别 - 自动化业务的守门员 发票、票据识别&#xff0c;是OCR技术和RPA、CMS系统结合的一个典型场景&#xff0c;从覆盖率、覆盖面的角度来说&#xff0c;应该也是结合得最成功的场景之一。 产品简介 国内通用票据识别V2.0&#xff08;简称“多票识别2.0”&#xff09;是…

深入探讨:UART与USART在单片机中串口的实际应用与实现技巧

单片机&#xff08;Microcontroller Unit, MCU&#xff09;是一种集成了处理器、存储器和输入输出接口的微型计算机。它广泛应用于嵌入式系统中&#xff0c;用于控制各类电子设备。UART和USART是单片机中常见的通信接口&#xff0c;负责串行数据传输。下面我们详细介绍它们在单…

初阶 《数组》 1. 一维数组的创建和初始化

1. 一维数组的创建和初始化 1.1 数组的创建 数组是一组相同类型元素的集合 数组的创建方式&#xff1a; type_t arr_name [const_n]; //type_t 是指数组的元素类型 //const_n 是一个常量表达式&#xff0c;用来指定数组的大小数组创建的实例&#xff1a; //代码1 int ar…

手写月课表

农历插件&#xff1a;chinese-lunar-calendar - npm&#xff0c;这个插件可以计算农历日期和节气等 安装&#xff1a; npm install --save chinese-lunar-calendar 使用&#xff1a; import { getLunar } from chinese-lunar-calendar;let res getLunar(years, months, da…

【Linux基础IO】重定向以及原理分析

我们先来看下面一个情况&#xff1a; #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define filename "text.txt"int main(){close(1);//关…

人工智能在【妇科肿瘤】领域的最新进展|顶刊速递·24-06-20

小罗碎碎念 文献主题&#xff1a;人工智能在妇科肿瘤中的最新研究进展 如下图所示&#xff0c;今天的六篇推文中&#xff0c;研究的全部都是妇科疾病&#xff0c;包括&#xff1a; 乳腺癌宫颈癌卵巢癌子宫内膜癌 老板经常对我说&#xff0c;不要只关注自己的研究领域&#xff…

Python | Leetcode Python题解之第167题两数之和II-输入有序数组

题目&#xff1a; 题解&#xff1a; class Solution:def twoSum(self, numbers: List[int], target: int) -> List[int]:low, high 0, len(numbers) - 1while low < high:total numbers[low] numbers[high]if total target:return [low 1, high 1]elif total <…

ml307A模块连接阿里云(详细版)

1、需要的信息 MQTT连接参数、订阅或发布的主题、服务器地址、端口1883 服务器地址&#xff1a; alFMz7jnArW.iot-as-mqtt.cn-shanghai.aliyuncs.com 注&#xff1a;重要的信息阿里云信息大家不要透露&#xff0c;写完笔记会及时删除产品及设备&#xff0c;大家用自己的信息…