W25Q128读写实验(一)

十二、SPI

1. IIC与SPI对比

1. IIC 是半双工通讯,无法同时收发信息;SPI 是全双工通讯,可以同时收发信息; 2. IIC 通讯协议较复杂,而 SPI 通讯协议较简单; 3. IIC 需要通过地址选择从机,而 SPI 只需一个引脚即可选中从机; 4. IIC 通讯速率一般为 100kHz 左右,而 SPI 可以达到 50MHz ; 5. IIC 需要的通讯线较少,而 SPI 需要较多。

2. SPI是什么?

SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线,并且 在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这 种简单易用的特性,越来越多的芯片集成了这种通信协议,比如 AT91RM9200 。

3. SPI物理架构

SPI 总线包含 4 条通讯线,分别为 SS、SCK、MOSI、MISO。它们的作用介绍如下 :

(1) MISO – Master Input Slave Output,主设备数据输入,从设备数据输出

(2) MOSI – Master Output Slave Input,主设备数据输出,从设备数据输入

(3) SCK – Serial Clock,时钟信号,由主设备产生

(4) CS – Chip Select,片选信号,由主设备控制

STM32F1 系列芯片有 3 个SPI 接口。

4. SPI工作原理

5. SPI工作模式 

时钟极性(CPOL):

没有数据传输时时钟线的空闲状态电平

0:SCK在空闲状态保持低电平

1:SCK在空闲状态保持高电平

时钟相位(CPHA):

时钟线在第几个时钟边沿采样数据

0:SCK的第一(奇数)边沿进行数据位采样,数据在第一个时钟边沿被锁存

1:SCK的第二(偶数)边沿进行数据位采样,数据在第二个时钟边沿被锁存

模式 0 和模式 3 最常用。

模式 0 时序图:

模式 3 时序图:

6. SPI寄存器及库函数介绍

读取为w25q128  数据读出来

90—dum-00h

 模块:W25Q128

小实验:读写W25Q128实验

实验目的

读写W25Q128

/---------w25q128.h--------------/

#include "sys.h"
//拉高拉低 读需要将nss拉低,之前虽然初始化了pin
//4引脚但是初始化是没有写但是直接write_pin比较麻烦实验在这里封装一次
#define W25Q128_CS(x)   do{ x ? \			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET): \		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET); \								}while(0)uint16_t w25q128_read_id(void);
void w25q128_init(void);

/---------w25q128.c--------------/

spi接口封装
初始化

SPI_HandleTypeDef spi_handle = {0};//多个参数
void w25q128_spi_init(void)
{spi_handle.Instance = SPI1;                //spi_handle.Init.Mode = SPI_MODE_MASTER;    //选择是主设备还是从设备spi_handle.Init.Direction = SPI_DIRECTION_2LINES;//选择几根线的  既要读又要写--全双工spi_handle.Init.DataSize  = SPI_DATASIZE_8BIT;  //数据格式spi_handle.Init.CLKPolarity = SPI_POLARITY_LOW;//  CPOL = 0 四种工作模式spi_handle.Init.CLKPhase = SPI_PHASE_1EDGE;//      CPHA = 0 计数边沿 工作模式0spi_handle.Init.NSS = SPI_NSS_SOFT;//  随便拿一个GPIO口控制模块 spi_handle.Init.BaudRatePrescaler  = SPI_BAUDRATEPRESCALER_256;// 波特率分频随便选择一个spi_handle.Init.FirstBit = SPI_FIRSTBIT_MSB;// 高位先行还是地位先行spi_handle.Init.TIMode   = SPI_TIMODE_DISABLE;//  暂时不用管spi_handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;//  CPOL = 0 spi_handle.Init.CRCPolynomial  = 7;HAL_SPI_Init(&spi_handle);
}

msp函数

void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{//gpio和中断,时钟进行操作 三个spi//首先先判断if(hspi->Instace == SPI1)
{GPIO_InitTypeDef gpio_initstruct;//打开时钟__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_SPI1_SCK_ENABLE();//调用GPIO初始化函数gpio_initstruct.Pin = GPIO_PIN_4;gpio_initstruct.Mode= GPIO_MODE_OUTPUT;gpio_initstruct.Pull= GPIO_PULLUP;//上拉gpio_initstruct.Speed=GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA,&gpio_initstruct);//CLK PA5 DI PA7gpio_initstruct.Pin  = GPIO_PIN__5 | GPIO_PIN_7;gpio_initstruct.Mode = GPIO_MODE_AF_PP;HAL_GPIO_Init(GPIOA,&gpio_initstruct);//IN输入引脚gpio_initstruct.Pin  = GPIO_PIN_6;gpio_initstruct.Mode = GPIO_MODE_INPUT;HAL_GPIO_Init(GPIOA,&gpio_initstruct);
}
}

封装读写函数  有个返回值

uint8_t w25q128_spi_swap_byte(uint8_t data)
{//发的同时也在收//句柄,发送的数据,接受的数据,发送几个字节,超时uint8_t recv_data = 0;HAL_SPI_TransmitReceive(&spi_handle,&data,&recv_data,1,1000);return recv_data;
}

w25q128初始化  调用spi初始化代码

void w25q128_init(void)
{w25q128_spi_init();
}

读id  引脚拉低写0

uint16_t w25q128_read_id(void)
{uint16_t device_id = 0;W25Q128_CS(0);//拉低w25q128_spi_swap_byte(0x90);//由数据手册可先发90w25q128_spi_swap_byte(0x00);//dummyw25q128_spi_swap_byte(0x00);w25q128_spi_swap_byte(0x00);device_id = w25q128_spi_swap_byte(0xFF) << 8;//两个字节的内容把这个数据放在device高位,左移8位device_id |= w25q128_spi_swap_byte(0xFF);//两个字节的内容把这个数据放在device低位为了不让高位干等会直接没掉,直接用|来操作}

写使能

void w25q128_writ_enable(void)
{}

读数据
16读的多的数据可能不够   写的内容  写的数据大小

void w25q128_read_data(uint32_t address, uint8_t *data, uint8_t size)
{}

页写  256字节最多

void w25q128_write_page(uint32_t address, uint8_t *data, uint8_t size)
{}

扇区擦除  位置传给他

void w25q128_erase_sector(uint32_t address)
{}

/------------main.c-----------/

#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "w25q128.h"
int main(void)
{HAL_Init();                         /* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */led_init();	/* LED初始化 */uart1_init(115200);w25q128_init();	
//			led1_on();
//			led1_off();printf("helloworld!\r\n");uint16_t device_id =w25q128_read_id();printf("device_id: %X\r\n",device_id);while(1){ }
}

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

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

相关文章

uniApp使用腾讯地图提示未添加maps模块

uniApp使用腾讯地图&#xff0c;打包提示未添加maps模块解决方案 这是报错信息&#xff0c;在标准基座运行的时候是没问题的&#xff0c;但是打包后会提示未添加&#xff0c;可以通过在mainfest里面把地图插件上腾讯地图的key更换高德地图的key&#xff0c;定位服务可以继续用腾…

【开源项目】数字孪生轨道~经典开源项目数字孪生智慧轨道——开源工程及源码

飞渡科技数字孪生轨道可视化平台&#xff0c;基于国产数字孪生引擎&#xff0c;结合物联网IOT、大数据、激光雷达等技术&#xff0c;对交通轨道进行超远距、高精度、全天侯的监测&#xff0c;集成轨道交通运营数据&#xff0c;快速准确感知目标&#xff0c;筑牢轨交运营生命线。…

【HarmonyOS之旅】DevEco Studio的安装与环境配置

目录 1 -> 下载与安装DevEco Studio 1.1 -> 运行环境要求 1.2 -> 下载和安装DevEco Studio 2 -> 配置环境变量 3 -> 配置开发环境 4 -> 开发项目准备 5 -> 实用小技巧 5.1 -> 中文插件 2 -> 简化工程目录栏 1 -> 下载与安装DevEco Stud…

Word使用分隔符实现页面部分分栏

文章目录 Word使用分隔符实现页面部分分栏分隔符使用页面设置 Word使用分隔符实现页面部分分栏 分隔符使用 word中的分隔符&#xff1a; 前面不分栏&#xff0c;后面分栏(或前面分栏&#xff0c;后面不分栏)&#xff0c;只需要在分隔位置处插入分隔符&#xff1a;“连续”即…

多协议视频监控汇聚/视频安防系统Liveweb搭建智慧园区视频管理平台

智慧园区作为现代化城市发展的重要组成部分&#xff0c;不仅承载着产业升级的使命&#xff0c;更是智慧城市建设的重要体现。随着产业园区竞争的逐渐白热化&#xff0c;将项目打造成完善的智慧园区是越来越多用户关注的内容。 然而我们往往在规划前期就开始面临众多难题&#…

PHP接入美团联盟推广

美团给的文档没有PHP的示例代码&#xff0c;下面是以Javascript示例更改的PHP代码&#xff0c;并且已经跑通 一、计算签名 签名类&#xff0c;因为接口不多&#xff0c;所以这里只写了获取请求头 class Meituan {private $APP_KEY 你的APP_KEY;private $APP_SECRET 你的APP…

ChatGPT重大更新:新增实时搜索和高级语音

12月17日消息&#xff0c;据报道&#xff0c;OpenAI开启了第八天技术分享直播&#xff0c;对ChatGPT搜索功能进行了大量更新。 此次ChatGPT新增的功能亮点纷呈。其中&#xff0c;实时搜索功能尤为引人注目。OpenAI对搜索算法进行了深度优化&#xff0c;使得用户提出问题后&…

Vue3组件封装技巧与心得

摘要&#xff1a; 日常开发中&#xff0c;用Vue组件进行业务拆分&#xff0c;代码解耦是一个很好的选择&#xff1b; 今天就来分享一下我在使用Vue3进行组件封装的一些技巧和心得&#xff0c;希望能够帮助到大家&#xff1b; 1. 组件特性&#xff1a; 在Vue中组件是一个独立的…

数据分析实战—鸢尾花数据分类

1.实战内容 (1) 加载鸢尾花数据集(iris.txt)并存到iris_df中,使用seaborn.lmplot寻找class&#xff08;种类&#xff09;项中的异常值&#xff0c;其他异常值也同时处理 。 import pandas as pd from sklearn.datasets import load_iris pd.set_option(display.max_columns, N…

【自用】通信内网部署rzgxxt项目_01,后端pipeDemo部署(使用nssm.exe仿照nohup)

做完这些工作之后&#xff0c;不要忘记打开 Windows Server 的防火墙端口&#xff0c;8181、8081、8080、22、443、1521 做完这些工作之后&#xff0c;不要忘记打开 Windows Server 的防火墙端口&#xff0c;8181、8081、8080、22、443、1521 做完这些工作之后&#xff0c;不要…

【Apache Doris】周FAQ集锦:第 26 期

SQL问题 Q1 doris 3.0存算分离模式下&#xff0c;建表的时是否需要指定表的副本数 不需要&#xff0c;指定了也会忽略&#xff1b;存算分离模式下&#xff0c;数据副本由远端存储去管控。 Q2 doris 通过dbeaver查询时报错&#xff1a;[SXXXX]… doris的错误码通常都是EXXXX&…

OpenSSL 心脏滴血漏洞(CVE-2014-0160)

OpenSSL 心脏滴血漏洞(CVE-2014-0160) Openssl简介: 该漏洞在国内被译为"OpenSSL心脏出血漏洞”&#xff0c;因其破坏性之大和影响的范围之广&#xff0c;堪称网络安全里程碑事件。 OpenSSL心脏滴血漏洞的大概原理是OpenSSL在2年前引入了心跳(hearbea0机制来维特TS链接的…

Git实用指南(精简版)

目录 读者须知 Git是什么 Git的原理 文件在Git中的几种状态 快速上手 结尾 读者须知 本文章适合从未接触过git,或者需要深度学习Git的用户进行阅读. 文末有详细的文档,读者可以前往Github下载阅读!!三克油 Git是什么 简单来说,Git是一个代码备份工具,你可以使用指令对…

YOLOv8目标检测(七)_AB压力测试

YOLOv8目标检测(一)_检测流程梳理&#xff1a;YOLOv8目标检测(一)_检测流程梳理_yolo检测流程-CSDN博客 YOLOv8目标检测(二)_准备数据集&#xff1a;YOLOv8目标检测(二)_准备数据集_yolov8 数据集准备-CSDN博客 YOLOv8目标检测(三)_训练模型&#xff1a;YOLOv8目标检测(三)_训…

在 Spring Boot 3 中实现基于角色的访问控制

基于角色的访问控制 (RBAC) 是一种有价值的访问控制模型,可增强安全性、简化访问管理并提高效率。它在管理资源访问对安全和运营至关重要的复杂环境中尤其有益。 我们将做什么 我们有一个包含公共路由和受限路由的 Web API。受限路由需要数据库中用户的有效 JWT。 现在用户…

线程知识总结(一)

1、概述 1.1 进程与线程 进程是程序运行时&#xff0c;操作系统进行资源分配的最小单位&#xff0c;包括 CPU、内存空间、磁盘 IO 等。从另一个角度讲&#xff0c;进程是程序在设备&#xff08;计算机、手机等&#xff09;上的一次执行活动&#xff0c;或者说是正在运行中的程…

OpenCV圆形标定板检测算法findGrid原理详解

OpenCV的findGrid函数检测圆形标定板的流程如下: class CirclesGridClusterFinder {CirclesGridClusterFinder(const CirclesGridClusterFinder&); public:CirclesGridClusterFinder

基于SpringBoot+Vue实现的个人备忘录系统

&#x1f384; 写在前面 最近学习vue&#xff0c;所以抽时间就用SpringBootVue做了一个个人备忘录&#xff0c;本意是想打造一个轻量级的、自托管的备忘录中心&#xff0c;可能是老了&#xff08;haha&#xff09;,很多时候都觉得好记性不如烂笔头&#xff0c;所以就有了这个小…

docker简单命令

docker images 查看镜像文件 docker ps -a 查看容器文件 docker rm 0b2 删除容器文件&#xff0c;id取前三位即可 docker rmi e64 删除镜像文件&#xff08;先删容器才能删镜像&#xff09;&#xff0c;id取前三位即可 在包含Dockerfile文件的目录…

【前端】vue数组去重的3种方法

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、数组去重说明二、Vue数组去重的3种方法 前言 随着开发语言及人工智能工具的普及&#xff0c;使得越来越多的人会主动学习使用一些开发工具&#xff0c;本…