STM32标准库-FLASH

FLASH模仿EEPROM

        STM32本身没有自带EEPROM,但是自带了FLASH存储器。

        STM32F103ZET6自带 1M字节的FLASH空间,和 128K+64K的SRAM空间。

        STM32F4 的 SPI 功能很强大,SPI 时钟最高可以到 37.5Mhz,支持 DMA,可以配置为 SPI协议或者 I2S 协议(支持全双工 I2S)。

SPI简介

        SPI,串行外围设备接口。主要应用在 EEPROM,FLASH,实时时钟,AD 转换器,还有数字信号处理器和数字信号解码器之间。是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线。

SPI内部结构简明图

SPI 接口一般使用 4 条线通信:

        MISO 主入从出。

        MOSI 主出从入。

        SCLK 时钟信号,由主设备产生。

        CS 从设备片选信号,由主设备控制。

        主机和从机都有一个移位寄存器,主机通过向自己的SPI串行寄存器写入一个字节来发起一次传输。寄存器通过MOSI信号线将字节传送给从机,从机将自己移位寄存器的内容通过MISO信号线返回给主机。这样,两个移位寄存器的内容被交换。

        外设的写操作和读操作是同步完成的,如果只进行写操作,主机只需忽略接收到的字节;反之,若主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输

        SPI总线有四种工作方式,通过配置时钟极性(CPOL)相位(CPHA)实现。CPOL决定时钟空闲状态电平,CPHA选择数据传输的采样时刻。主从设备需保持时钟配置一致。

SPI1主模式配置步骤

1)配置相关引脚的复用功能,使能 SPI1 时钟。

        启用SPI1需两步:

        首先使能SPI1时钟,通过APB2ENR的第12位设置;

        然后将PB3、4、5配置为复用输出AF5,分别对应SCK、MISO、MOSI,CS由软件管理。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);//使能 SPI1 时钟

        复用 PB3,PB4,PB5 为 SPI1 引脚的方法为:

GPIO_PinAFConfig(GPIOB,GPIO_PinSource3,GPIO_AF_SPI1); //PB3 复用为 SPI1
GPIO_PinAFConfig(GPIOB,GPIO_PinSource4,GPIO_AF_SPI1); //PB4 复用为 SPI1
GPIO_PinAFConfig(GPIOB,GPIO_PinSource5,GPIO_AF_SPI1); //PB5 复用为 SPI1

        同时我们设置相应的引脚模式为复用功能模式:

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能

2)初始化 SPI1,设置 SPI1 工作模式等。

        通过SPI1_CR1寄存器配置SPI1:

        设为主机模式

        数据格式8位

        设置SCK时钟极性采样方式(CPOL/CPHA),

        并调整时钟频率至最大37.5MHz,

        同时确定数据格式(MSB或LSB在前)。

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

typedef struct
{
 uint16_t SPI_Direction;//通信方式,半双工、全双工
 uint16_t SPI_Mode;     //设置主从模式。例如主机模式SPI_Mode_Master
 uint16_t SPI_DataSize; //8/16位帧格式选择。8位传输则SPI_DataSize_8b。
 uint16_t SPI_CPOL;     //时钟极性。决定同步时钟空闲状态的电平。
 uint16_t SPI_CPHA;     //采样方式。在串行同步时钟的第几个跳变沿采集信号。SPI_CPHA_2Edge位为第2个跳变沿。
 uint16_t SPI_NSS;      //设置NSS信号由硬件控制还是软件控制。SPI_NSS_Soft软件控制
 uint16_t SPI_BaudRatePrescaler; //波特率预分频值。有2到256分频共八个值可选。
                                 //初始化的时候我们选择 256 分频值
                                 //SPI_BaudRatePrescaler_256,传输速度为 84M/256=328.125KHz。
//数据传输顺序是MSB在前还是LSB在前。MSB为最高有效位,LSB最低有效位。
 uint16_t SPI_FirstBit;         
 uint16_t SPI_CRCPolynomial; //CRC校验多项式,大于1即可。
}SPI_InitTypeDef;

使能SPI1

SPI_Cmd(SPI1, ENABLE); //使能 SPI1 外设

SPI 传输数据

//往SPIx数据寄存器写入数据,实现发送
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);
//从SPI的数据寄存器读数据
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);

查看 SPI 传输状态

        SPI传输过程中经常要判断数据是否传输完成发送区是否为空等等状态。

//检查SPI1的接收缓冲区非空
SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE);

W25Q128简介

        W25Q128将 16M的容量分为 256个块,每个块64K字节

        一个块又分为 16个扇区,每个扇区 4K字节

        最小擦除单位为一个扇区,也就是 4K字节。

        W25Q128支持不超过存储范围的任意地址开始读取数据,在发送24位地址之后程序就可以开始循环读数据,其地址会自动增加

//读取 SPI FLASH 
//在指定地址开始读取指定长度的数据
//NumByteToRead:要读取的字节数(最大 65535)
void W25QXX_Read(u8* pBuffer,      //数据存储区  
                 u32 ReadAddr,     //开始读取的地址(24bit)
                 u16 NumByteToRead) 
{ 
    u16 i; 
    W25QXX_CS=0; //使能器件 
    SPI1_ReadWriteByte(W25X_ReadData); //发送读取命令 
    SPI1_ReadWriteByte((u8)((ReadAddr)>>16)); //发送 24bit 地址 
    SPI1_ReadWriteByte((u8)((ReadAddr)>>8)); 
    SPI1_ReadWriteByte((u8)ReadAddr); 
    for(i=0;i<NumByteToRead;i++)
    { 
        pBuffer[i]=SPI1_ReadWriteByte(0XFF); //循环读数,主机发送空字节 
    }
    W25QXX_CS=1; 
}

        正点原子提供的FLASH写入函数支持在 W25Q128的任意地址写入不超过容量的任意长度。

         /4096获取扇区地址

        %4096获取在扇区内的偏移

        4096-扇区偏移 = 扇区剩余空间大小。

        在SPI Flash写入时,需判断扇区是否需擦除,即检查目标区域是否全为0xFF

        因Flash写入前需擦除(置位为1),擦除后扇区全为0xFF。若区域非全0xFF,则需擦除;否则可直接写入,因未擦除位写0无效。

//写 SPI FLASH 
//在指定地址开始写入指定长度的数据
//该函数带擦除操作!
//pBuffer:数据存储区 WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大 65535) 
u8 W25QXX_BUFFER[4096];
void W25QXX_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite) 
{ 
    u32 secpos;
    u16 secoff; u16 secremain; u16 i; 
    u8 * W25QXX_BUF; 
    W25QXX_BUF=W25QXX_BUFFER; 
    secpos=WriteAddr/4096;//扇区地址 
    secoff=WriteAddr%4096;//在扇区内的偏移
    secremain=4096-secoff;//扇区剩余空间大小
    //printf("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);//测试用
    if(NumByteToWrite<=secremain) //写入的字节数小于扇区剩余字节
        secremain=NumByteToWrite; //不大于 4096 个字节
    while(1) 
    {
        W25QXX_Read(W25QXX_BUF,secpos*4096,4096);//读出整个扇区的内容
        for(i=0;i<secremain;i++)//校验数据,遍历整个扇区,判断是否都是0xFF
        {
            if(W25QXX_BUF[secoff+i]!=0XFF)break;//需要擦除
        }
        if(i<secremain)//需要擦除
        {
            W25QXX_Erase_Sector(secpos);//擦除这个扇区
            for(i=0;i<secremain;i++) //复制
            {
                W25QXX_BUF[i+secoff]=pBuffer[i]; 
            }
            W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//写入整个扇区
        }
    else 
    {
        W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);//已擦除的,直接写
    }
    if(NumByteToWrite==secremain) 
        break;//写入结束了
    else//写入未结束
    {
        secpos++; //扇区地址增 1
        secoff=0; //偏移位置为 0 
        pBuffer+=secremain; //指针偏移
        WriteAddr+=secremain; //写地址偏移 
        NumByteToWrite-=secremain; //字节数递减
        //如果要写入的字节数
        if(NumByteToWrite>4096)
            secremain=4096;//下一个扇区还是写不完
        else 
            secremain=NumByteToWrite; //下一个扇区可以写完了
        }
    }; 
}

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

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

相关文章

重学设计模式-工厂模式(简单工厂模式,工厂方法模式,抽象工厂模式)

在平常的学习和工作中&#xff0c;我们创建对象一般会直接用new&#xff0c;但是很多时候直接new会存在一些问题&#xff0c;而且直接new会让我们的代码变得非常繁杂&#xff0c;这时候就会巧妙的用到设计模式&#xff0c;平常我们通过力扣学习的算法可能并不会在我们工作中用到…

linux(centos) 环境部署,安装JDK,docker(mysql, redis,nginx,minio,nacos)

目录 1.安装JDK (非docker)1.1 将文件放在目录下&#xff1a; /usr/local/jdk1.2 解压至当前目录1.3 配置环境变量 2.安装docker2.1 验证centos内核2.2 安装软件工具包2.3 设置yum源2.4 查看仓库中所有docker版本&#xff0c;按需选择安装2.5 安装docker2.6 启动docker 并 开机…

算法日记 40 day 单调栈

最后两题了&#xff0c;直接上题目。 题目&#xff1a;接雨水 42. 接雨水 - 力扣&#xff08;LeetCode&#xff09; 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1…

yagmail邮件发送库:如何用Python实现自动化邮件营销?

&#x1f3a5; 作者简介&#xff1a; CSDN\阿里云\腾讯云\华为云开发社区优质创作者&#xff0c;专注分享大数据、Python、数据库、人工智能等领域的优质内容 &#x1f338;个人主页&#xff1a; 长风清留杨的博客 &#x1f343;形式准则&#xff1a; 无论成就大小&#xff0c;…

【RL Base】强化学习:信赖域策略优化(TRPO)算法

&#x1f4e2;本篇文章是博主强化学习&#xff08;RL&#xff09;领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对相关等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅…

黑马2024AI+JavaWeb开发入门Day04-SpringBootWeb入门-HTTP协议-分层解耦-IOCDI飞书作业

视频地址&#xff1a;哔哩哔哩 讲义作业飞书地址&#xff1a;day04作业&#xff08;IOC&DI&#xff09; 作业很简单&#xff0c;主要是练习拆分为三层架构controller、service、dao&#xff0c;并基于IOC & DI进行解耦。 1、结构&#xff1a; 2、代码 网盘链接&…

(长期更新)《零基础入门 ArcGIS(ArcMap) 》实验三----学校选址与路径规划(超超超详细!!!)

目录 实验三 学校选址与道路规划 3.1 实验内容及目的 3.1.1 实验内容 3.1.2 实验目的 3.2 实验方案 3.3 操作流程 3.3.1 环境设置 3.3.2 地势分析 &#xff08;1&#xff09;提取坡度: (2)重分类: 3.3.3 学校点分析 (1)欧氏距离: (2)重分类: 3.3.4 娱乐场所点分析 (1)欧氏距离…

【Python网络爬虫笔记】8- (BeautifulSoup)抓取电影天堂2024年最新电影,并保存所有电影名称和链接

目录 一. BeautifulSoup的作用二. 核心方法介绍2.1 构造函数2.2 find()方法2.3 find_all()方法2.4 select()方法 三. 网络爬虫中使用BeautifulSoup四、案例爬取结果 一. BeautifulSoup的作用 解析HTML/XML文档&#xff1a;它可以将复杂的HTML或XML文本转换为易于操作的树形结构…

MATLAB期末复习笔记(中)

目录 三、MATLAB函数和程序结构 1.MATLAB文件 2.变量和数据类型 &#xff08;1&#xff09;变量 &#xff08;2&#xff09;变量类型 &#xff08;3&#xff09;字符串 3.函数文件 &#xff08;1&#xff09;函数文件规范 &#xff08;2&#xff09;子函数和私有函数 &…

算法刷题Day8:BM30 二叉搜索树与双向链表

题目 牛客网题目传送门 思路 对二叉搜索树进行中序遍历&#xff0c;结果就是按序数组。因此想办法把前面遍历过的节点给记下来&#xff0c;记作pre。当遍历到某个节点node的时候&#xff0c;令前驱指向pre&#xff0c;然后让pre的后驱指向node。 代码 class TreeNode:def…

深入解析 Dubbo 中的常见问题及优化方案: 数据量限制与配置错误20241203

&#x1f31f; 深入解析 Dubbo 中的常见问题及优化方案&#xff1a;数据量限制与配置错误 在分布式系统中&#xff0c;Dubbo 作为高性能的 RPC 框架广泛应用于企业服务化架构。然而&#xff0c;在实际使用过程中&#xff0c;开发者往往会遇到一些复杂问题&#xff0c;比如 数据…

debian ubuntu armbian部署asp.net core 项目 开机自启动

我本地的环境是 rk3399机器&#xff0c;安装armbian系统。 1.安装.net core 组件 sudo apt-get update && \sudo apt-get install -y dotnet-sdk-8.0或者安装运行库&#xff0c;但无法生成编译项目 sudo apt-get update && \sudo apt-get install -y aspnet…

【AI系统】Ascend C 编程范式

Ascend C 编程范式 AI 的发展日新月异&#xff0c;AI 系统相关软件的更新迭代也是应接不暇&#xff0c;作为一本讲授理论的作品&#xff0c;我们将尽可能地讨论编程范式背后的原理和思考&#xff0c;而少体现代码实现&#xff0c;以期让读者理解 Ascend C 为何这样设计&#x…

hadoop环境配置-创建hadoop用户+更新apt+安装SSH+配置Java环境

一、创建hadoop用户(在vm安装的ubantu上打开控制台) 1、sudo useradd -m hadoop -s /bin/bash &#xff08;创建hadoop用户&#xff09; 2、sudo passwd hadoop (设置密码) 3、sudo adduser hadoop sudo&#xff08;将新建的hadoop用户设置为管理员&#xff09; 执行如下图 将…

嵌入式系统应用-LVGL的应用-平衡球游戏 part1

平衡球游戏 part1 1 平衡球游戏的界面设计2 界面设计2.1 背景设计2.2 球的设计2.3 移动球的坐标2.4 用鼠标移动这个球2.5 增加边框规则2.6 效果图 3 为小球增加增加动画效果3.1 增加移动效果代码3.2 具体效果图片 平衡球游戏 part2 第二部分文章在这里 1 平衡球游戏的界面设计…

从被动响应到主动帮助,ProActive Agent开启人机交互新篇章

在人工智能领域&#xff0c;我们正见证着一场革命性的变革。传统的AI助手&#xff0c;如ChatGPT&#xff0c;需要明确的指令才能执行任务。但现在&#xff0c;清华大学联合面壁智能等团队提出了一种全新的主动式Agent交互范式——ProActive Agent&#xff0c;它能够主动观察环境…

2.mysql 中一条更新语句的执行流程是怎样的呢?

前面我们系统了解了一个查询语句的执行流程&#xff0c;并介绍了执行过程中涉及的处理模块。 相信你还记得&#xff0c;一条查询语句的执行过程一般是经过连接器、分析器、优化器、执行器等功能模块&#xff0c;最后到达存储引擎。 那么&#xff0c;一条更新语句的执行流程又…

NaviveUI框架的使用 ——安装与引入(图标安装与引入)

文章目录 概述安装直接引入引入图标样式库 概述 &#x1f349;Naive UI 是一个轻量、现代化且易于使用的 Vue 3 UI 组件库&#xff0c;它提供了一组简洁、易用且功能强大的组件&#xff0c;旨在为开发者提供更高效的开发体验&#xff0c;特别是对于构建现代化的 web 应用程序。…

web vue 滑动选择 n宫格选中 九宫格选中

页面动态布局经常性要交给客户来操作&#xff0c;他们按时他们的习惯在同一个屏幕内显示若干个子视图&#xff0c;尤其是在医学影像领域对于影像的同屏显示目视对比显的更为重要。 来看看如下的用户体验&#xff1a; 设计为最多支持5行6列页面展示后&#xff0c;右侧的布局则动…

ELK的Filebeat

目录 传送门前言一、概念1. 主要功能2. 架构3. 使用场景4. 模块5. 监控与管理 二、下载地址三、Linux下7.6.2版本安装filebeat.yml配置文件参考&#xff08;不要直接拷贝用&#xff09;多行匹配配置过滤配置最终配置&#xff08;一、多行匹配、直接读取日志文件、EFK方案&#…