华芯微特SWM260读写W25Q128
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相关推荐
- 华芯微特SWM32SRET6-50控制器应用记录
因为项目需要驱动800*480的TFT液晶屏,同时客户对成本比较敏感,经过对比选型,最终确定使用了华芯微特的SWM32SRET6-LQFP64,这款芯片先说说优势: 硬件方面: 优点: 主频120MH ...
- 华芯微特SWM320TFT屏人机交互方案手册
1方案特点概述 TFT屏驱动人机交互方案采用华芯微特科技有限公司(附录简介)的SWM320芯片进行设计,支持输出RGB565格式,可直接读取SD卡内数据显示.最高支持驱动1024x768分辨率显示屏, ...
- Nano34SR工业级开源智能硬件主板 华芯微特 SWM34SRET6
Nano34SR是广州枇杷树科技(www.loqtree.com)开发的一款便捷灵活.方便上手的工业级开源智能硬件主板,它从低成本.小体积(普通银行卡片式大小,尺寸54x85mm).高性能方面入手,结 ...
- 华芯微特MCU——SWM181
01SWM181芯片介绍 文章目录 01SWM181芯片介绍 我们来认识一下!SWM181CBT6是什么? 环境搭建教程 板子的使用都是点灯大师开始的! 记得关注噢!会持续推进学习新进度! 我们先来看 ...
- [0]SWM181-从零开发华芯微特MCU
[0]从零开发华芯微特MCU--SWM181 感谢韬哥发来的SWM181CBT6开发板,板子是最小系统,我们仅仅是用于熟悉这个芯片,即使上面资源不多,也丝毫不影响我们对这个芯片外设进行开发. 对SWM ...
- 华芯微特SWM181学习笔记--GPIO应用与环境搭建
华芯微特SWM181 系列 32 位 MCU(以下简称 SWM181)内嵌 ARM® CortexTM-M0 内核, SWM181 支持片上包含精度为 1%以内的 24MHz.48MHz 时钟,并提供 ...
- 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温度表,增加数 ...
- STC8通过SPI读写W25Q128
这几天在看SPI总线,应用主要是围绕W25Q128的读写进行的. 网上关于W25Q的程序可以说非常多,大多是以STM32为主控芯片进行的.无妨.这块FLASH的寄存器是基本固定的,但是只有英文手册确实 ...
- STM32F103标准库开发---SPI实验---读写 W25Q128 外部 Flash
STM32F103标准库开发----目录 W25Q128读写----程序源码----点击下载 W25Qxx全系列数据手册-点击下载 一.实验前期准备 本次实验的 MCU 是 STM32F103C8T6 ...
最新文章
- hibernate02环境的搭建
- Git - 使用指南
- Java相对路径调用dll文件,VS项目中调用他人提供的.lib和.dll文件的用法(绝对路径和相对路径)...
- C语言试题四十七之程序定义了N×M的二维数组,并在主函数中自动赋值。请编写函数function(int a[N][M], int m),该函数的功能是:将数组右上半三角元素中的值乘以m。
- Virtio: An I/O virtualization framework for Linux
- python 100题_python 100题
- 认识Python基础环境搭建
- [poj] 1236 networks of schools
- 线性代数【六】:解线性方程组
- 设计模式 (二十二) 责任链模式
- Implement queue with two stack 用两个堆实现队列
- lbs与gis的计算机存储模式,什么是LBS、GIS
- Linux学习笔记2—常见指令的使用
- (转)[IOS]正在通过app store进行鉴定解决方案
- 北京移动宽带光猫 GM219-S 路由功能分离内置路由器改接外置路由器
- 计算机右键无法新建excel2007,电脑桌面右键新建菜单中没有Word/Excel/PPT等文档怎么办?...
- 分享Silverlight/Windows8/WPF/WP7/HTML5周学习导读(6月11日-6月17日)
- 哄女朋友开心的html源码,很好玩的代码,哄女票开心用
- mplayer的安装
- Unity Shader - 类似七龙珠的人物气焰效果
热门文章
- c语言 函数计算0869,c语言编程- 微积分程序
- onedrive 配置 教你如何获取5T windows资源存储空间和提高数据同步速度
- 劳资蜀道山!6个高质量免费电子书网站!我看谁还不知道
- 新版LinuxLinus Torvalds发布
- Python实现主播人气排行榜,带你发现人气王
- Pygame小游戏:无敌斗牛士
- win7系统如何映射服务器,win7系统映射网络驱动器怎么访问
- PaddleNLP系列课程一:Taskflow、小样本学习、FasterTransformer
- 基于广度优先遍历算法求采用邻接表存储的无向连通图G中从顶点u到v的最短路径
- js获取微信号_前端js可以直接获取到微信用户基本信息吗