W25Q128的读写采用的是SPI接口;本人移植的程序是在STM32上验证过的,只需要修改相应的底层函数即可;

初始化SPI接口;

void MX_SPI_Flash_Init(void)
{SPI_InitStructure SPI_initStruct;PORT_Init(PORTA, PIN5, PORTA_PIN5_SPI0_SSEL, 0);PORT_Init(PORTA, PIN6, PORTA_PIN6_SPI0_MISO, 1);PORT_Init(PORTA, PIN7, PORTA_PIN7_SPI0_MOSI, 0);PORT_Init(PORTA, PIN8, PORTA_PIN8_SPI0_SCLK, 0);SPI_initStruct.FrameFormat = SPI_FORMAT_SPI;//帧格式:SPI_FORMAT_SPI ; SPI_FORMAT_TI_SSISPI_initStruct.SampleEdge = SPI_FIRST_EDGE;在SPI帧格式下,选择数据采样边沿:1 SPI_FIRST_EDGE 、2 SPI_SECOND_EDGESPI_initStruct.IdleLevel = SPI_LOW_LEVEL;//在SPI帧格式下,选择空闲时(无数据传输时)时钟线的电平: SPI_LOW_LEVEL 、 SPI_HIGH_LEVELSPI_initStruct.WordSize = 8;//字长度, 有效值4-16SPI_initStruct.Master = 1;//1 主机模式    0 从机模式SPI_initStruct.clkDiv = SPI_CLKDIV_256;// SPI_CLK = SYS_CLK / clkDiv,有效值:SPI_CLKDIV_4、SPI_CLKDIV_8、... ... 、SPI_CLKDIV_512SPI_initStruct.RXThresholdIEn = 0;//当RX FIFO中数据个数 >= RXThreshold时触发中断   SPI_initStruct.TXThresholdIEn = 0;//当TX FIFO中数据个数 <= TXThreshold时触发中断  SPI_initStruct.TXCompleteIEn  = 0;//发送FIFO空且发送移位寄存器空中断使能SPI_FLASH_CS_H();SPI_Init(SPI0, &SPI_initStruct);SPI_Open(SPI0);SPI2_WriteByte( 0xFF);
}

修改底层函数,主要是SPI的读写函数,参照官方SWM181读写flash的写法,全部采用SPI_ReadWrite();来进行SPI通信的读写操作;

uint8_t SPI2_ReadByte(void)
{return SPI_ReadWrite(SPI0, 0xFF);
}
void SPI2_WriteByte(uint8_t TxData)
{SPI_ReadWrite(SPI0, TxData);
}
/*SPI1 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节*/
uint8_t SPI2_ReadWriteByte(uint8_t TxData)
{return SPI_ReadWrite(SPI0, TxData);
}

注意踩坑部分!!!!!!

因为是项目需要,我的程序中有一个串口是一直在接收蓝牙扫描的广播信息的,该串口我采用的是DMA的方式进行接收的,一直会有DMA中断过来影响到SPI接口读写W25Q,也就是说,在SPI读写W25Q时不能有任何中断来打断它,故最后我修改代码部分如下:

#if 0#define SPI_FLASH_CS_L()    GPIO_ClrBit(GPIOA, PIN5)
#define SPI_FLASH_CS_H()    GPIO_SetBit(GPIOA, PIN5) //GPIO_SetBit(GPIOA, PIN5)#else
void SPI_FLASH_CS_L(void)
{UART_Close(UART0);GPIO_ClrBit(GPIOA, PIN5);    // SPI_CS_Low()
}
void SPI_FLASH_CS_H(void)
{GPIO_SetBit(GPIOA, PIN5);  // SPI_CS_Low()UART_Open(UART0);
}
#endif

在SPI通信时关闭影响的串口,读写测试,全部OK

同样的用法,这种问题在STM32上并没有出现,国产芯片任重而道远呐

附W25Q读写部分,主要是看底层关于SPI的操作,关于W25Q的读写是从网上找的前辈的程序修改的

"w25q128.h"


#ifndef __W25Q128_H__
#define __W25Q128_H__#include "SWM260.h"
#include "SWM260_spi.h"//SPIflash
#define FLASH_ID 0XEF17                     //W25Q128
//指令表
#define W25X_WriteEnable        0x06 //写使能
#define W25X_WriteDisable       0x04 //写失能
#define W25X_ReadStatusReg      0x05 //读控制和状态寄存器
#define W25X_WriteStatusReg     0x01 //写控制和状态寄存器
#define W25X_ReadData           0x03 //读数据
#define W25X_FastReadData       0x0B //快速读数据
#define W25X_FastReadDual       0x3B //快速读取双通道输出
#define W25X_PageProgram        0x02 //页写
#define W25X_BlockErase         0xD8 //64KB块擦除
#define W25X_SectorErase        0x20 //扇区擦除4k
#define W25X_ChipErase          0xC7 //整片擦除
#define W25X_PowerDown          0xB9 //待机模式
#define W25X_ReleasePowerDown   0xAB //读芯片ID
#define W25X_DeviceID           0xAB //读芯片ID
#define W25X_ManufactDeviceID   0x90 //读芯片ID  读取制造商/设备ID
#define W25X_JedecDeviceID      0x9F //读 JEDEC ID (9Fh)
//片选使能位//spi FLASH          w25Q128  flash读写操作函数
void MX_SPI_Flash_Init(void);//初始化uint8_t SPI2_ReadByte(void);                      //返回通过SPIx最近接收的数据
void SPI2_WriteByte(uint8_t TxData);        //通过外设SPIx发送一个数据
uint8_t SPI2_ReadWriteByte(uint8_t TxData);//发送并接收返回的一个数据
void SPI_FLASH_Write_Enable(void);          //SPI_FLASH写使能          //将WEL置位
void SPI_FLASH_Write_Disable(void);      //SPI_FLASH写禁止         //将WEL清零
uint8_t SPI_Flash_ReadSR(void);             //读取SPI_FLASH的状态寄存器
void SPI_Flash_Wait_Busy(void);             //等待空闲uint16_t SPI_Flash_ReadID(void);          //读取芯片ID W25Q128的ID:0XEF17
void SPI_Flash_Erase_Chip(void) ;       //擦除整个芯片  W25Q128   80S
void SPI_Flash_Erase_Sector(uint32_t Dst_Addr);//擦除一个扇区
void SPI_Flash_Read(uint32_t ReadAddr,uint16_t NumByteToRead,uint8_t* pBuffer) ;            //读取SPI FLASH
void SPI_Flash_Write_Page(uint32_t WriteAddr,uint16_t NumByteToWrite,uint8_t* pBuffer);//SPI在一页(0~65535)内写入少于256个字节的数据
void W25QXX_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);//无需校验写入  #endif

"w25q128.c"


#include "w25q128.h"#define SpiW25Q                   SPI0#if 0#define SPI_FLASH_CS_L()   GPIO_ClrBit(GPIOA, PIN5)
#define SPI_FLASH_CS_H()    GPIO_SetBit(GPIOA, PIN5) //GPIO_SetBit(GPIOA, PIN5)#else
void SPI_FLASH_CS_L(void)
{UART_Close(UART0);GPIO_ClrBit(GPIOA, PIN5);    // SPI_CS_Low()
}
void SPI_FLASH_CS_H(void)
{GPIO_SetBit(GPIOA, PIN5);  // SPI_CS_Low()UART_Open(UART0);
}
#endif/*-------------------------SPIflash----------------------------------------------------W25Q128---------------------------------------------*/
void MX_SPI_Flash_Init(void)
{SPI_InitStructure SPI_initStruct;PORT_Init(PORTA, PIN5, PORTA_PIN5_SPI0_SSEL, 0);PORT_Init(PORTA, PIN6, PORTA_PIN6_SPI0_MISO, 1);PORT_Init(PORTA, PIN7, PORTA_PIN7_SPI0_MOSI, 0);PORT_Init(PORTA, PIN8, PORTA_PIN8_SPI0_SCLK, 0);SPI_initStruct.FrameFormat = SPI_FORMAT_SPI;//帧格式:SPI_FORMAT_SPI ; SPI_FORMAT_TI_SSISPI_initStruct.SampleEdge = SPI_FIRST_EDGE;在SPI帧格式下,选择数据采样边沿:1 SPI_FIRST_EDGE 、2 SPI_SECOND_EDGESPI_initStruct.IdleLevel = SPI_LOW_LEVEL;//在SPI帧格式下,选择空闲时(无数据传输时)时钟线的电平: SPI_LOW_LEVEL 、 SPI_HIGH_LEVELSPI_initStruct.WordSize = 8;//字长度, 有效值4-16SPI_initStruct.Master = 1;//1 主机模式    0 从机模式SPI_initStruct.clkDiv = SPI_CLKDIV_256;// SPI_CLK = SYS_CLK / clkDiv,有效值:SPI_CLKDIV_4、SPI_CLKDIV_8、... ... 、SPI_CLKDIV_512SPI_initStruct.RXThresholdIEn = 0;//当RX FIFO中数据个数 >= RXThreshold时触发中断   SPI_initStruct.TXThresholdIEn = 0;//当TX FIFO中数据个数 <= TXThreshold时触发中断  SPI_initStruct.TXCompleteIEn  = 0;//发送FIFO空且发送移位寄存器空中断使能SPI_FLASH_CS_H();SPI_Init(SPI0, &SPI_initStruct);SPI_Open(SPI0);SPI2_WriteByte( 0xFF);
}uint8_t SPI2_ReadByte(void)
{return SPI_ReadWrite(SPI0, 0xFF);
}
void SPI2_WriteByte(uint8_t TxData)
{SPI_ReadWrite(SPI0, TxData);
}
/*SPI1 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节*/
uint8_t SPI2_ReadWriteByte(uint8_t TxData)
{return SPI_ReadWrite(SPI0, TxData);
}/*SPI_FLASH写使能 将WEL置位   */
void SPI_FLASH_Write_Enable(void)
{SPI_FLASH_CS_L();                            //使能器件   SPI2_WriteByte(W25X_WriteEnable);                //发送``写使能  0x06SPI_FLASH_CS_H();                            //取消片选
}
/*SPI_FLASH写禁止  将WEL清零  */
void SPI_FLASH_Write_Disable(void)
{SPI_FLASH_CS_L();                            //使能器件   SPI2_WriteByte(W25X_WriteDisable);     //发送写禁止指令 ```0x04   SPI_FLASH_CS_H();                           //取消片选
}
/*读取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,空闲)
//默认:0x00
*/
uint8_t SPI_Flash_ReadSR(void)
{  uint8_t byte=0;   SPI_FLASH_CS_L();                                 //使能器件   SPI2_WriteByte(W25X_ReadStatusReg);                 //发送读取状态寄存器命令 ```0x05  byte = SPI2_ReadByte();                                             //读取一个字节  SPI_FLASH_CS_H();                            //取消片选 return byte;
}
/*等待空闲*/
void SPI_Flash_Wait_Busy(void)
{while ((SPI_Flash_ReadSR()&0x01)==0x01);   // 等待BUSY位清空
}/*读取芯片ID
//返回值如下:
//0XEF13,表示芯片型号为W25Q80
//0XEF14,表示芯片型号为W25Q16
//0XEF15,表示芯片型号为W25Q32
//0XEF16,表示芯片型号为W25Q64
//0XEF17,表示芯片型号为W25Q128
*/
uint16_t SPI_Flash_ReadID(void)
{uint16_t Temp = 0;SPI_FLASH_CS_L();SPI2_WriteByte(0x90);//发送读取ID命令        0x90SPI2_WriteByte(0x00);SPI2_WriteByte(0x00);SPI2_WriteByte(0x00);Temp|=SPI2_ReadByte()<<8;Temp|=SPI2_ReadByte();SPI_FLASH_CS_H();return Temp;
}  /*擦除整个芯片
//整片擦除时间:
//W25X16:25s
//W25X32:40s
//W25X64:40s
//等待时间超长...
*/
void SPI_Flash_Erase_Chip(void)
{SPI_FLASH_Write_Enable();                  //SET WEL SPI_Flash_Wait_Busy();   SPI_FLASH_CS_L();                            //使能器件   SPI2_WriteByte(W25X_ChipErase);        //发送片擦除命令  SPI_FLASH_CS_H();                            //取消片选            SPI_Flash_Wait_Busy();                   //等待芯片擦除结束
}  /*擦除一个扇区;Dst_Addr:扇区地址 根据实际容量设置;擦除一个扇区的最少时间:150ms   4k  */
void SPI_Flash_Erase_Sector(uint32_t Dst_Addr)
{Dst_Addr*=4096;   SPI_FLASH_Write_Enable();                  //SET WEL SPI_Flash_Wait_Busy();   SPI_FLASH_CS_L();                            //使能器件   SPI2_WriteByte(W25X_SectorErase);        //发送扇区擦除命令     SPI2_ReadWriteByte((uint8_t)((Dst_Addr)>>16));  //发送24bit地址    SPI2_ReadWriteByte((uint8_t)((Dst_Addr)>>8));   SPI2_ReadWriteByte((uint8_t)Dst_Addr);SPI_FLASH_CS_H();                            //取消片选              SPI_Flash_Wait_Busy();                   //等待芯片擦除结束
}  /*读取SPI FLASH  在指定地址开始读取指定长度的数据ReadAddr:开始读取的地址(24bit)NumByteToRead:要读取的字节数(最大65535)pBuffer:数据存储区
*/
void SPI_Flash_Read(uint32_t ReadAddr,uint16_t NumByteToRead,uint8_t* pBuffer)
{uint16_t i;                                                        SPI_FLASH_CS_L();                          //使能器件   SPI2_WriteByte(W25X_ReadData);         //发送读取命令   SPI2_WriteByte((uint8_t)((ReadAddr)>>16));  //发送24bit地址    SPI2_WriteByte((uint8_t)((ReadAddr)>>8));SPI2_WriteByte((uint8_t)ReadAddr);for(i=0;i<NumByteToRead;i++){ pBuffer[i] = SPI2_ReadByte();   //循环读数  }SPI_FLASH_CS_H();//取消片选
}/*SPI在一页(0~65535)内写入少于256个字节的数据
在指定地址开始写入最大256字节的数据
pBuffer:数据存储区
WriteAddr:开始写入的地址(24bit)
NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!
*/
void SPI_Flash_Write_Page(uint32_t WriteAddr,uint16_t NumByteToWrite,uint8_t* pBuffer)
{uint16_t i;SPI_FLASH_Write_Enable();                  //SET WELSPI_FLASH_CS_L();                            //使能器件SPI2_WriteByte(W25X_PageProgram);      //发送写页命令SPI2_WriteByte((uint8_t)((WriteAddr)>>16)); //发送24bit地址SPI2_WriteByte((uint8_t)((WriteAddr)>>8));SPI2_WriteByte((uint8_t)WriteAddr);for(i=0;i<NumByteToWrite;i++) SPI2_WriteByte(pBuffer[i]);//循环写数SPI_FLASH_CS_H();                            //取消片选 SPI_Flash_Wait_Busy();                      //等待写入结束
}
/*
无检验写SPI FLASH ;必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败!
具有自动换页功能 ;在指定地址开始写入指定长度的数据,但是要确保地址不越界!
pBuffer:数据存储区
WriteAddr:开始写入的地址(24bit)
NumByteToWrite:要写入的字节数(最大65535)
CHECK OK
*/
void W25QXX_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{uint16_t pageremain;      pageremain=256-WriteAddr%256; //单页剩余的字节数                if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256个字节while(1){      SPI_Flash_Write_Page(WriteAddr,pageremain,pBuffer);if(NumByteToWrite==pageremain)break;//写入结束了else //NumByteToWrite>pageremain{pBuffer+=pageremain;WriteAddr+=pageremain;   NumByteToWrite-=pageremain;              //减去已经写入了的字节数if(NumByteToWrite>256)pageremain=256; //一次可以写入256个字节else pageremain=NumByteToWrite;       //不够256个字节了}}
}

华芯微特SWM260读写W25Q128相关推荐

  1. 华芯微特SWM32SRET6-50控制器应用记录

    因为项目需要驱动800*480的TFT液晶屏,同时客户对成本比较敏感,经过对比选型,最终确定使用了华芯微特的SWM32SRET6-LQFP64,这款芯片先说说优势: 硬件方面: 优点: 主频120MH ...

  2. 华芯微特SWM320TFT屏人机交互方案手册

    1方案特点概述 TFT屏驱动人机交互方案采用华芯微特科技有限公司(附录简介)的SWM320芯片进行设计,支持输出RGB565格式,可直接读取SD卡内数据显示.最高支持驱动1024x768分辨率显示屏, ...

  3. Nano34SR工业级开源智能硬件主板 华芯微特 SWM34SRET6

    Nano34SR是广州枇杷树科技(www.loqtree.com)开发的一款便捷灵活.方便上手的工业级开源智能硬件主板,它从低成本.小体积(普通银行卡片式大小,尺寸54x85mm).高性能方面入手,结 ...

  4. 华芯微特MCU——SWM181

    01SWM181芯片介绍 文章目录 01SWM181芯片介绍 我们来认识一下!SWM181CBT6是什么? 环境搭建教程 板子的使用都是点灯大师开始的! 记得关注噢!会持续推进学习新进度! 我们先来看 ...

  5. [0]SWM181-从零开发华芯微特MCU

    [0]从零开发华芯微特MCU--SWM181 感谢韬哥发来的SWM181CBT6开发板,板子是最小系统,我们仅仅是用于熟悉这个芯片,即使上面资源不多,也丝毫不影响我们对这个芯片外设进行开发. 对SWM ...

  6. 华芯微特SWM181学习笔记--GPIO应用与环境搭建

    华芯微特SWM181 系列 32 位 MCU(以下简称 SWM181)内嵌 ARM® CortexTM-M0 内核, SWM181 支持片上包含精度为 1%以内的 24MHz.48MHz 时钟,并提供 ...

  7. H7-TOOL的APP固件升级至V2.05,上位机升级至V2.05,支持CAN助手,新增华芯微特SWM和杰发科技AC78X脱机烧录(2021-05-16)

    说明: 1.增加CAN助手功能. 2.串口助手中新增串口示波器功能. 3.lua增加CAN接口API. 4.lua增加读文件接口API, f_read, f_dir. 5.DS18B20温度表,增加数 ...

  8. STC8通过SPI读写W25Q128

    这几天在看SPI总线,应用主要是围绕W25Q128的读写进行的. 网上关于W25Q的程序可以说非常多,大多是以STM32为主控芯片进行的.无妨.这块FLASH的寄存器是基本固定的,但是只有英文手册确实 ...

  9. STM32F103标准库开发---SPI实验---读写 W25Q128 外部 Flash

    STM32F103标准库开发----目录 W25Q128读写----程序源码----点击下载 W25Qxx全系列数据手册-点击下载 一.实验前期准备 本次实验的 MCU 是 STM32F103C8T6 ...

最新文章

  1. hibernate02环境的搭建
  2. Git - 使用指南
  3. Java相对路径调用dll文件,VS项目中调用他人提供的.lib和.dll文件的用法(绝对路径和相对路径)...
  4. C语言试题四十七之程序定义了N×M的二维数组,并在主函数中自动赋值。请编写函数function(int a[N][M], int m),该函数的功能是:将数组右上半三角元素中的值乘以m。
  5. Virtio: An I/O virtualization framework for Linux
  6. python 100题_python 100题
  7. 认识Python基础环境搭建
  8. [poj] 1236 networks of schools
  9. 线性代数【六】:解线性方程组
  10. 设计模式 (二十二) 责任链模式
  11. Implement queue with two stack 用两个堆实现队列
  12. lbs与gis的计算机存储模式,什么是LBS、GIS
  13. Linux学习笔记2—常见指令的使用
  14. (转)[IOS]正在通过app store进行鉴定解决方案
  15. 北京移动宽带光猫 GM219-S 路由功能分离内置路由器改接外置路由器
  16. 计算机右键无法新建excel2007,电脑桌面右键新建菜单中没有Word/Excel/PPT等文档怎么办?...
  17. 分享Silverlight/Windows8/WPF/WP7/HTML5周学习导读(6月11日-6月17日)
  18. 哄女朋友开心的html源码,很好玩的代码,哄女票开心用
  19. mplayer的安装
  20. Unity Shader - 类似七龙珠的人物气焰效果

热门文章

  1. c语言 函数计算0869,c语言编程- 微积分程序
  2. onedrive 配置 教你如何获取5T windows资源存储空间和提高数据同步速度
  3. 劳资蜀道山!6个高质量免费电子书网站!我看谁还不知道
  4. 新版LinuxLinus Torvalds发布
  5. Python实现主播人气排行榜,带你发现人气王
  6. Pygame小游戏:无敌斗牛士
  7. win7系统如何映射服务器,win7系统映射网络驱动器怎么访问
  8. PaddleNLP系列课程一:Taskflow、小样本学习、FasterTransformer
  9. 基于广度优先遍历算法求采用邻接表存储的无向连通图G中从顶点u到v的最短路径
  10. js获取微信号_前端js可以直接获取到微信用户基本信息吗