stm32入门-----硬件SPI读写W25Q64

news2024/9/23 1:37:43

 目录

前言        

 一、相关库函数介绍

 1.初始化

 2.写入数据

3.接收数据

 4.获取标志位

二、软件SPI读写W25Q64


前言        

        上一期我们学习了stm32的SPI外设(上一期链接:stm32入门-----硬件SPI外设-CSDN博客),那么我们本期就来通过stm32的SPI外设来去实现之前软件读写W25Q64的功能。(视频:[11-5] 硬件SPI读写W25Q64_哔哩哔哩_bilibili)

本期代码我已上传至百度网盘,需要的可以自己下载。

通过百度网盘分享的文件:硬件SPI读写W25Q64(1).rar
链接:https://pan.baidu.com/s/1JZiDtAC9tOKsidcS_BGesA?pwd=0721 
提取码:0721

 一、相关库函数介绍

这里我们点开项目的library库,然后看到下面这两个文件,这两个文件就是存储SPI的底层功能的函数。

下面这些就是关于SPI的相关函数,但是I2S的也是跟SPI弄到一起了,不过我们不需要用到,这里本期要用到的我已经在下面画出来了。 

 1.初始化

这个函数我们已经再熟悉不过了,也就是定义结构体,对结构体进行配置,然后放入到下面这个函数去初始化。

void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);

下面看一个示例: 

   //SPI结构体初始化
    SPI_InitTypeDef SPI_initstruct;
    SPI_initstruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;//波特率预分频器,对SPI总线上的时钟进行分频,这里是SPI1对应的APB2时钟为72MHz
    SPI_initstruct.SPI_CPHA = SPI_CPHA_1Edge;//配置模式,第几个边沿采样(模式0第一个边沿采样)
    SPI_initstruct.SPI_CPOL = SPI_CPOL_Low;//配置模式,SCK默认情况下电平(模式0是低电平)
    SPI_initstruct.SPI_CRCPolynomial = 7;//CRC校验,这里选默认值0x0007就行了
    SPI_initstruct.SPI_DataSize = SPI_DataSize_8b;//配置数据帧,当前选择一个字节为一个数据,8位
    SPI_initstruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//选择工作模式,当前选择双线全双工
    SPI_initstruct.SPI_FirstBit = SPI_FirstBit_MSB;//选择低位先行还是高位先行,这里选择高位先行
    SPI_initstruct.SPI_Mode = SPI_Mode_Master; //选择SPI的模式,当前设备为主机还是从机,这里选择主机
    SPI_initstruct.SPI_NSS = SPI_NSS_Soft; //选择SS SPI设备,这里使用软件NSS模式
    SPI_Init(SPI1, &SPI_initstruct);

 2.写入数据

void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);

把数据写入到发送数据寄存器DR中。 

3.接收数据

uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);

读取接收数据寄存器DR里面的数据,返回出来。 

 4.获取标志位

FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);

 这个函数的参数选择如下,我们可以去通过这个函数来去获取到TEX和RNEX的标志位,从而去判断数据是否能继续写入或者读取操作。

二、软件SPI读写W25Q64

现象:

电路连接图:

工程文件如下,这里我们只需要在软件SPI读写W25Q64的代码进行修改就行了,这里要修改的部分实际上就是底层部分,之前是软件底层,那这里我们只需要改MySPI.c文件的底层即可。

MySPI.c代码如下: 

#include "stm32f10x.h"                  // Device header

//对SS的写入
void SPI_W_SS(uint8_t val) {
    GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)val);
}


void SPI_init() {
    /*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//开启GPIOA的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); //开启SPI1时钟
    
    /*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//通用推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //SS
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);					

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7; //MOSI和SCK
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);					

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //MISO
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    //SPI结构体初始化
    SPI_InitTypeDef SPI_initstruct;
    SPI_initstruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;//波特率预分频器,对SPI总线上的时钟进行分频,这里是SPI1对应的APB2时钟为72MHz
    SPI_initstruct.SPI_CPHA = SPI_CPHA_1Edge;//配置模式,第几个边沿采样(模式0第一个边沿采样)
    SPI_initstruct.SPI_CPOL = SPI_CPOL_Low;//配置模式,SCK默认情况下电平(模式0是低电平)
    SPI_initstruct.SPI_CRCPolynomial = 7;//CRC校验,这里选默认值0x0007就行了
    SPI_initstruct.SPI_DataSize = SPI_DataSize_8b;//配置数据帧,当前选择一个字节为一个数据,8位
    SPI_initstruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//选择工作模式,当前选择双线全双工
    SPI_initstruct.SPI_FirstBit = SPI_FirstBit_MSB;//选择低位先行还是高位先行,这里选择高位先行
    SPI_initstruct.SPI_Mode = SPI_Mode_Master; //选择SPI的模式,当前设备为主机还是从机,这里选择主机
    SPI_initstruct.SPI_NSS = SPI_NSS_Soft; //选择SS SPI设备,这里使用软件NSS模式
    SPI_Init(SPI1, &SPI_initstruct);

    //使能
    SPI_Cmd(SPI1, ENABLE);
    SPI_W_SS(1);//SS为高电平表示不选中从机,
}

//1.起始
void SPI_Start() {
    //SS置为低电平
    SPI_W_SS(0);
}
// 2.终止
void SPI_Stop() {
    // SS置回高电平
    SPI_W_SS(1);
}


// 交换字节   4步搞定
uint8_t SPI_SwapByte(uint8_t byteSend) {
    //先发送再有接收
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != SET);//等待TXE标志位,表示是否可以写入数据到发送寄存器TDR
    SPI_I2S_SendData(SPI1, byteSend);//写入数据到发送数据寄存器
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != SET);//等待RXNE标志位,表示是否可以从接收数据寄存器RDR读取数据
    return SPI_I2S_ReceiveData(SPI1);//返回读取到的数据
}

main.c文件代码:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "W25Q64.h"

uint8_t MID;
uint16_t DID;

uint8_t arrWrite[] = { 0x01,0x02,0x03,0x04 };
uint8_t arrRead[4];

int main(void)
{	
	OLED_Init();
	W25Q64_init();
	OLED_ShowString(1, 1, "MID:    DID:");
	OLED_ShowString(2, 1, "W:");
	OLED_ShowString(3, 1, "R:");

	W25Q64_ReadID(&MID, &DID);
	OLED_ShowHexNum(1, 5, MID, 2);
	OLED_ShowHexNum(1, 13, DID, 4);

	W25Q64_SectorErase(0x000000);//扇区的地址取决于前面三位,后面三位无论怎么变都是表示同一个扇区
	W25Q64_PagePro(0x0000FF, arrWrite, 4);//写入
	W25Q64_ReadData(0x0000FF, arrRead, 4);//读取

	// 展示发送的数据
	for (uint8_t i = 0;i < 4;i++) {
		OLED_ShowHexNum(2, 3+3*i, arrWrite[i],2);
	}
	// 展示读取的数据
	for (uint8_t i = 0;i < 4;i++) {
		OLED_ShowHexNum(3, 3+3*i, arrRead[i],2);
	}

	while (1) {
		
	}
}

以上就是本期的全部内容了,我们下次见!

今日壁纸:

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

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

相关文章

最近很火的FLUX.1文生图模型本地一键整合包SwarmUI,schnell量化版,6G显存可畅玩的FLUX.1

最近一个新的文生图模型突然火出圈&#xff0c;它就是由Black Forest Labs&#xff08;黑森林实验室&#xff09;团队开发的FLUX.1。 Black Forest Labs估计很多人都没听说过&#xff0c;还以为是新生的创业团队&#xff0c;现在就先来说一说Black Forest Labs。玩过AI绘画的&a…

【Ansible 学习之旅】Ansible 介绍和架构

目录 Ansible 发展Ansible 介绍Ansible 组成 Ansible 发展 2012-03-09&#xff0c;发布0.0.1版 2015-10-17&#xff0c;Red Hat宣布1.5亿美元收购 官网&#xff1a;https://www.ansible.com/ 官方文档&#xff1a;https://docs.ansible.com/ Ansible 介绍 Ansible 可自动管理…

云存储技术:HBase HDFS 无感知迁移方案

在大数据生态系统中&#xff0c;HBase 和 HDFS 是两个关键组件。HBase 是一个分布式列式数据库&#xff0c;常用于实时读写大规模数据&#xff1b;HDFS 是一个高可靠的分布式文件系统&#xff0c;用于存储海量数据。 1、背景 随着业务的发展和技术的进步&#xff0c;可能需要对…

HDMI vs DP:LED显示屏背后的高清传输大揭秘

在如今数字化高速发展的时代&#xff0c;LED显示屏以其高亮度、高清晰度、长寿命等优点&#xff0c;广泛应用于广告、会议、娱乐等多个领域。然而&#xff0c;要让这些绚丽多彩的画面完美呈现&#xff0c;离不开背后默默工作的接口技术。今天&#xff0c;我们就来揭开LED显示屏…

前端react集成OIDC

文章目录 OpenID Connect (OIDC)3种 授权模式 【服务端】express 集成OIDC【前端】react 集成OIDCoidc-client-js库 原生集成react-oidc-context 库非组件获取user信息 OAuth 2.0 协议主要用于资源授权。 OpenID Connect (OIDC) https://openid.net/specs/openid-connect-core…

【安当产品应用案例100集】007-工业控制系统防勒索解决方案-安当RDM防勒索

《工业控制系统网络安全防护指南》是由工业和信息化部于2024年1月19日发布&#xff0c;旨在指导企业提升工业控制系统网络安全防护水平&#xff0c;确保新型工业化发展的安全根基。该指南适用于使用和运营工业控制系统的企业&#xff0c;包括但不限于可编程逻辑控制器&#xff…

【生成式人工智能-十-文字、图片、声音生成策略】

人工智能生成文字、图片、声音的方法 生成的本质生成的策略文字AR (Autoregressive Generation)图像和视频 NAR(Non-Autoregressive Generation)解决NAR生成品质低的问题 AR NAR 生成的本质 文字、图像、声音的生成的本质&#xff0c;就是给模型一个输入&#xff0c;模型把基…

大模型应用中的幻觉问题是什么?

大模型应用中的幻觉问题是什么&#xff1f; 在现代自然语言处理领域&#xff0c;大语言模型&#xff08;如GPT系列&#xff09;以其惊人的生成能力和语言理解能力被广泛应用。然而&#xff0c;随着这些模型的广泛使用&#xff0c;幻觉问题逐渐显现出其对实际应用的潜在影响。本…

怎样快速查询数家公司是否存在关联关系?

▶关联关系的查询是企业稳健运营和长期发展的关键环节 企业在关键时期需要查询数家公司是否存在关联关系&#xff0c;以确保合规性和透明度。这通常发生在年度审计、税务申报、并购活动、上市准备、风险评估和法律诉讼时。监管合规性检查、内部控制加强、市场策略制定、资金管…

加速区域市场扩张,ATFX任命Amer Zino为中东和北非业务发展总监

全球领先的差价合约经纪商ATFX再度向世界展示了其吸纳行业顶尖复合型人才的决心和能力。日前&#xff0c;ATFX旗下机构业务ATFX Connect宣布一项重磅人事任命&#xff0c;行业杰出领袖Amer Zino加入公司&#xff0c;出任中东和北非业务发展总监一职&#xff0c;并将常驻工作地阿…

【ARM】ULINK Pro如何和SWD接口进行连接调试

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 解决ULINK Pro和JTAR接口进行连接问题。 2、 问题场景 因为ULINK Pro本身自带的接口是Cortex-M ETM Interface 20-pin Connector。所以无法和JTAR接口直接进行连接。 图2-1 3、软硬件环境 1&#xff09;、软件版…

综合交易系统---强大的问财自定义实盘交易系统上线

这几天知识星球的朋友的需要&#xff0c;我重新写了问财自定义实盘交易系统&#xff0c;同时把数据库上线了&#xff0c;网页 https://gitee.com/li-xingguo11111/xg_data 调用网页的源代码数据服务器地址 http://124.220.32.224:8888/ 问财实盘设置&#xff0c;打开总结交易系…

【从零开始一步步学习VSOA开发】VSOA数据报

VSOA数据报 概念 Datagram 是 VSOA 的一种数据传输类型&#xff0c;通常这种类型用于传输一些不需要确认的数据&#xff0c;例如传输视频流数据或构建 VPN 网络。 Datagram 可以简单快速的在网络中传输数据。它即不需要建立连接&#xff0c;也不需要维护连接&#xff0c;因此…

GESP 一级 比赛

出错了 - 洛谷https://www.luogu.com.cn/contest/190441#problems 邀请码&#xff1a;zura 有讲解哦&#xff01;

SCAU学习笔记 - 高级语言程序设计课后习题

写在前面 趁着暑假赶紧把C语言的习题也补了 也欢迎看到这篇博客的小灯们来到华南农业大学喵 专栏里还有后续其他部分课程的学习笔记 如何提交自己的代码 首先给各位说一下这门课程的要求&#xff0c;首先是我们学校的校内OJ&#xff0c;我们计算机类专业的学生用的是前面这个…

突破 ES 引擎局限性在用户体验场景中的优化实践

回顾&#xff1a;ES 慢上游响应问题优化在用户体验场景中的实践-CSDN博客 上文介绍了用户体验管理平台&#xff08;简称 VoC&#xff09;在针对 ES 慢上游响应场景下的优化实践&#xff0c;本文继续介绍针对第二个痛点问题——ES 引擎局限性的性能优化实践进行介绍。 下文以搜…

MaxKB:基于 LLM大语言模型的知识库问答系统实操

1.MaxKB介绍 MaxKB 是一款基于 LLM&#xff08;Large Language Model&#xff09;大语言模型的知识库问答系统。MaxKB 的产品命名内涵为 “Max Knowledge Base”&#xff0c;为用户提供强大的学习能力和问答响应速度&#xff0c;致力于成为企业的最强大脑。与同类基于 LLM 的知…

数值分析【4】

目录 ​编辑第六章 数值积分微分 龙贝格 高斯求积 查表&#xff1f; 插值求导 两点 ​编辑 三点​编辑 第七章 ode 龙哥库塔 线性多步法 第八章 eig 幂法&#xff1a;v-》Av-》AAv-》……​编辑 反幂法 每次成得是A逆&#xff0c;这样得到摸最小的特征值​编辑 Q…

【IEEE独立出版】第四届计算机科学与区块链国际学术会议 (CCSB 2024)

第四届计算机科学与区块链国际学术会议 (CCSB 2024) 2024 4th International Conference on Computer Science and Blockchain 2024年9月6-8日 中国-深圳 老牌会议 | 涵盖计算机学科 | 往届均完成见刊、稳定检索 | 论文录用速度快 | 有ISBN号! *关于IEEE出版社 电气电子工…

使用ant design的modal时,发现自定义组件的样式(组件高度)被改变了!

一 问题描述 在项目中&#xff0c;自定义了一个组件&#xff0c;分别在界面和 antd的modal中都有使用到。但是突然发现&#xff0c;界面中的组件样式跟modal中的组件样式高度不一样。modal中的组件整体要比页面中的组件要高一点。 项目中的自定义组件比较复杂&#xff0c;因此&…