软件SPI读写W25Q64

文章目录

  • 前言
  • 接线
    • 引脚定义图
  • 软件SPI读写W25Q64
    • 代码规划
    • 代码实现
      • ThisSPI.c
      • ThisW25Q64.c
      • main.c


前言

SPI介绍:https://blog.csdn.net/qq_53922901/article/details/137142038
W25Q64介绍:
https://blog.csdn.net/qq_53922901/article/details/137197048

本文主要介绍使用软件模拟SPI时序来读写W25Q64,其他相关内容可见此专栏


接线

为了方便软件模拟和硬件SPI的切换,可以直接使用硬件SPI的接线,可由下面引脚定义得知
在这里插入图片描述

引脚定义图

在这里插入图片描述

软件SPI读写W25Q64

代码规划

使用ThisSPI.c来用于书写SPI基本时序单元的内容,然后使用ThisW25Q64.c来基于ThisSPI.c来调用这些SPI基本时序单元来完成读写的功能

代码实现

以下内容都使用同名头文件声明了.c文件中的函数

ThisSPI.c

#include "stm32f10x.h"                  // Device header// 封装写入CS位的函数
void ThisSPI_W_CS(uint8_t BitValue){GPIO_WriteBit(GPIOA,GPIO_Pin_4,(BitAction)BitValue);
}
// 封装写入CLK位的函数
void ThisSPI_W_CLK(uint8_t BitValue){GPIO_WriteBit(GPIOA,GPIO_Pin_5,(BitAction)BitValue);
}
// 封装写入MOSI位的函数
void ThisSPI_W_MOSI(uint8_t BitValue){GPIO_WriteBit(GPIOA,GPIO_Pin_7,(BitAction)BitValue);
}
// 封装读取MISO位的函数
uint8_t ThisSPI_R_MISO(void){return GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6);
}void ThisSPI_Init(void){// 初始化引脚配置RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;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);// 初始化引脚电平,使用SPI状态0ThisSPI_W_CS(1);ThisSPI_W_CLK(0);
}
/*** @brief  SPI起始时序单元* @param 	无* @retval 无*/
void ThisSPI_Start(void){ThisSPI_W_CS(0);
}
/*** @brief  SPI结束时序单元* @param 	无* @retval 无*/
void ThisSPI_End(void){ThisSPI_W_CS(1);
}
/*** @brief  SPI交换字节时序单元* @param 	Byte 要发送给从机的字节数据* @retval ByteReceive 从从机接收过来的字节数据*/
uint8_t ThisSPI_SwapByte(uint8_t Byte){uint8_t ByteReceive = 0x00,i = 0;		// 用于接收交换来的数据for(i=0;i<8;i++){// 时钟线下降沿,选择发送的数据ThisSPI_W_MOSI(Byte & (0x80>>i));// 时钟线上升沿,接收到从机发送过来的数据ThisSPI_W_CLK(1);if(ThisSPI_R_MISO() == 1){ByteReceive |= (0x80>>i);}ThisSPI_W_CLK(0);}return ByteReceive;
}

ThisW25Q64.c

#include "stm32f10x.h"                  // Device header
#include "ThisSPI.h"
// 指令集宏定义
#define JEDEC_ID 				0X9F
#define Write_Enable 			0X06
#define Read_Status_Register_1 	0X05
#define Page_Program 			0X02
#define Sector_Erase 			0X20
#define Read_Data 				0X03// 初始化
void ThisW25Q64_Init(void){ThisSPI_Init();}
// 参考指令集来完成SPI时序单元的拼接
/*** @brief  	读取产品ID* @param 	MID 产品ID,DID 设备ID* @retval 	无*/
void W25Q64_ReadID(uint8_t *MID,uint16_t *DID){ThisSPI_Start();ThisSPI_SwapByte(JEDEC_ID);*MID = ThisSPI_SwapByte(0XFF);*DID = ThisSPI_SwapByte(0XFF);*DID <<= 8;*DID |= ThisSPI_SwapByte(0XFF);ThisSPI_End();
}
/*** @brief  	写使能* @param 	无* @retval 	无*/
void W25Q64_WriteEnable(void){ThisSPI_Start();ThisSPI_SwapByte(Write_Enable);ThisSPI_End();
}
/*** @brief  	等待写入完成(通过状态寄存器1的BUSY位)* @param 	无* @retval 	无*/
void W25Q64_WaitBUSY(void){uint32_t Timeout = 10000;ThisSPI_Start();ThisSPI_SwapByte(Read_Status_Register_1);while((ThisSPI_SwapByte(0XFF) & 0x01) == 0x01){Timeout--;if(Timeout == 0) break;}ThisSPI_End();
}
/*** @brief  	页写入* @param 	Address,页地址* @param 	DataArr,写入的数据* @param 	Count,一次写入的大小* @retval 	无*/
void W25Q64_PageProgram(uint32_t Address,uint8_t *DataArr,uint16_t Count){uint8_t i;W25Q64_WriteEnable();ThisSPI_Start();ThisSPI_SwapByte(Page_Program);ThisSPI_SwapByte(Address>>16);ThisSPI_SwapByte(Address>>8);ThisSPI_SwapByte(Address);for(i=0;i<Count;i++){ThisSPI_SwapByte(DataArr[i]);}ThisSPI_End();W25Q64_WaitBUSY();
}
/*** @brief  	扇区擦除* @param 	Address,页地址* @retval 	无*/
void W25Q64_SectorErase(uint32_t Address){W25Q64_WriteEnable();ThisSPI_Start();ThisSPI_SwapByte(Sector_Erase);ThisSPI_SwapByte(Address>>16);ThisSPI_SwapByte(Address>>8);ThisSPI_SwapByte(Address);ThisSPI_End();W25Q64_WaitBUSY();
}
/*** @brief  	读取页内数据* @param 	Address,页地址* @param 	DataArr,用于存取读取的数据* @param 	Count,读取数据的大小* @retval 	无*/
void W25Q64_ReadData(uint32_t Address,uint8_t *DataArr,uint32_t Count){uint32_t i;ThisSPI_Start();ThisSPI_SwapByte(Read_Data);ThisSPI_SwapByte(Address>>16);ThisSPI_SwapByte(Address>>8);ThisSPI_SwapByte(Address);for(i=0;i<Count;i++){DataArr[i] = ThisSPI_SwapByte(0XFF);}ThisSPI_End();
}

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "ThisW25Q64.h"uint8_t MID;
uint16_t DID;
uint8_t ArrWrite[] = {0x11,0x92,0x73,0x24};
uint8_t ArrRead[4];int main(void)
{OLED_Init();OLED_ShowString(1,1,"MID:");OLED_ShowString(1,8,"DID:");ThisW25Q64_Init();W25Q64_ReadID(&MID,&DID);OLED_ShowHexNum(1,5,MID,2);OLED_ShowHexNum(1,12,DID,4);OLED_ShowString(2,1,"W:");OLED_ShowString(3,1,"R:");// 对页的操作一般都以此页页首地址开始,写操作不能跨页,读操作可以跨页W25Q64_SectorErase(0X000000);W25Q64_PageProgram(0X000000,ArrWrite,4);W25Q64_ReadData(0X000000,ArrRead,4);OLED_ShowHexNum(2,3,ArrWrite[0],2);OLED_ShowHexNum(2,5,ArrWrite[1],2);OLED_ShowHexNum(2,7,ArrWrite[2],2);OLED_ShowHexNum(2,9,ArrWrite[3],2);OLED_ShowHexNum(3,3,ArrRead[0],2);OLED_ShowHexNum(3,5,ArrRead[1],2);OLED_ShowHexNum(3,7,ArrRead[2],2);OLED_ShowHexNum(3,9,ArrRead[3],2);while (1){}
}

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

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

相关文章

C++性能测试工具

使用示例main.cpp // g-13 -O3 -stdc17 main.cpp profile.cpp #include <iostream> #include <chrono> #include <stdint.h> #include <mutex> // std::mutex#include "profile.h" #include "profile_rdtsc.h"std::mut…

Java基于SpringBoot+Vue 的医院预约挂号系统

博主介绍&#xff1a;✌程序员徐师兄、10年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447…

【问题记录】使用Audition播放时低8位数据会被修改

一&#xff0c;问题现象记录 使用Audition连接UAC播放采样点数据比较大的时候&#xff0c;低8位的数据会被修改。如果对低8位数据敏感的情况&#xff0c;需要使用其他播放器进行播放。 二&#xff0c;问题复现 1&#xff0c;使用C代码生成一个PCM文件&#xff1a; #include…

智慧水库解决方案(打造水库智慧监测体系)

​作为一名水利自动化系统集成商,最近我司接手了一个智慧水库建设项目。这个项目位于一座山区的大型水库,目的是对其进行现代化、智能化改造,提升供水、防洪等管理水平。&#xff08;key-iot.com.cn&#xff09; 在方案设计之初,我们组织了现场勘测,全面了解水库的实际情况。这…

win11系统和ubuntu双系统首次连接网线上网流程

硬件准备 首先需要将网线连接到电脑&#xff0c;另一头可以连接交换机或者路由器 上网前需要拨号上网&#xff0c;如果是连的路由器&#xff0c;那么一台路由器上拨号一次就行了。 如果是连的交换机需要拨号上网 这里踩的第一个坑是刚开始电脑连的是交换机1又连的交换机2&…

STM32中C编程引入C++程序

C具备类的创建思想很实用于实际场景多相似性的框架搭建&#xff1b;同种类型或相似类型的C的优势明显因此进行相互嵌套使用 需要在C中使用C类的话&#xff0c;你可以通过C的“extern "C"”语法来实现。这允许你在C代码中使用C的链接方式&#xff0c;而在C代码中使用…

【Linux】UDP编程【上】{诸多编程接口/小白入门式讲解}

文章目录 0.预备知识0.1套接字0.2TCP/UDP0.3大小端问题 1.socket 常见API1.1socket1.2各个接口1.3int bind();1.3网络头文件四件套1.4bzero1.5recvfrom1.6sendto() 2.UDP编程2.1服务器编程2.2客户端编程2.3运行测试2.3.1本机通信2.3.2popen2.3.3strcasestr2.3.4回顾C11智能指针…

微电网优化:基于肝癌算法(Liver Cancer algorithm, LCA)的微电网优化(提供MATLAB代码)

一、微电网优化模型 微电网是一个相对独立的本地化电力单元&#xff0c;用户现场的分布式发电可以支持用电需求。为此&#xff0c;您的微电网将接入、监控、预测和控制您本地的分布式能源系统&#xff0c;同时强化供电系统的弹性&#xff0c;保障您的用电更经济。您可以在连接…

Mamba解读(FlashAttention,SSM,LSSL,S4,S5,Mamba)

Sequence modelScale and EfficiencyFlashAttentionMotivationMethodFlashDecoding MambaState-Space Models&#xff08;SSM&#xff09;Selective State Space Models&#xff08;Mamba&#xff09; Sequence model seq2seq任务将 输入序列 x ( t ) x(t) x(t) 映射为 输出序…

每日两题 / 1.两数之和 49.字母异位词分组(leetcode热题100)

1. 两数之和 - 力扣&#xff08;LeetCode&#xff09; 暴力解法&#xff1a; O ( N 2 ) O(N^2) O(N2)遍历数组&#xff0c;找两个数相加为target O ( N ) O(N) O(N)解法&#xff1a;将所有数排序&#xff0c;并记录这些数的下标&#xff0c;双指针从左右向中间走。指向的两数…

吴恩达深度学习笔记:深层神经网络(Deep Neural Networks)4.1-4.4

目录 第一门课&#xff1a;神经网络和深度学习 (Neural Networks and Deep Learning)第四周&#xff1a;深层神经网络(Deep Neural Networks)4.1 深层神经网络&#xff08;Deep L-layer neural network&#xff09;4.2 前向传播和反向传播&#xff08;Forward and backward pro…

vscode 重命名很慢或失败 vscode renames are slow

网上问题&#xff0c; 插件问题&#xff08;我遇见的排除&#xff0c;不是&#xff09;被其他程序占用问题&#xff0c;&#xff08;我这边是这个&#xff09; 解决方案&#xff1a; 打开【资源管理器】&#xff0c;使用火绒 或其他软件&#xff0c;查看文件夹 or 文件 被哪个…

智慧公厕系统3.0有哪些新功能呢

随着科技的不断进步&#xff0c;智慧公厕系统也在不断升级和完善。最新推出的智慧公厕系统3.0&#xff0c;集成了一系列创新功能&#xff0c;为城市公共卫生设施管理带来了全新的体验和便利。让我们一起来看看智慧公厕系统3.0有哪些新功能吧。 1、云端管理平台&#xff1a;智慧…

家用洗地机哪个牌子好?四大热销机型推荐,值得推荐!

随着科技的进步&#xff0c;洗地机在日常生活中能够帮助人们省时省力地打扫卫生&#xff0c;但市面上出现了各种各样的洗地机&#xff0c;好坏参差不齐&#xff0c;选择一个好品牌的洗地机非常重要&#xff0c;因为它们有着可靠的质量保证。那市面上如此众多的洗地机品牌&#…

8×8点阵数码管显示驱动/大电流数码管驱动IC-VK16K33C SOP20

产品品牌&#xff1a;永嘉微电/VINKA 产品型号&#xff1a;VK16K33C 封装形式&#xff1a;SOP20 概述 VK16K33C是一种带按键扫描接口的数码管或点阵LED驱动控制专用芯片&#xff0c;内部集成有数据锁 存器、键盘扫描、LED 驱动模块等电路。数据通过I2C通讯接口与MCU通信。SE…

为什么电脑越用越慢!

电脑随着时间推移逐渐变慢是一个常见的现象,其背后涉及多种原因。以下是导致电脑运行速度变慢的几个主要因素: 系统资源消耗增加 软件更新与新增应用:随着软件版本的更新和新应用程序的安装,它们往往对硬件资源的需求更高,尤其是对处理器、内存和硬盘的要求。这些新软件可…

Java毕业设计 基于SpringBoot vue流浪动物救助网站

Java毕业设计 基于SpringBoot vue流浪动物救助网站 SpringBoot 流浪动物救助网站 功能介绍 首页 图片轮播 动物领养/捐赠 留言 论坛 发布帖子 公告信息 商品信息 添加购物车 立即购买 寻宠请求 购物车 注册登录 个人中心 余额充值 收货地址 动物收藏 动物领养审核 商品订单 …

6AV6643-5CB10-0BN0触摸屏

6AV6643-5CB10-0BN0触摸屏 6AV6643-5CB10-0BN0触摸屏 6AV6643-5CB10-0BN0触摸屏 商品编号(市售编号) 6AV6643-5CB10-0BN0 产品说明 SIMATIC MP 277 8" 触摸屏 多功能面板带剩磁存储器 7.5" TFT 显示屏 6MByte 项目组态存储器 可项目组态&#xff0c;利用 W…

R语言绘图 | 散点小提琴图

原文链接&#xff1a;R语言绘图 | 散点小提琴图 本期教程 写在前面 本期的图形来自发表在Nature期刊中的文章&#xff0c;这样的基础图形在日常分析中使用频率较高。 获得本期教程数据及代码&#xff0c;后台回复关键词&#xff1a;20240405 绘图 设置路径 setwd("You…

【经典算法】LeetCode 5: 最长回文子串(Java/C/Python3实现含注释说明,Medium)

目录 题目描述思路及实现方式一&#xff1a;动态规划法思路代码实现Java版本C语言版本Python3版本 复杂度分析 方式二&#xff1a;中心扩展法思路代码实现Java版本C语言版本Python3版本 复杂度分析 总结相似题目 标签(题目类型)&#xff1a;回文串、动态规划 题目描述 给定一…