STM32 软件SPI读写W25Q64

接线图

 功能函数

//写SS函数
void My_W_SS(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);
}//写SCK函数
void My_W_SCK(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)BitValue);
}//写MOSI函数
void My_W_MOSI(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)BitValue);
}//读MISO函数
uint8_t My_R_MISO(void)
{return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6);
}

代码配置

1.开启时钟

//开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIO A族的时钟

2.配置GPIO

        引脚配置,将输出引脚配置为推挽输出,输入引脚配置为上拉输入,这里接线图,DO对应从机输出,对应主机PA6就是输入,其他三个引脚配置为推挽输出。

GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO结构体变量	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 										//配置为推挽输出 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;	//选择引脚
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;					//选择引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速率
GPIO_Init(GPIOA, &GPIO_InitStructure);

3.配置电平

My_W_SS(1);//置高电平,默认不选择从机
My_W_SCK(0);//默认选择低电平,使用SPI模式0

配置SPI时序基本单元

起始条件与终止条件

        起始条件:SS从高电平切换到低电平

        终止条件:SS从低电平切换到高电平

//起始条件
void My_SPI_Start(void)
{//置低电平My_W_SS(0);
}//终止条件
void My_SPI_Stop(void)
{//置高电平My_W_SS(1);
}

交换一个字节

方法一

使用掩码,以此提取数据的每一位

//交换一个字节
uint8_t My_SPI_SwapByte(uint8_t ByteSend)
{uint8_t i, ByteReceive = 0x00;for(i = 0; i < 8; i++){//写MOSIMy_W_MOSI(ByteSend & (0x80 >> i));//SCK上升沿 置高电平My_W_SCK(1);//读MISOif(My_R_MISO() == 1){ByteReceive |= (0x80 >> i);}//SCK产生下降沿 置低电平My_W_SCK(0);}return ByteReceive;}

方法二

用移位数据本身来进行操作,好处是效率高,但是ByteSend数据在移位的过程中改变了,for循环执行完,原始传入的参数就没有了

//交换一个字节
uint8_t My_SPI_SwapByte2(uint8_t ByteSend)
{uint8_t i;for(i = 0; i < 8; i++){//写MOSIMy_W_MOSI(ByteSend & 0x80 );ByteSend <<= 1;//SCK上升沿 置高电平My_W_SCK(1);//读MISOif(My_R_MISO() == 1){ByteSend |= 0x01;}//SCK产生下降沿 置低电平My_W_SCK(0);}return ByteSend;}

SPI配置完成,接下来建立W25Q64的驱动层

W25Q64配置

#include "stm32f10x.h"         
#include "MySPI.h"void W25Q64_Init(void)
{MySPI_Init();
}

接下来实现业务代码,拼接完整时序

 宏定义指令集

根据手册指令表将指令宏定义出来

//宏定义指令集
#define W25Q64_WRITE_ENABLE							0x06
#define W25Q64_WRITE_DISABLE						0x04
#define W25Q64_READ_STATUS_REGISTER_1				0x05
#define W25Q64_READ_STATUS_REGISTER_2				0x35
#define W25Q64_WRITE_STATUS_REGISTER				0x01
#define W25Q64_PAGE_PROGRAM							0x02
#define W25Q64_QUAD_PAGE_PROGRAM					0x32
#define W25Q64_BLOCK_ERASE_64KB						0xD8
#define W25Q64_BLOCK_ERASE_32KB						0x52
#define W25Q64_SECTOR_ERASE_4KB						0x20
#define W25Q64_CHIP_ERASE							0xC7
#define W25Q64_ERASE_SUSPEND						0x75
#define W25Q64_ERASE_RESUME							0x7A
#define W25Q64_POWER_DOWN							0xB9
#define W25Q64_HIGH_PERFORMANCE_MODE				0xA3
#define W25Q64_CONTINUOUS_READ_MODE_RESET		    0xFF
#define W25Q64_RELEASE_POWER_DOWN_HPM_DEVICE_ID	    0xAB
#define W25Q64_MANUFACTURER_DEVICE_ID				0x90
#define W25Q64_READ_UNIQUE_ID						0x4B
#define W25Q64_JEDEC_ID								0x9F
#define W25Q64_READ_DATA							0x03
#define W25Q64_FAST_READ							0x0B
#define W25Q64_FAST_READ_DUAL_OUTPUT				0x3B
#define W25Q64_FAST_READ_DUAL_IO					0xBB
#define W25Q64_FAST_READ_QUAD_OUTPUT				0x6B
#define W25Q64_FAST_READ_QUAD_IO					0xEB
#define W25Q64_OCTAL_WORD_READ_QUAD_IO			    0xE3#define W25Q64_DUMMY_BYTE							0xFF

实现获取ID号的时序

*MID输出8位的厂商ID

*DID输出16位的设备ID

//获取ID号的时序
void W25Q64_ReadID(uint8_t* MID, uint16_t* DID)
{//开始传输My_SPI_Start();//交换发送一个字节 9FMy_SPI_SwapByte(W25Q64_JEDEC_ID);//给从机一个东西,目的是将对方的数据置换过来*MID = My_SPI_SwapByte(W25Q64_DUMMY_BYTE);//返回设备ID的高8位*DID = My_SPI_SwapByte(W25Q64_DUMMY_BYTE);*DID <<= 8;	//把第一次读取的数据运到DID的高8位去//返回设备ID的低8位*DID |= My_SPI_SwapByte(W25Q64_DUMMY_BYTE);//结束时序My_SPI_Stop();
}

写使能

//写使能
void W25Q64_WriteEnable(void)
{My_SPI_Start();My_SPI_SwapByte(W25Q64_WRITE_ENABLE);My_SPI_Stop();}

读状态寄存器1

判断芯片忙不忙

//读状态寄存器1
//判断芯片是否处于忙状态
void W25Q64_WaitBusy(void)
{uint32_t Timeout;My_SPI_Start();My_SPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1);//等待BUSYwhile ((My_SPI_SwapByte(W25Q64_DUMMY_BYTE) & 0x01) == 0x01){Timeout--;if(Timeout == 0){break;}}My_SPI_Stop();
}

页编程函数

根据Flash注意事项

        写入操作前必须先写使能,写入操作后等待忙状态,这里的页编程与扇形擦除进行了写入操作,需要注意事项。

//页编程
void W25Q64_PageProgram(uint32_t Address, uint8_t* DataArray, uint16_t Count)
{uint16_t i;W25Q64_WriteEnable();//写使能My_SPI_Start();My_SPI_SwapByte(W25Q64_PAGE_PROGRAM);//指定24位地址My_SPI_SwapByte(Address >> 16);My_SPI_SwapByte(Address >> 8);My_SPI_SwapByte(Address);for(i = 0; i < Count; i++){My_SPI_SwapByte(DataArray[i]);}My_SPI_Stop();W25Q64_WaitBusy();//等待BUSY(事后等待)
}

扇区擦除函数

//扇区擦除函数
void W25Q64_SectorErase(uint32_t Address)
{W25Q64_WriteEnable();//写使能My_SPI_Start();My_SPI_SwapByte(W25Q64_SECTOR_ERASE_4KB);//指定24位地址My_SPI_SwapByte(Address >> 16);My_SPI_SwapByte(Address >> 8);My_SPI_SwapByte(Address);My_SPI_Stop();W25Q64_WaitBusy();//等待BUSY(事后等待)}

读取数据

//读取数据
void W25Q64_ReadData(uint32_t Address, uint8_t* DataArray, uint32_t Count)
{uint32_t i;My_SPI_Start();My_SPI_SwapByte(W25Q64_READ_DATA);//指定24位地址My_SPI_SwapByte(Address >> 16);My_SPI_SwapByte(Address >> 8);My_SPI_SwapByte(Address);for(i = 0; i < Count; i++){DataArray[i] = My_SPI_SwapByte(W25Q64_DUMMY_BYTE);}My_SPI_Stop();}

主函数

#include "W25Q64.h"
int main(void)
{uint8_t MID;uint16_t DID;uint8_t ArraryWrite[] = {0x01, 0x02, 0x03, 0x04};uint8_t ArraryRead[4];OLED_Init();W25Q64_Init();OLED_ShowString(1, 1, "MID:");OLED_ShowString(1, 8, "DID:");OLED_ShowString(2, 1, "W:");OLED_ShowString(3, 1, "R:");W25Q64_ReadID(&MID, &DID);OLED_ShowHexNum(1, 5, MID, 2);OLED_ShowHexNum(1, 12, DID, 4);W25Q64_SectorErase(0x000000);W25Q64_PageProgram(0x000000, ArraryWrite, 4);W25Q64_ReadData(0x000000, ArraryRead, 4);OLED_ShowHexNum(2, 3, ArraryWrite[0], 2);OLED_ShowHexNum(2, 6, ArraryWrite[1], 2);OLED_ShowHexNum(2, 9, ArraryWrite[2], 2);OLED_ShowHexNum(2, 12,ArraryWrite[3], 2);OLED_ShowHexNum(3, 3, ArraryRead[0], 2);OLED_ShowHexNum(3, 6, ArraryRead[1], 2);OLED_ShowHexNum(3, 9, ArraryRead[2], 2);OLED_ShowHexNum(3, 12,ArraryRead[3], 2);while(1){}}

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

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

相关文章

apachePoi中XSSFClientAnchor图片坐标简述;填充多张图片

概述 业务中经常会遇到在单元格内填充图片的需求&#xff0c;而且要求指定图片在单元格内的位置。 一般都是用的apache的poi&#xff0c;设置图片坐标。 HSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2)dx1 dy1 起始单元…

Centos挂载镜像制作本地yum源,并补装图形界面

内网环境centos7.9安装图形页面内网环境制作本地yum源 上传镜像到服务器目录 创建目录并挂载镜像 #创建目录 cd /mnt/ mkdir iso#挂载 mount -o loop ./CentOS-7-x86_64-DVD-2009.iso ./iso #前面镜像所在目录&#xff0c;后面所挂载得目录#检查 [rootlocalhost mnt]# df -h…

ssti学习笔记(服务器端模板注入)

目录 一&#xff0c;ssti是什么 二&#xff0c;原理 所谓模板引擎&#xff08;三列&#xff0c;可滑动查看&#xff09; 三&#xff0c;漏洞复现 1&#xff0c;如何判断其所属的模板引擎&#xff1f; 2&#xff0c;判断清楚后开始注入 &#xff08;1&#xff09;Jinja2&a…

【前端】Python 闭包与JavaScript闭包的实现差异

目录 Python 闭包JavaScript 闭包 推荐超级课程&#xff1a; Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战 Python 闭包 如何定义&#xff1a; 在一个函数内部定义另一个函数&#xff0c;内部函数引用外部函数的变量。 def outer_function(text):…

【JVM详解二】常量池

一、常量池概述 JVM的常量池主要有以下几种&#xff1a; class文件常量池运行时常量池字符串常量池基本类型包装类常量池 它们相互之间关系大致如下图所示&#xff1a; 每个 class 的字节码文件中都有一个常量池&#xff0c;里面是编译后即知的该 class 会用到的字面量与符号引…

人工智能入门 数学基础 线性代数 笔记

必备的数学知识是理解人工智能不可或缺的要素&#xff0c;今天的种种人工智能技术归根到底都建立在数学模型之上&#xff0c;而这些数学模型又都离不开线性代数&#xff08;linear algebra&#xff09;的理论框架。 线性代数的核心意义&#xff1a;世间万事万物都可以被抽象成某…

C# Winform怎么设计串口,客户端和相机控件界面显示

首先我们必须把这个类创建好 INIAPI using System; using System.Text; using System.Runtime.InteropServices;namespace Ini {public class IniAPI{#region INI文件操作/** 针对INI文件的API操作方法&#xff0c;其中的节点&#xff08;Section)、键&#xff08;KEY&#x…

在 Windows 上使用 ZIP 包安装 MySQL 的详细步骤

以下是使用官方 ZIP 包在 Windows 上安装 MySQL 的详细步骤&#xff0c;确保能通过 mysql -uroot -p 成功连接。 步骤 1&#xff1a;下载 MySQL ZIP 包 访问 MySQL 官方下载页面&#xff1a; https://dev.mysql.com/downloads/mysql/选择 Windows (x86, 64-bit), ZIP Archive&…

el-table表格点击单元格实现编辑

使用 el-table 和 el-table-column 创建表格。在单元格的默认插槽中&#xff0c;使用 div 显示文本内容&#xff0c;单击时触发编辑功能。使用 el-input 组件在单元格中显示编辑框。data() 方法中定义了 tableData&#xff0c;tabClickIndex: null,tabClickLabel: ,用于判断是否…

Windows逆向工程入门之汇编环境搭建

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 Visual Studio逆向工程配置 基础环境搭建 Visual Studio 官方下载地址安装配置选项(后期可随时通过VS调整) 使用C的桌面开发 拓展可选选项 MASM汇编框架 配置MASM汇编项目 创建新项目 选择空…

手写一个C++ Android Binder服务及源码分析

手写一个C Android Binder服务及源码分析 前言一、 基于C语言编写Android Binder跨进程通信Demo总结及改进二、C语言编写自己的Binder服务Demo1. binder服务demo功能介绍2. binder服务demo代码结构图3. binder服务demo代码实现3.1 IHelloService.h代码实现3.2 BnHelloService.c…

DeepSeekMoE 论文解读:混合专家架构的效能革新者

论文链接&#xff1a;DeepSeekMoE: Towards Ultimate Expert Specialization in Mixture-of-Experts Language Models 目录 一、引言二、背景知识&#xff08;一&#xff09;MoE架构概述&#xff08;二&#xff09;现有MoE架构的问题 三、DeepSeekMoE架构详解&#xff08;一&a…

[每周一更]-(第133期):Go中MapReduce架构思想的使用场景

文章目录 **MapReduce 工作流程**Go 中使用 MapReduce 的实现方式&#xff1a;**Go MapReduce 的特点****哪些场景适合使用 MapReduce&#xff1f;**使用场景1. 数据聚合2. 数据过滤3. 数据排序4. 数据转换5. 数据去重6. 数据分组7. 数据统计8.**统计文本中单词出现次数****代码…

【C++高并发服务器WebServer】-13:多线程服务器开发

本文目录 一、多线程服务器开发二、TCP状态转换三、端口复用 一、多线程服务器开发 服务端代码如下。 #include <stdio.h> #include <arpa/inet.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <pthread.h>s…

「vue3-element-admin」告别 vite-plugin-svg-icons!用 @unocss/preset-icons 加载本地 SVG 图标

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template &#x1f33a; 仓库主页&#xff1a; GitCode︱ Gitee ︱ Github &#x1f496; 欢迎点赞 &#x1f44d; 收藏 ⭐评论 …

C#中深度解析BinaryFormatter序列化生成的二进制文件

C#中深度解析BinaryFormatter序列化生成的二进制文件 BinaryFormatter序列化时,对象必须有 可序列化特性[Serializable] 一.新建窗体测试程序BinaryDeepAnalysisDemo,将默认的Form1重命名为FormBinaryDeepAnalysis 二.新建测试类Test Test.cs源程序如下: using System; us…

深度学习在医疗影像分析中的应用

引言 随着人工智能技术的快速发展&#xff0c;深度学习在各个领域都展现出了巨大的潜力。特别是在医疗影像分析中&#xff0c;深度学习的应用不仅提高了诊断的准确性&#xff0c;还大大缩短了医生的工作时间&#xff0c;提升了医疗服务的质量。本文将详细介绍深度学习在医疗影像…

计算机领域QPM、TPM分别是什么并发指标,还有其他类似指标吗?

在计算机领域&#xff0c;QPM和TPM是两种不同的并发指标&#xff0c;它们分别用于衡量系统处理请求的能力和吞吐量。 QPM&#xff08;每分钟请求数&#xff09; QPM&#xff08;Query Per Minute&#xff09;表示每分钟系统能够处理的请求数量。它通常用于衡量系统在单位时间…

【安当产品应用案例100集】036-视频监控机房权限管理新突破:安当windows操作系统登录双因素认证解决方案

一、机房管理痛点&#xff1a;权限失控下的数据泄露风险 在智慧城市与数字化转型浪潮下&#xff0c;视频监控系统已成为能源、金融、司法等行业的核心安防设施。然而&#xff0c;传统机房管理模式中&#xff0c;值班人员通过单一密码即可解锁监控画面的操作漏洞&#xff0c;正…

Unity抖音云启动测试:如何用cmd命令行启动exe

相关资料&#xff1a;弹幕云启动&#xff08;原“玩法云启动能力”&#xff09;_直播小玩法_抖音开放平台 1&#xff0c;操作方法 在做云启动的时候&#xff0c;接完发现需要命令行模拟云环境测试启动&#xff0c;所以研究了下。 首先进入cmd命令&#xff0c;CD进入对应包的文件…