STC89C52驱动W25Q32测试笔记
STC89C52是经典的C51单片机,该芯片不自带硬件SPI接口,正好有手上一块W25Q32的存储模块(某宝上买的2.2元),试着使用89C52模拟SPI接口驱动W25Q32,在驱动的过程中遇到了几个问题,首先的问题是电平不匹配,其次是对芯片datasheet资料的解读,关于W25Qx的资料基本上是全英文的资料,笔者英文水平有限解读起来有一定的困难,只能一点点去解读;其次网络上关于使用C51驱动W25Qx的相关资料有限,很大部分都是使用stm32芯片驱动的案例,结合stm32案例实现W25Qx的驱动,以下内容为个人学习过程小结,由于笔者水平有限,难免有错误,敬请谅解。
一、电路搭建(解决芯片IO电平匹配):
依据W25Qx芯片资料,该芯片支持电平范围为2.7V-3.6V,过电平可能造成损坏芯片,而89C52的IO电平为5V。解决办法是加一块3.3V转5V的电平转换模块(TXS-0108E),电路的连接如下图:
另外网络上也有采用电阻限流的方案,由于元件较多,焊接有点麻烦,笔者未验证,提供下图,仅供学习参考。
二、编写软SPI驱动:
SPI接口一般使用 4 条线通信:
DO 主设备数据输入,从设备数据输出。
DI 主设备数据输出,从设备数据输入。
SCK 时钟信号,由主设备产生。
CS 从设备片选信号,由主设备控制。
SPI 主要特点有:可以同时发出和接收串行数据;可以当作主机或从机工作;提供频率可编程时钟;发送结束中断标志;写冲突保护;总线竞争保护等。
以下是SPI传送时序,SPI传送时序有4种方式,方式0-方式3。
方式0(0,0),方式1(0,1),方式2(1,0),方式3(1,1)
SPI模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,时钟极性(CPOL)对传输协议没有重大的影响。如果CPOL=0,串行同步时钟的空闲状态为低电平;SPI主模块和与之通信的外设时钟相位和极性应该一致。CPOL是用来决定SCK时钟信号空闲时的电平,CPOL=0,空闲电平为低电平,CPOL=1时,空闲电平为高电平。CPHA是用来决定采样时刻的,CPHA=0,在每个周期的第一个时钟沿采样,CPHA=1,在每个周期的第二个时钟沿采样。
小结下上述内容:CPOL=0时起始电平为低电平,CPOL=1时起始电平为高电平。CPHA=0时,CLK的第一个上升沿为采样(写W25Qx), CLK的第一个下降沿为输出(读W25Qx),CPHA=1时,CLK的第一个下降沿为采样(写W25Qx), CLK的第一个上升沿为输出(读W25Qx)。
W25Qx的SPI传输支持方式0和方式3,即方式0(CPOL=0,CPHA=0),方式3(CPOL=1,CPHA=1)。
为了方便起见,笔者以方式0为基础,编写一个SPI的传输函数,该函数发送以MSB(高位优先传输)。
//SPI传输函数,发送与接收一个字节
unsignedchar SPI_Byte(unsigned char dat)
{
unsigned charread=0,i=0;
for(i=0;i<8;i++)
{
W25_DI=dat&0x80;
W25_CLK=1;
dat<<=1;
read<<=1;
read|=W25_DO;
W25_CLK=0;
}
return read;
}
三、编写函数测试获取芯片的Flash ID号(JEDEC ID):
当电路搭建完成后,SPI通信基础函数编写完成后,下一步需要获取芯片返回一个值,测试电路与基础函数成功与否。
依据资料文件,获取ID之前有两点需要注意,第一点是MSB高位优先传输,第二点是获取操作时CS必须拉低。
当获取成功后W25Q32对应的16位的码值为0x4016,下面依据芯片资料提供的时序。
依据上图小结如下信息。
1、获取时CS必须为低电平,高位优先传输。
2、获取JEDEC ID的指令为0x90。
3、接收到信息三个字节,第一个字节为ManufacturerID(制造商ID)固定值为0xEF,第二个字节为MemoryType(内存类型),第三个字节为Capacity(容量)。
编写代码如下:
unsignedlong W25x_read_ID()
{
unsigned long re,t1,t2,t3;
W25_CS=0;
W25_CLK=0;
SPI_Byte(0x9F);
t3=SPI_Byte(0xff);
t2=SPI_Byte(0xff);
t1=SPI_Byte(0xff);
W25_CS=1;
re=(t3<<16)|(t2<<8)|t1;
return re;
}
测试结果:
四、芯片写使能与忙状态等待。
1、写使能:
写使能的操作与读ID的操作类似,其操作指令为0x06,写使能成功后Status Register1的S1位WSL置1,即允许写操作与擦除操作。
//写使能
voidW25x_write_Enable()
{
W25_CS=0;
W25_CLK=0;
SPI_Byte(0x06);
W25_CS=1;
}
2、忙状态等待函数:
当芯片正在执行擦除、写操作时,不允许其它操作,此时必须进入等待状态,直到执行完成后Status Register1的S0位BUSY重新置0后才允许后续操作,函数必须不断的读取状态寄存器,从中提取S0的数据,从而确定相应操作的状态。Status Register1读取指令为0x05,读取方式为MSB那么S0位对应与操作位为0x01,操作方式与读ID的操作类似,依据下图资料的时序,编写函数如下。
//等待擦除或写入操作,直到操作完成结束。
voidW25x_wait_BusyEnd()
{
unsigned char i=0,temp;
W25_CS=0;
W25_CLK=0;
SPI_Byte(0x05);
temp=SPI_Byte(0xff);
while((temp&0x01)==1)
{
temp=SPI_Byte(0xff);
}
W25_CS=1;
}
五、编写擦除指令:
W25Q32为非易失性存储器,写数据之前必须先执行擦除操作,这里我们先编写一个芯片擦除函数。
小结上图芯片资料信息:
1、所谓的芯片擦除是往存储单元字节中填充0xFF即为擦除。
2、芯片擦除操作前必须开启Write Enable(写使能)之前有介绍。
3、芯片擦除操作的指令0x07或0x60,当然CS也必须低电平。
4、芯片擦除完成后需要等待一段时间(读忙状态),之前有介绍。
5、其它与读取ID操作类似。
//芯片擦除操作函数
voidW25x_chipErase()
{
W25x_write_Enable();//开使能
W25_CS=0;
W25_CLK=0;
SPI_Byte(0xC7);
W25_CS=1;
W25x_wait_BusyEnd();//等待擦除操作完成结束
}
六、页写入操作:
W25Qx最大写入单位为页(Page),每页最多写入256B,超过256B必须另写一页,每16页组成一个扇区(Sector),每16个扇区组成一个块(Block)。W25x32为4MB的容量,共有64个块,1024个扇区,16384个页。地址范围为(0x000000-0x2FFFFF),理论上地址每一位对应一个字节,实际在连续写入大数据的过程中还需考虑页、扇区、块的容量问题。注意写之前必须确保是擦除操作过的,最小的擦除单位不是页而是扇区。下面的例子仅考虑页写,理想的起始地址为页的起始位置,内容小于256B。
1块=16扇区,1扇区=16页,1页=256字节
小结上图芯片资料如下:
1、页写操作与擦除操作类似,需要CS低电平、写使能、忙等待。
2、页写操作指令为0x02,接下来是24位地址(页的每页的起始地址为:0xXXXX00,页结束地址为0xXXXXFF其中X为16进制任意数)。
3、写入地址完成后,再次写入不大于256B的数据内容
页写代码如下:
//页写操作,*buf为内容,addr为地址,PageSize为写入字节数必//须小于256个
voidW25x_write_Page(unsigned char *buf,unsigned long addr,unsigned int Pagesize)
{
W25x_write_Enable();
W25_CS=0;
W25_CLK=0;
SPI_Byte(0x02);
SPI_Byte(addr>>16&0xff);
SPI_Byte(addr>>8&0xff);
SPI_Byte(addr&0xff);
if(Pagesize>256)
{
Pagesize=256;
}
while(Pagesize--)
{
SPI_Byte(*buf++);
}
W25_CS=1;
W25x_wait_BusyEnd();
}
七、读操作:
读操作相对于写操作比较简单,不用考虑页、扇区、块,仅使用24位地址即可读。
小结上图芯片资料如下:
1、读操作与读ID操作类似,需要CS低电平。
2、读操作指令为0x03,接下来是24位地址。
3、写入地址完成后直接读出数据内容。
//读操作,*buf为内容,addr为地址,PageSize为读出的字节数
voidW25x_read_Page(unsigned char *buf,unsigned long addr,unsigned int Pagesize)
{
W25_CS=0;
W25_CLK=0;
SPI_Byte(0x03);
SPI_Byte(addr>>16&0xff);
SPI_Byte(addr>>8&0xff);
SPI_Byte(addr&0xff);
while(Pagesize--)
{
*buf=SPI_Byte(0xff);
buf++;
}
W25_CS=1;
}
八、读写测试
数组a为写入内容,数据b为读出数据,i为芯片ID信息,所有信息通过串口发送至电脑。
voidmain()
{
unsigned long i;
unsigned chara[]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,0x11,0x12,0x13};//写入内容
unsigned char b[15];//读出内容
char j;
uart_init(); //串口初始化
i=W25x_read_ID();//读ID
uart_sendbyte(i/256/256);
uart_sendbyte(i/256);
uart_sendbyte(i%256);
W25x_chipErase();//芯片擦除
W25x_write_Page(a,0x000002,15);//从02位置开始写入
W25x_read_Page(b,0x000000,15);//从00位置开始读信息
for(j=0;j<15;j++)
{
uart_sendbyte(b[j]);//输出所读内容
}
while(1);
}
输出结果:
实物展示:
STC89C52驱动W25Q32测试笔记相关推荐
- Windows驱动开发学习笔记(四)—— 3环与0环通信(常规方式)
Windows驱动开发学习笔记(四)-- 3环与0环通信(常规方式) 设备对象 创建设备对象 设置数据交互方式 创建符号链接 IRP与派遣函数 IRP的类型 其它类型的IRP 派遣函数 派遣函数注册位 ...
- Windows驱动开发学习笔记(一)—— 环境配置第一个驱动程序
Windows驱动开发学习笔记(一)-- 环境配置&第一个驱动程序 环境配置 第一个驱动程序 环境配置 安装VS2010:https://pan.baidu.com/s/1uZWWxCtB60 ...
- 软件质量保证与测试笔记——江湖救急版
软件质量保证与测试笔记--江湖救急版 Powered by DZY 以下部分图片来源于老师课件,仅供学习交流使用,侵权致删! Ch1 软件质量与测试概念 软件质量的定义 软件质量是"反映实体 ...
- Windows驱动开发学习笔记(七)—— 多核同步内核重载
Windows驱动开发学习笔记(七)-- 多核同步 基础知识 并发与同步 分析 InterlockedIncrement 原子操作相关API 内核文件 多核同步 临界区 示例一:错误的临界区 示例二: ...
- Windows驱动开发学习笔记(六)—— Inline HOOK
Windows驱动开发学习笔记(六)-- Inline HOOK SSDT HOOK Inline Hook 挂钩 执行流程 脱钩 实验一:3环 Inline Hook 实验二:0环 Inline H ...
- Windows驱动开发学习笔记(五)—— SSDT HOOK
Windows驱动开发学习笔记(五)-- SSDT HOOK 系统服务表 系统服务描述符表 实验一:通过代码获取SSDT表地址 通过页表基址修改页属性 方法1:修改页属性 方法2:修改CR0寄存器 实 ...
- Windows驱动开发学习笔记(三)—— 内核空间内核模块
Windows驱动开发学习笔记(三)-- 内核空间&内核模块 内核空间 实验 第一步:编译如下代码 第二步:将 .sys 文件拷贝到虚拟机中 第三步:部署 .sys 文件并运行 第四步:创建一 ...
- Windows驱动开发学习笔记(二)—— 驱动调试内核编程基础
Windows驱动开发学习笔记(二)-- 驱动调试&内核编程基础 基础知识 驱动调试 PDB(Program Debug Database) WinDbg 加载 PDB 实验:调试 .sys ...
- 基于fpga的dds函数信号发生器的设计_超声信号功率放大器驱动压电陶瓷测试
压电陶瓷片是一种电子发音元件,以锆钛酸铅压电陶瓷材料制成.基于压电效应原理,当在两片电极上面接通交流音频信号时,压电片会根据信号的大小频率发生震动而产生相应的声音来. 压电陶瓷驱动电源的性能直接关系着 ...
最新文章
- oracle enterprise linux 5.7,Red Hat Enterprise Linux 5.7 安装Oracle数据库
- (五)springmvc+mybatis+dubbo+zookeeper分布式架构 整合 - maven构建根项目
- ubuntu 16.04修复固件刷新失败的LimeSDR-USB V1.4
- mailmessage html编码,C#MailMessage顯示HTML標記的AlternateViews
- 使用级联SFU改善媒体质量和规模
- mapreduce阶段出现pending的原因及解决
- SSO之CAS单点登录实例演示
- 云南省最好的计算机学校排名,云南学校排名
- ⽤户去输⼊⼀个⼈民币⾦额,然后程序会计算如何去⽤20元纸币,10元纸币,5元纸币和⼀元纸币去表⽰这个⼈民币⾦额。要求使⽤最⼩数⽬的纸币。
- React + Springboot + Quartz,从0实现Excel报表自动化
- latex的段落间距设置
- java统计字数_JAVA 仿 MS word 字数统计
- 信息与网络安全复习(四)——无线网络安全与DES算法
- 编程语言只是一个工具
- 细数人工智能这几年的悲与喜
- 手机软件开发环境种类介绍(转)
- 02.Python网络爬虫第二弹(http和https协议)
- mysql数据报错:Packet for query is too large (1348754 1048576)
- 变量泵-变量马达静液压行走 Variable pump-variable motor in Drive system
- 鼠标点一下就行 玩转CPU软件超频
热门文章
- 用关键词搜索店铺列表详情
- 编辑器下运行exe或bat run exe or bat in editor
- android10全面屏手势 操作图,丨系统设计丨ZUI 10加入更多全面屏手势
- syntactic与semantic
- Syntactic sugar Syntactic salt
- MAC软件推荐(Java方向)
- [Kaggle实战] Titanic 逃生预测 (1) - 项目起步
- 《易经》 数中以9最为奇妙
- 华为确定发布鸿蒙的时间了吗,Mate40系列首发,华为鸿蒙OS手机版发布时间确定...
- PyTorch语音识别框架,将语音转成文本格式