从零实现 SPI_flash(W25Q256)
前言:
SPI是全双工,即同一时刻可以双向通讯。
SPI是英语serial peripheral interface 的缩写,顾名思义就是穿行外围设备接口。是motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。SPI是一种高速的,全双工,同步的通信总线。并且在芯片的管脚上只占用4根线。
SPI的主要特点:可以同时发送和接收串行数据;可以当作主机或者从机工作;提供频率可编程时钟;发送结束中断标志;写冲突保护;总线竞争保护等。
W25Q256(256Mb)将32M(字节byte)的容量分为512个块(block),每个块大小为64K字节,每个块又分为16个扇区(sector),每个扇区4K字节。最小擦除单位为一个扇区,也就是4K字节。
W25Q256的擦写周期多达10W次,具有20年的数据保存期限。这就是我用的norflash,我当前用2M字节,因为用norflash的目的是IAP远程升级代码用,而flash只有1MB,2MB的norflash也绰绰有余了。
后面做到STM32H750时还会发现,SPI_FLASH是可以用作分散加载的。还有QSPI通讯方式
在原子哥的讲解中关于CPHA=0和CPHA=1时的时序图弄反了,查了STM32F29的中文手册SPI部分,是这样的。对比一下即可知。
配置cubemx
cubemx:模式选择全速双向主机(双工主机嘛)。NSS是一个关于CS的管脚,若为从机则NSS就用作CS,若为主机则可以当作控制线控制从机的CS,他会在通信前拉低通信后拉高,但是我们这里采用软件控制,所以并不需要他的NSS功能。
原子的代码解释的非常清晰,参照下图可以配置SPI5
CS用PF6,设置为推挽输出,默认上拉
硬件配置完毕,生成代码后,还需要对W25Q256特殊初始化一下。需要注意和原子不同,我将SPI5的初始化蔽掉了,因为cubemx上已经设置好了,代码生成已包含。此外这个时候对SPI5的速度进行设置我不太理解,前面SPI配置为256分频,后面又改为2。那直接配置为2不就好了么。 其实若刚上来就用高时钟来配置SPI_FLASH是容易出错的,不如先用低时钟先配置好,使用前在配置为高时钟。
//4Kbytes为一个Sector
//16个扇区为1个Block
//W25Q256
//容量为32M字节,共有512个Block,8192个Sector
//初始化SPI FLASH的IO口
void W25QXX_Init(void)
{ uint8_t temp;W25QXX_CS(1); //SPI FLASH不选中
// SPI5_Init(); //初始化SPI
// SPI5_SetSpeed(SPI_BAUDRATEPRESCALER_2); //设置为45M时钟,高速模式W25QXX_TYPE=W25QXX_ReadID(); //读取FLASH ID.if(W25QXX_TYPE==W25Q256) //SPI FLASH为W25Q256{temp=W25QXX_ReadSR(3); //读取状态寄存器3,判断地址模式if((temp&0X01)==0) //如果不是4字节地址模式,则进入4字节地址模式{W25QXX_CS(0); //选中SPI5_ReadWriteByte(W25X_Enable4ByteAddr);//发送进入4字节地址模式指令 W25QXX_CS(1); //取消片选 }}
}
接下来编写测试代码,先在while(1)前读一下W25Q256的ID号,若能读出代表通信没问题。若读回不正确则闪烁LED1。
接下来再通过KEY0,KEY1分别写入一段字符串,读出同样地址的字符串。在LCD上显示看是否一致,以此检查是否正常。
//main.c
main()
{MX_SPI5_Init();W25QXX_Init();//检查W25QXX是否读回ID号是否正确if(W25QXX_ReadID()!=W25Q256)LED_Twinkle(1);while(1){if(_u8KeyStatus[KEY0]){W25QXX_Write((uint8_t*)TEXT_Buffer,FLASH_SIZE-100,sizeof(TEXT_Buffer)); //从倒数第100个地址处开始,写入SIZE长度的数据memcpy(InLtdcBuff1, TEXT_Buffer, sizeof(TEXT_Buffer)); //提示传送完成}if(_u8KeyStatus[KEY1]){W25QXX_Read(datatemp,FLASH_SIZE-100,sizeof(TEXT_Buffer)); //从倒数第100个地址处开始,读出SIZE个字节memcpy(InLtdcBuff2, datatemp, sizeof(TEXT_Buffer));}}
}
实验效果:
第一行“hello world”是我写入的,第二行“hello world”是我读出
最后:
想聊一聊原子哥写的
uint8_t W25QXX_BUFFER[4096];
void W25QXX_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
在这个函数中实现的功能是从pBuffer地址向地址WriteAddr写入NumByteToWrite长度的字节。
因为最小擦除单位是一个扇区,4K字节嘛,所以在写入的时候需要检查下要写入的部分是否有不为0XFF,否则就得先擦再写。所有可能要写入的字节数和目标地址跨扇区,那么假设要从扇区1的一半写到扇区3的一半,怎么办呢。
1.先把扇区1的前一半读出来,擦除扇区1,然后将要写入的剩下一半扇区的长度的数据连同扇区之前保存的前一半一并写入。扇区1的写入完成。
2.判断扇区2也有数据,因为我要写满一个扇区,所以我先把扇区2清空,再接着写入一个扇区长度的数据。扇区2的写入完成。
3.扇区3我要写前一半,那么就也判断下,若需要擦除,那我得把扇区3的后半部分读出来,擦除扇区3,再一并写入到扇区3。扇区3完成。
整个过程有一种似曾相识感觉,这跟我之前IAP的过程极为相似,单片机的flash最小擦除单位也为一个扇区。nandflash也很相似,他也是最小擦除单位为扇区,你说巧不巧。
所以技术是有相通的部分,今后在学习时,不仅要掌握用法,也要从思想上去理解,这样做的好处在哪。这种思维还能用在哪些地方会有更好的效果。
从零实现 SPI_flash(W25Q256)相关推荐
- 从零实现 Cortex-M7从驱动到应用(一)分散加载+SDRAM+SPI_FLASH
接下来我将与大家分享H750的开发,最终实现emwin的运行. 搭建环境 cubemx 由于cubemx老版本不支持H750,所以只能用新版本,注意:老版本支持工程路径为中文,新版本不支持! 需要H7 ...
- 从零实现 USB_SLAVE读卡器 USB_MSC+FATFS+SD/SPI_FLASH/NANDFLASH
欢迎大家留言交流~ 要实现USB读卡器,其核心就是F429作为从设备用USB_MSC与主机通讯,利用FATFS从SD卡.SPI_FLASH.NANDFLASH中读写数据. 什么是OTG?OTG是On- ...
- STM32CubeMX+FATFS+FREERTOS实现W25Q256虚拟U盘
一.软件硬件说明 软件:STM32CubeMX V6.6.1 /KEIL5 V5.29 硬件:正点原子阿波罗开发板,核心板STM32F429IGT6(176脚) 使用USB_SLAVE接口连接电脑US ...
- STM32CbueMX之SPI_FLASH + FATFS + USB MSC + 虚拟扩容
前言: 做一个在spi flash 上挂一个文件系统,然后板子用USB线连接电脑能识别读出spi flash上的文件. 背景: 因为spi flash容量比较小,我使用的是32MB的,插上电脑,感觉不 ...
- 3.1、CUBEMX使用FATFS读写SPI_FLASH
所需工具 CUBEMX5.6 STM32F103ZET6开发板(正点原子战舰) LINK及其他线束 1.CUBEMX设置 设置RCC 切记选择第三个,否则串口无法使用. 设置串口 设置SPI_FLAS ...
- W25Q256被写保护如何修改
W25Q256被写保护如何修改 1. W25Q256数据读不到 1.1 打印的寄存器的值 1.2 可能原因 1.3 解决办法 1.4 用到的函数 1. W25Q256数据读不到 能够正确的读到ID,但 ...
- nxp kea128 spi_flash驱动开发
一.编程要点 1. 3字节地址模式和4字节地址模式 W25Q256的容量有256M-bits,上图可见它的终止地址是1FFFFFFh,每个地址存一个字节.256Mbits/8 = 32MB.32MB ...
- 零基础入门--中文命名实体识别(BiLSTM+CRF模型,含代码)
https://github.com/mali19064/LSTM-CRF-pytorch-faster 中文分词 说到命名实体抽取,先要了解一下基于字标注的中文分词. 比如一句话 "我爱北 ...
- LeetCode简单题之复写零
题目 给你一个长度固定的整数数组 arr,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移. 注意:请不要在超过该数组长度的位置写入元素. 要求:请对输入的数组 就地 进行上述修改,不要从 ...
- LeetCode简单题之柠檬水找零
题目 在柠檬水摊上,每一杯柠檬水的售价为 5 美元.顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯. 每位顾客只买一杯柠檬水,然后向你付 5 美元.10 美元或 20 美元.你必 ...
最新文章
- SVN 问题解决之 The XML response contains invalid XML
- tcpdump for Android 移动端抓包
- 龙格库塔法解微分方程组的matlab程序,MATLAB实例源码教程:龙格库塔法求解微分方程组源代码实例.doc...
- MySQL(三)——函数、事务(ACID)、索引、权限管理和备份、数据库三大范式
- 教程-delphi的开源json库:superobject,用法简介
- 简单谈谈MySQL优化利器-慢查询
- 医院耗材管理系统开发_2
- CISCO技术(1.7万)
- java openxml word_【转】【OpenXml】OpenXml操作Word的一些操作总结
- React的调和过程(Reconcilliation)
- 考勤日历插件 android,jQuery手机考勤日历插件
- 锁存器—74HC573D
- 游戏中常见的Bug也有你不知道的秘密
- 听《正面管教》,论如何教育孩子
- ideaIU-2020.1下载
- Nginx实现网站发布
- 关于HP WebInspect 9.1
- 从PS视频流中提取H264数据
- Foxtable编程
- 联想 Linux下 装win10 双系统(免坑)
热门文章
- 韩顺平 php大牛班课程,2016 泰牛程序员 韩顺平 PHP 大牛班 javascript课程 完整笔记.doc...
- 两天撸一个天气应用微信小程序
- 官方版WIN10PE如何添加explorer?
- 【系统安装】MediaCreationTool工具制作U盘安装win10系统
- 【Python】Tkinter教程
- 跟着团子学SAP—SAP LTMC基础教程(物料主数据导入示例)
- hrm系统源码php,悟空HRM下载_悟空HRM0.1开源版 - 系统之家
- Windows电脑上最好的3个txt阅读器
- java pcm to wav_Java音频转换:PCM格式转WAV格式
- LabelImg安装