spiFLASH芯片WQ的单片机驱动代码

合集下载

spiflash操作

spiflash操作

spiflash操作W25Q16V 是华邦出的一颗 spi flash. 25系列是比较通用的一个系列. 后面的数字 16 跟容量有关, 16 表示 16Mbits, 相当于 2MB.与此类似的还有 W25Q128V 等, 128 就表示容量 16MB.对于 W25Q16V:•page 为最大的编程单位. 1 page = 256 bytes•sector 为最小的擦除单位, 1sector = 16 pages = 4096 bytes (4KB)•块擦除有两种大小:•32K block = 8 secotrs = 128 pages = 32 kbytes•64k block = 16 sectors = 256 pages = 64 kbytes封装如图的 8-pin 是较常用的一种封装. 各 pin 的意义:1.CS , chip select, 芯片使能引脚. CS拉高时, 芯片处理省电模式, 各数据引脚(D0/D1/D2/D3)处理高阻态. CS拉低时芯片工作, 数据引脚可以传输数据.2.DO 用于(在CLK下降沿)输出数据或状态. 正常情况下只有DI/DO作为IO引脚, 启用Quad 模式需要置QE(Quad Enable)位. QE=1时, WP和HOLD分别变为IO2,IO3.3.WP pin, 低电平有效, 以保护状态寄存器不被写入.4.GND 接地5.DI用于(在CLK上升沿)向 Flash 输入指令, 地址或数据.6.CLK, 提供输入输出操作的同步时钟.7.HOLD pin, 当多个芯片共用 SPI 总线时非常有用. HOLD 为低电平时, DO 引脚变为高阻态, 且此时 DI/CLK 上的信号被忽略. 相当于芯片此时不工作. 假设对一个 SPI FLASH 的页写操作只进行到一半, 此时一个中断来了, 另一个更高优先级的任务要占用SPI 总线, 此时就可以使用 HOLD 拉低来暂停 SPI FLASH 内部的工作, 等到任务切换回来再让操作继续下去.8.VCC, 2.7 ~ 3.6V内部模块框图SPI 操作标准 SPI 有四根信号线: CS, CLK, DI, DO. 其中 DI 用于在CLK上升沿时输入指令, 地址或数据, DO用于在CLK下降沿时读数据或状态.SPI 总线有四种工作模式, 区别是 CLK 常态电平和数据采样时机. W25Q16V 支持 MODE0 和 MODE3. 详见这篇笔记使用3B/BB指令可以进入"快速双路模式", 此时DI/DO变为IO0, IO1.6B, EB 进入"四路"模式, 此时 WP, HOLD 分别变为 IO2, IO3状态寄存器BUSY, 只读位,当 SPI FLASH 在执行页编程, 扇区擦除, 块擦除, 整片擦除, 写状态寄存器指令等操作时, BUSY位被置1, 这些操作完成之后, BUSY位自动清0. 当BUSY位为1时, 除了"读状态寄存器"操作和"擦除暂停"操作之外, 不接受任何其他操作.WEL, Write Enable Latch只读位. 当执行了一个"写使能"指令后, WEL置1, 表示可以写入了. "写禁止"时, WEL为0."写禁止", "页编程", "扇区擦除", "块擦除", "整片擦除", "写状态寄存器", 执行完这些操作之后, WEL 自动被清0, 回到禁止写入状态.BP0, BP2, BP2 (Block Protect Bits) 块保护"写状态寄存器" 指令可以改变这些位的值.TBSECSRP1, SRP0, 状态寄存器保护这两个位与 WP 引脚一起, 用于保护状态寄存器不被改写.QE指令有 26 个基本指令. DI 输入的第一个字节就是指令代码. DI在CLK 上升沿采样, MSB .指令有一个或多个字节, 可能后面还有地址, 数据, dummy.。

SPI接口的FLASH

SPI接口的FLASH

SPI接⼝的FLASHSPI flash W25Qxx:W25Q系列的spiflash。

每页(Page)256B,每16个page为⼀个sector(扇区=4KB),每16个扇区为⼀个block(块=64KB)W25Q16=16Mb=2MB=2048KB=32block=512sector=8192page;操作:SPI flash写操作必须确保为0XFF才能写⼊,否则需要檫除操作,檫除的最⼩单位为Sector即4KB,所以有的会在单⽚机内部开⼀个4K的缓存(有点奢侈),写之前先读出来,檫除数据,合并数据(在檫除数据的同时进⾏操作,合并完了在检查檫除是否完成,不闲着;操作系统级的将因此进⼊挂起。

要么设定⼀个合适的超时时间,要么有⼀个专门的轮训这些标志完成则发信号量),再写⼊。

SPI SPI flash驱动规范:1 硬件SPI/软件SPI涉及的MOSI/MISO/SCK的IO设置、SPI设置读写⼀个字节。

2 存储器件IC涉及的⽚选、调⽤SPI读写⼀个字节操作在某个指定地址读写⼀个字节/多个字节,檫除等操作。

3业务层次的读写记录,APP升级等。

⼀主多从可以通过不同⽚选来发送(都⽚选则都会收到),但对接收,如果关闭某个⽚选则可能得不到及时相应;如果都打开则同时来时的处理。

IO模拟SPI⼀主多从如右图,先操作译码器(速度要快)再操作SPI的其它三根⼝线即可。

GPIO模拟的SPI操作灵活,但效率不⾼。

同时这种⽅法不适⽤于SPI的DMA传输,仅适合数据量少、对传输速度要求不同的场合。

硬件SPI的⽚选可以软件控制也能硬件控制(DMA传输时必须)关于IO模拟SPI驱动的另⼀种编程⽅法:SCLK⽤PWM输出⽅波(脉宽周期按⼿册),其它的4线配置SCLK进⾏操作,通过读SCLK引脚GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)来配合时序,不满⾜就等,满⾜就进⾏其它IO的置⾼置低(配置SYSTICK或NOP进⾏延时)关于如何根据时序图⽤IO模拟写驱动/上升沿采样下降沿发送数据的含义,以TM7705为例:上图表⽰对主机MCU⽽⾔:写的时候:MOSI上上升沿采样,上升沿前低电平时就要发送bit数据即:SCLK=0延时⼀⼩段时间就将send_data的MSB发出,然后SCLK=1再延时⼀段时间,接着进⾏下⼀个bit的操作。

spi flash的写操作流程

spi flash的写操作流程

spi flash的写操作流程下载温馨提示:该文档是我店铺精心编制而成,希望大家下载以后,能够帮助大家解决实际的问题。

文档下载后可定制随意修改,请根据实际需要进行相应的调整和使用,谢谢!并且,本店铺为大家提供各种各样类型的实用资料,如教育随笔、日记赏析、句子摘抄、古诗大全、经典美文、话题作文、工作总结、词语解析、文案摘录、其他资料等等,如想了解不同资料格式和写法,敬请关注!Download tips: This document is carefully compiled by theeditor. I hope that after you download them,they can help yousolve practical problems. The document can be customized andmodified after downloading,please adjust and use it according toactual needs, thank you!In addition, our shop provides you with various types ofpractical materials,such as educational essays, diaryappreciation,sentence excerpts,ancient poems,classic articles,topic composition,work summary,word parsing,copy excerpts,other materials and so on,want to know different data formats andwriting methods,please pay attention!《SPI Flash 的写操作流程》一、准备工作1. 确定 SPI Flash 的型号和规格,了解其支持的指令和操作方式。

25X系列SPI FLASH芯片编程操作

25X系列SPI FLASH芯片编程操作

一、 恒通2009智通型编程器2008年BIOS之家全新打造恒通2009智通型编程器恒通2009智通型编程器是。

采用双核mcu处理方式,已经更换为2毫米厚度PCB,双层设计,PCB背面带有绝缘背板保护,并采用环形磁环电感和高速齐纳二极管改进供电模块,新版烧写更加稳定可靠。

最新软件发布0.98D9,全面支持8脚 SPI flash BIOS 芯片支持芯片超过1500种,包括EPROM , EEPROM , FLASH , PIC , AVR , MCS-51 , MCS-48, 27Cxx , 28Cxx 28Fxx , 29Fxx , AT29Cxxx , 24Cxx , 93Cxx , PIC16xxx , DS12xx , AT89Cxx , AT89Cx051 , AT25xxx , AT90Sxxx , EPROM16bit , 29Fx00 , 28Fx00。

适用于升级维修电脑主板BIOS、手机、VCD、DVD、彩电、复印机,传真机,打印机等;可修改VCD/DVD/彩电开机画面;可用于汽车存储器代码读写;可用于开发MCS-51系列,AVR 系列,PIC系列单片机。

内置PLCC32和HUB/LPC适配器(支持29/39/49LVxxx,低电压3.3V),支持高速编程,编程速度比PCB3,PCB3B+ 提高50%,比PCB3.5,PCB4C 提高20%。

能够解锁AM29F040B。

并能通过板上跳线切换PCB3B<->PCB4.5C,从而能兼容所有老版本软件。

2.工作环境* 本编程器与PC机并口进行通讯,通过配套软件对各种芯片进行读写等操作* 5M硬盘空间* Win9X、WinNT、Win2000、WinXP操作系统二、硬件结构及安装方法一、硬件安装注意:计算机的并口要在BIOS中设置为ECP或ECP+EPP。

若不能联机,请每种设置下都试试!恒通2009的硬件分布图:各接口功能综述:1、编程电压调整跳线,用来设置27系列芯片的编程电压。

stm32W25Q64

stm32W25Q64

.C文件#include "flash.h"#include "spi.h"#include "delay.h"////////////////////////////////////////////////////////////////////////////////////本程序只供学习使用,未经作者许可,不得用于其它任何用途//ALIENTEK战舰STM32开发板//W25Q64 代码//正点原子ALIENTEK//技术论坛:.openedv.//修改日期:2012/9/9//版本:V1.0//所有,盗版必究。

//Copyright(C) 市星翼电子科技2009-2019//All rights reserved//flash写入只能把1写成0,所以写入前应该先擦除//////////////////////////////////////////////////////////////////////////////////u16 SPI_FLASH_TYPE = W25Q64;//默认就是25Q64//W25Q64一共8M容量//分为128个快,每块大小为64K字节//每块又可以分为16个扇区,每个扇区4K字节//每次擦除最少一个扇区,也就是4K字节//25Q64 一共有2048个扇区//初始化SPI FLASH的IO口void SPI_Flash_Init(void){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOG, ENABLE );//PORTB时钟使能//W25Q64的片选GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; // PB12 推挽GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB,GPIO_Pin_12);//SD卡片选信号GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // PD2 推挽GPIO_Init(GPIOD, &GPIO_InitStructure);GPIO_SetBits(GPIOD,GPIO_Pin_2);//2.4G无线片选信号GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; // PG7 推挽GPIO_Init(GPIOG, &GPIO_InitStructure);GPIO_SetBits(GPIOG,GPIO_Pin_7);SPI2_Init(); //初始化SPISPI2_SetSpeed(SPI_BaudRatePrescaler_2);//设置为18M时钟,高速模式SPI_FLASH_TYPE = SPI_Flash_ReadID();//读取FLASH ID.}//读取SPI_FLASH的状态寄存器//BIT7 6 5 4 3 2 1 0//SPR RV TB BP2 BP1 BP0 WEL BUSY//SPR:默认0,状态寄存器保护位,配合WP使用//TB,BP2,BP1,BP0:FLASH区域写保护设置//WEL:写使能锁定//BUSY:忙标记位(1,忙;0,空闲)//默认:0x00u8 SPI_Flash_ReadSR(void){u8 byte=0;SPI_FLASH_CS=0; //使能器件SPI2_ReadWriteByte(W25X_ReadStatusReg); //发送读取状态寄存器命令byte=SPI2_ReadWriteByte(0Xff); //读取一个字节SPI_FLASH_CS=1; //取消片选return byte;}//写SPI_FLASH状态寄存器//只有SPR,TB,BP2,BP1,BP0(bit 7,5,4,3,2)可以写!!!void SPI_FLASH_Write_SR(u8 sr){SPI_FLASH_CS=0; //使能器件SPI2_ReadWriteByte(W25X_WriteStatusReg); //发送写取状态寄存器命令SPI2_ReadWriteByte(sr); //写入一个字节SPI_FLASH_CS=1; //取消片选}//SPI_FLASH写使能//将WEL置位void SPI_FLASH_Write_Enable(void){SPI_FLASH_CS=0; //使能器件SPI2_ReadWriteByte(W25X_WriteEnable); //发送写使能SPI_FLASH_CS=1; //取消片选}//SPI_FLASH写禁止//将WEL清零void SPI_FLASH_Write_Disable(void){SPI_FLASH_CS=0; //使能器件SPI2_ReadWriteByte(W25X_WriteDisable); //发送写禁止指令SPI_FLASH_CS=1; //取消片选}//读取芯片ID W25X16的ID:0XEF14u16 SPI_Flash_ReadID(void){u16 Temp = 0;SPI_FLASH_CS=0;SPI2_ReadWriteByte(0x90);//发送读取ID命令SPI2_ReadWriteByte(0x00);SPI2_ReadWriteByte(0x00);SPI2_ReadWriteByte(0x00);Temp|=SPI2_ReadWriteByte(0xFF)<<8;Temp|=SPI2_ReadWriteByte(0xFF);SPI_FLASH_CS = 1;return Temp;}//读取SPI FLASH//在指定地址开始读取指定长度的数据//pBuffer:数据存储区//ReadAddr:开始读取的地址(24bit)//NumByteToRead:要读取的字节数(最大65535)//2^10=1024 1K=1024字节//8M最大能读到2^23 也就是24位void SPI_Flash_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead) {u16 i;SPI_FLASH_CS=0; //使能器件SPI2_ReadWriteByte(W25X_ReadData); //发送读取命令SPI2_ReadWriteByte((u8)((ReadAddr)>>16)); //发送24bit地址SPI2_ReadWriteByte((u8)((ReadAddr)>>8));SPI2_ReadWriteByte((u8)ReadAddr);for(i=0;i<NumByteToRead;i++){pBuffer[i]=SPI2_ReadWriteByte(0XFF); //循环读数}SPI_FLASH_CS=1; //取消片选}//SPI在一页(0~65535)写入少于256个字节的数据//在指定地址开始写入最大256字节的数据//pBuffer:数据存储区//WriteAddr:开始写入的地址(24bit)//NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!! void SPI_Flash_Write_Page(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite){u16 i;SPI_FLASH_Write_Enable(); //SET WELSPI_FLASH_CS=0; //使能器件SPI2_ReadWriteByte(W25X_PageProgram); //发送写页命令SPI2_ReadWriteByte((u8)((WriteAddr)>>16)); //发送24bit地址SPI2_ReadWriteByte((u8)((WriteAddr)>>8));SPI2_ReadWriteByte((u8)WriteAddr);for(i=0;i<NumByteToWrite;i++)SPI2_ReadWriteByte(pBuffer[i]); //循环写数SPI_FLASH_CS=1; //取消片选SPI_Flash_Wait_Busy(); //等待写入结束}//无检验写SPI FLASH//必须确保所写的地址围的数据全部为0XFF,否则在非0XFF处写入的数据将失败! //具有自动换页功能//在指定地址开始写入指定长度的数据,但是要确保地址不越界!//pBuffer:数据存储区//WriteAddr:开始写入的地址(24bit)//NumByteToWrite:要写入的字节数(最大65535)//每页256个字节void SPI_Flash_Write_NoCheck(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite) {u16 YeSengYu;YeSengYu = 256-WriteAddr%256; //单页剩余的字节数if(NumByteToWrite <= YeSengYu)YeSengYu = NumByteToWrite; //不大于256个字节while(1){SPI_Flash_Write_Page(pBuffer,WriteAddr,YeSengYu);if(NumByteToWrite == YeSengYu)break;//写入结束了else // NumByteToWrite > YeSengYu{pBuffer += YeSengY u;WriteAddr += YeSengYu;NumByteToWrite -= YeSengYu; //减去已经写入了的字节数if(NumByteToWrite > 256)YeSengYu = 256; //一次可以写入256个字节elseYeSengYu = NumByteToWrite; //不够256个字节了}}}//写SPI FLASH//在指定地址开始写入指定长度的数据//该函数带擦除操作!//pBuffer:数据存储区//WriteAddr:开始写入的地址(24bit)//NumByteToWrite:要写入的字节数(最大65535)u8 SPI_FLASH_BUF[4096];void SPI_Flash_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite){u32 secpos;u16 secoff;u16 secremain;u16 i;secpos = WriteAddr / 4096; //扇区地址0~2047 for w25x64secoff = WriteAddr % 4096; //在扇区的偏移secremain = 4096 - secoff; //扇区剩余空间大小if(NumByteToWrite <= secremain)secremain = NumByteToWrite;//不大于4096个字节while(1){SPI_Flash_Read(SPI_FLASH_BUF,secpos*4096,4096);//读出整个扇区的容for(i=0;i<secremain;i++)//校验数据{if(SPI_FLASH_BUF[secoff+i] != 0XFF)break;//需要擦除}if(i<secremain)//需要擦除{SPI_Flash_Erase_Sector(secpos);//擦除这个扇区for(i=0;i<secremain;i++) //复制{SPI_FLASH_BUF[i+secoff] = pBuffer[i];}SPI_Flash_Write_NoCheck(SPI_FLASH_BUF,secpos*4096,4096);//写入整个扇区}elseSPI_Flash_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间.if(NumByteToWrite == secremain)break;//写入结束了else//写入未结束{secpos++; //扇区地址增1secoff=0; //偏移位置为0pBuffer += secremain; //指针偏移WriteAddr += secremain; //写地址偏移NumByteToWrite -= secremain;//字节数递减if(NumByteToWrite>4096)secremain = 4096; //下一个扇区还是写不完elsesecremain = NumByteToWrite; //下一个扇区可以写完了}}}//擦除整个芯片//整片擦除时间://W25X16:25s//W25X32:40s//W25X64:40s//等待时间超长...void SPI_Flash_Erase_Chip(void){SPI_FLASH_Write_Enable(); //SET WELSPI_Flash_Wait_Busy();SPI_FLASH_CS=0; //使能器件SPI2_ReadWriteByte(W25X_ChipErase); //发送片擦除命令SPI_FLASH_CS=1; //取消片选SPI_Flash_Wait_Busy(); //等待芯片擦除结束}//擦除一个扇区//Dst_Addr:扇区地址0~511 for w25x16//Dst_Addr:扇区地址0~2047 for w25x64//擦除一个山区的最少时间:150msvoid SPI_Flash_Erase_Sector(u32 Dst_Addr){Dst_Addr*=4096;SPI_FLASH_Write_Enable(); //SET WELSPI_Flash_Wait_Busy();SPI_FLASH_CS=0; //使能器件SPI2_ReadWriteByte(W25X_SectorErase); //发送扇区擦除指令SPI2_ReadWriteByte((u8)((Dst_Addr)>>16)); //发送24bit地址SPI2_ReadWriteByte((u8)((Dst_Addr)>>8));SPI2_ReadWriteByte((u8)Dst_Addr);SPI_FLASH_CS=1; //取消片选SPI_Flash_Wait_Busy(); //等待擦除完成}//等待空闲void SPI_Flash_Wait_Busy(void){while ((SPI_Flash_ReadSR()&0x01)==0x01); // 等待BUSY位清空}//进入掉电模式void SPI_Flash_PowerDown(void){SPI_FLASH_CS=0; //使能器件SPI2_ReadWriteByte(W25X_PowerDown); //发送掉电命令SPI_FLASH_CS=1; //取消片选delay_us(3); //等待TPD}//唤醒void SPI_Flash_WAKEUP(void){SPI_FLASH_CS=0; //使能器件SPI2_ReadWriteByte(W25X_ReleasePowerDown); // send W25X_PowerDown command 0xAB SPI_FLASH_CS=1; //取消片选delay_us(3); //等待TRES1}.H文件#ifndef __FLASH_H#define __FLASH_H#include "sys.h"////////////////////////////////////////////////////////////////////////////////////本程序只供学习使用,未经作者许可,不得用于其它任何用途//ALIENTEK战舰STM32开发板//W25Q64 代码//正点原子ALIENTEK//技术论坛:.openedv.//修改日期:2012/9/9//版本:V1.0//所有,盗版必究。

SPI Flash Quad读写流程

SPI Flash Quad读写流程

SPI Flash Quad读写流程
1. 系统提供SPI控制器和SPI Flash芯片连接(dual或quad SPI)
2. 安装Flash驱动程序
3. 初始化Flash及SPI控制器:检查Flash型号、SPI模式、CLK频率等参数是否正确设置,并进行控制寄存器初始化。

4. 读取Flash中的数据:通过SPI控制器发送读取命令,Flash 芯片返回数据,在SPI帧中打开Quad模式使Flash可以传输四个数据位。

将传输的数据缓存在一个寄存器中,直至读取完成。

5. 写入数据到Flash中:通过SPI控制器发送写入命令。

在SPI帧中打开Quad模式使Flash传输四个数据位。

向Flash 写入数据后,等待写入完成的确认信号。

6. 擦除Flash中的数据:通过SPI控制器发送擦除命令。

在SPI帧中打开Quad模式使Flash可以传输四个数据位,指定要擦除的扇区地址,等待擦除完成的确认信号。

7. 维护Flash状态寄存器:Flash芯片会将状态信息保存在状态寄存器中,包括写入、擦除、保护等信息,需要不定期地读取、判断。

8. 退出程序:完成以后进行相应的清理工作,例如释放资源、关闭SPI控制器等。

这些步骤形成了SPI Flash Quad读写的完整流程,其中需要确保正确的Flash和SPI控制器配对设置,以便读写数据和状
态信息。

单片机IO口模拟SPI四种模式的程序

单片机IO口模拟SPI四种模式的程序

单片机IO口模拟SPI四种模式的程序单片机IO口模拟SPI四种模式的程序#include "iom8535v.h"#define _CPOL 1#define _CPHA 0#define SCK_IO DDRA|=0X01#define MOSI_IO DDRA|=0X02#define MISO_IO DDRA&=0XFB#define SSEL_IO DDRA|=0X08#define SCK_D(X) (X?(PORTA|=0X01):(PORTA&=0XFE)) #define MOSI_D(X) (X?(PORTA|=0X02):(PORTA&=0XFD)) #define SSEL_D(X) (X?(PORTA|=0X08):(PORTA&=0XF7))#define MISO_I() (PINA&0X04)void delay(){unsigned char m,n;for(n=0;n<5;n++);for(m=0;m<100;m++);}/************************************************ 端口方向配置与输出初始化************************************************/ void SPI_Init(void){SCK_IO ;MOSI_IO ;MISO_IO ;SSEL_IO ;SSEL_D(1);MOSI_D(1);#if _CPOL==0SCK_D(0);#elseSCK_D(1);#endif}/**********************************************模式零写数据***********************************************/ #if _CPOL==0&&_CPHA==0 //MODE 0 0 void SPI_Send_Dat(unsigned char dat){unsigned char n;for(n=0;n<8;n++){SCK_D(0);if(dat&0x80)MOSI_D(1);else MOSI_D(0);dat<<=1;SCK_D(1);}SCK_D(0);}/********************************************* 模式零读数据*********************************************/ unsigned char SPI_Receiver_Dat(void){unsigned char n ,dat,bit_t;for(n=0;n<8;n++)SCK_D(0);dat<<=1;if(MISO_I())dat|=0x01;else dat&=0xfe;SCK_D(1);}SCK_D(0);return dat;}#endif/********************************************** 模式二写数据***********************************************/ #if _CPOL==1&&_CPHA==0 //MODE 1 0 void SPI_Send_Dat(unsigned char dat){unsigned char n;for(n=0;n<8;n++){SCK_D(1);if(dat&0x80)MOSI_D(1);else MOSI_D(0);dat<<=1;SCK_D(0);}SCK_D(1);}/********************************************* 模式二读数据*********************************************/ unsigned char SPI_Receiver_Dat(void)unsigned char n ,dat,bit_t;for(n=0;n<8;n++){SCK_D(1);dat<<=1;if(MISO_I())dat|=0x01;else dat&=0xfe;SCK_D(0);}SCK_D(1);return dat;}#endif/********************************************* 模式一写数据*********************************************/ #if _CPOL==0&&_CPHA==1 //MODE 0 1 void SPI_Send_Dat(unsigned char dat){unsigned char n;SCK_D(0);for(n=0;n<8;n++){SCK_D(1);if(dat&0x80)MOSI_D(1);else MOSI_D(0);dat<<=1;SCK_D(0);}}/********************************************* 模式一读数据*********************************************/ unsigned char SPI_Receiver_Dat(void){unsigned char n ,dat,bit_t;for(n=0;n<8;n++){SCK_D(1);dat<<=1;if(MISO_I())dat|=0x01;else dat&=0xfe;SCK_D(0);}SCK_D(0);return dat;}#endif//////////////////////////////////////////////////////////////////////////////////////////////////////////////#if _CPOL==1&&_CPHA==1 //MODE 1 1void SPI_Send_Dat(unsigned char dat){unsigned char n;SCK_D(1);for(n=0;n<8;n++){SCK_D(0);if(dat&0x80)MOSI_D(1);else MOSI_D(0);dat<<=1;SCK_D(1);}}/************************************模式三读数据************************************/unsigned char SPI_Receiver_Dat(void){unsigned char n ,dat,bit_t;SCK_D(0);for(n=0;n<8;n++){ SCK_D(0);dat<<=1;if(MISO_I())dat|=0x01;else dat&=0xfe;SCK_D(1);}SCK_D(1);return dat;}#endif/**************************************************************************/ void main() {SPI_Init();DDRB = 0XFF;//#if _CPOL//SCK_D(0);//#endifwhile(1){//SSEL_D(0);//SPI_Send_Dat(0x01);//SPI_Send_Dat(0x31);//SSEL_D(1);SSEL_D(0);SPI_Send_Dat(0x81); PORTB =SPI_Receiver_Dat(); SSEL_D(1);//delay();}}。

RT-Thread中使用SPI操作FLASH(W25Q128),并在W25Q128上挂载文件系统

RT-Thread中使用SPI操作FLASH(W25Q128),并在W25Q128上挂载文件系统
步骤三:根据 RTT官网文档对 SPI驱动进行修改,右击 SPI 图标 ->选择开发文档 -->驱动开发文档
SPI 设备驱动的开发可总结为如下: *** 新建 RT-Thread 完整版项目** *** 打开 SPI 设备驱动框架** *** 定义 SPI 总线相关的宏** *** 打开 HAL 库函数对 SPI 总线的支持** *** 复制 SPI 引脚初始化函数到工程**
在rtthread源码中 rt-thread/ bsp / stm32 / stm32f407-atk-explorer / board / CubeMX_Config / Src目录下有stm32f4xx_hal_msp.c 文件中有CubeMX针对SPI的初始化函数将其拷贝到drv_spi.c的文末。 编译,下载到板子。结果如图
步骤四:添加 SPI从设备,也就是 W25Q128设备
添加文件和代码
下载到开发板
步骤五:将 W25Q128抽象为块设备供 rtt使用,后续挂载文件系 统
步骤六:挂载文件系统
结果:
rtt的otaboot是基于面临的问题是tftp不知道怎么让它将下载的文
RT-Thread中使用 SPI操作 FLASH( W25Q128) ,并在 W25Q128上 挂载文件系统
开发板 正点原子的STM32F407探索者
IDE RT-Thread Studio
FLASH W25Q128
FATFS 参考RTThread官方文档
步骤一:创建基础工程
点 击 完 成 。 修 改 main.c中 对 应 LED0灯 的 引 脚
步骤二:点击 RT-Thread setting在图形界面配置需要的组件和驱 动
W25Q128是16M spi flash,一共有256个block ,每个Block 64KB。 一个Block可以分割为16个扇区(small sector),每个扇区4096字节(4KB),所以我们需要修改fatfs的扇区大小为4096
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

spiFLASH芯片WQ的单片机驱动代码
#include &quot;w25q80.h&quot;
// 注:W25Q80由256 BYTE 组成一个PAGE,不可PGAE擦除,可以进行BYTE PROGRAM 或者PAGE PROGRAM
// 由16 PAGE 组成一个SECTOR,可SECTOR擦除
// 由16 SECTOR组成一个BLOCK,可BLOCK 擦除
// 由16 BLOCK 组成一个FULL MEMEORY,可FULL MEMORY 擦除
// 所以,总容量是1M bytes
// W25Q80主要命令字
#define READ_ARRAY 0x03
#define SECTOR_ERASE 0x20
#define BYTE_OR_PAGE_PROGRAM 0x02
#define WRITE_ENABLE 0x06
#define WRITE_DISABLE 0x04
#define READ_STATUS_REGISTER 0x05
#define Manufacturer_DeviceID 0x9F
// 定义W25Q80的CS脚对应MCU的IO
#define W25Q80_CS P1_2
// SPI硬件初始化
void Spi_Init(void)
{
PERCFG |= 0x02; // SPI1映射到P1口
P1SEL |= 0xE0; // P15~P17作复用功能(clk mosi miso)
P1SEL &amp;= ~0x04; // P12作GPIO
P1DIR |= 0x04; // P12作输出
P1_2 = 1; // P12输出高电平
U1CSR &amp;= ~0xA0; // SPI主方式
U1GCR &amp;= ~0xC0; // CPOL=0 CPHA=0
U1GCR |= 0x20; // MSB
U1BAUD = 0; // 波特率设为sysclk/8
U1GCR |= 0x11;
// SPI发送与接收字节
static u8 Spi_ReadWriteByte(u8 TxData)
{
U1DBUF = TxData; // 发送数据
while( !(U1CSR&amp;0x02) ); // 等待发送完成
U1CSR &amp;= 0xFD; // 清除发送完成标志
return U1DBUF;
}
// CS线拉低,使能芯片
static void W25Q80_Enable( void )
{
volatile u8 i;
W25Q80_CS = 0;
for ( i=5; i&gt;0; i-- ); // 延时
}
// CS线拉高,禁能芯片
#define W25Q80_Disable() ( W25Q80_CS = 1 )
// 设置FLASH芯片&quot;写使能&quot;
static void SetW25Q80WriteEnable(void)
{
W25Q80_Enable();
Spi_ReadWriteByte(WRITE_ENABLE);
W25Q80_Disable();
}
// 设置FLASH芯片&quot;写禁能&quot;
//static void ClearW25Q80WriteEnable(void)
//{
// W25Q80_Enable();
// Spi_ReadWriteByte(WRITE_DISABLE);
// W25Q80_Disable();
//}
// 读取FLASH芯片的状态字节,可判断芯片是否busy
static u8 ReadW25Q80StatusRegister(void)
{
u8 temp;
W25Q80_Enable();
Spi_ReadWriteByte(READ_STATUS_REGISTER);
temp = Spi_ReadWriteByte(0xF0);
W25Q80_Disable();
return temp;
}
// 读取FLASH的内容,读取的字节数没有限制
void ReadW25Q80Operation(u32 addr,u8 *databuf,u32 len)
{
u32 i = 0;
u8 temp;
temp = ReadW25Q80StatusRegister();
while( temp&amp;0x01 ) // 等待FLASH芯片结束BUSY状态{
temp = ReadW25Q80StatusRegister();
if ( ++i&gt;1000000 ) return;
}
W25Q80_Enable();
Spi_ReadWriteByte(READ_ARRAY);
Spi_ReadWriteByte((u8)(addr &gt;&gt;16));
Spi_ReadWriteByte((u8)(addr &gt;&gt;8));
Spi_ReadWriteByte((u8)addr);
for ( i=0; i&lt;len; i++ )
{
databuf[i] = Spi_ReadWriteByte(0xF0);
}
W25Q80_Disable();
}
// 写入FLASH,一次最多写256字节,注意不要越界(不要超过页边界)
void WriteW25Q80Operation(u32 addr,u8 *databuf,u16 len)
{
u32 i = 0;
u8 temp;
temp = ReadW25Q80StatusRegister();
while( temp&amp;0x01 ) // 等待FLASH芯片结束BUSY状态{
temp = ReadW25Q80StatusRegister();
if ( ++i&gt;1000000 ) return;
}
SetW25Q80WriteEnable(); // 设置芯片写使能
W25Q80_Enable();
Spi_ReadWriteByte(BYTE_OR_PAGE_PROGRAM);
Spi_ReadWriteByte((u8)(addr &gt;&gt;16));
Spi_ReadWriteByte((u8)(addr &gt;&gt;8));
Spi_ReadWriteByte((u8)addr);
for ( i=0; i&lt;len; i++ )
{
Spi_ReadWriteByte(databuf[i]);
}
W25Q80_Disable();
}
// 对FLASH进行SECTOR擦除
void EraseW25Q80Operation(u32 addr)
{
u32 i = 0;
u8 temp;
temp = ReadW25Q80StatusRegister();
while( temp&amp;0x01 ) // 等待FLASH芯片结束BUSY状态{
temp = ReadW25Q80StatusRegister();
if ( ++i&gt;1000000 ) return;
}
SetW25Q80WriteEnable(); // 设置芯片写使能
W25Q80_Enable();
Spi_ReadWriteByte(SECTOR_ERASE);
Spi_ReadWriteByte((u8)(addr &gt;&gt;16));
Spi_ReadWriteByte((u8)(addr &gt;&gt;8));
Spi_ReadWriteByte((u8)addr);
W25Q80_Disable();
}
// 读取FLASH芯片的JEDEC ID信息
void ReadW25Q80DeviceID(u8 *buf)
{
W25Q80_Enable();
Spi_ReadWriteByte(Manufacturer_DeviceID);
buf[0] = Spi_ReadWriteByte(0xF0);
buf[1] = Spi_ReadWriteByte(0xF0);
buf[2] = Spi_ReadWriteByte(0xF0);
W25Q80_Disable();
}。

相关文档
最新文档