匆匆忙忙拼凑了一个使用QSPI方式读写W25Q128的例程,依旧使用擎天柱开发板。测试中有单线模式、双线模式、四线模式的处理。
接线方式:

程序代码如下:
//// 测试工作频率为 40MHz
//// 测试使用Timer2作为串口1的波特率发生器,波特率=115200
//// 串口1:P3.6(RXD),P3.7(TXD)
#include "AI8051U.h"
#include <stdio.h>
#include <intrins.h>
#include "qspi.h"
#include "w25q128.h"
//#define FOSC 22118400L // 下载程序时,使用改频率烧录
//#define BRT (65536 - (FOSC / 115200+2) / 4) //加 2 操作是为了让 Keil 编译器,自动实现四舍五入运算
sbit LED = P1^0;
#define FOSC 40000000UL
#define BAUD (65536 - FOSC/4/115200)
#define SIZE 30
/*****************************************************************************/
#define INIT_BUF() for (i=0; i<SIZE; i++) buf[i] = 0;
#define SET_BUF() for (i=0; i<SIZE; i++) buf[i] = (BYTE)(i + 0x00);
#define PRINT_BUF() for (i=0; i<SIZE; i++) \
{ \
printf("%02bx ", buf[i]); \
if ((i % 32) == 31) \
printf("\n "); \
} \
printf("\n");
/*****************************************************************************/
BYTE xdata buf[1024];
/*****************************************************************************/
void delay(int n) {
int i;
while (n--)
for (i = 0; i < 1000; i++) {
_nop_();
_nop_();
_nop_();
_nop_();
}
}
// 初始化定时器2
void Timer2Init(void) {
T2L = BAUD;
T2H = BAUD >> 8;
S1BRT = 1; // S1BRT:串口 1 波特率发生器选择位, 0:选择定时器 1 作为波特率发生器, 1:选择定时器 2 作为波特率发生器(默认值)
T2x12 = 1;
T2R = 1;
}
// 串口1
//------------------------------begin---------------------------------
// 串口处理用变量
bit busy1;
char wptr1;
char rptr1;
char buffer1[64];
// 串口1的中断处理
void Uart1Isr() interrupt 4 {
if (TI) {
TI = 0;
busy1 = 0;
}
if (RI) {
RI = 0;
buffer1[wptr1++] = SBUF;
wptr1 &= 0x0f;
}
}
// 初始化串口1
void Uart1Init() {
SCON = 0x50; //
wptr1 = 0x00;
rptr1 = 0x00;
busy1 = 0;
P_SW1 |= 0x40; // 选择P3.6,P3.7,因为擎天柱开发板上不提供P3.0,P3.1引脚
ES = 1;
}
// 向串口1输出一个字符
void Uart1Send(char dat) {
while (busy1);
busy1 = 1;
SBUF = dat;
}
char putchar(char c) {
Uart1Send(c);
return c;
}
//------------------------------end---------------------------------
// 延时
void delay_ms(int ms) {
int i;
do {
i = FOSC/6000;
while(--i);
} while(--ms);
}
void sys_inti(void) {
WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P4M0 |= 0x09; //设置CS/P4.0,SCK/P4.3为强推挽模式
P4M1 &= ~0x09;
P4SR &= ~0x0f; //设置所有的QSPI口为快速模式
P5SR &= ~0x0c;
P4PU |= 0x0f; //使能所有的QSPI口的内部10K上拉电阻
P5PU |= 0x0c;
P4BP &= ~0x06; //使能QSPI的IO0~IO3数据硬件自动设置端口模式
P5BP &= ~0x0c;
}
void main() {
unsigned char state = 0;
unsigned long addr = 0;
unsigned char buff[24]={0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,};
int i;
int j;
unsigned char d1, d2;
// 初始化单片机
sys_inti();
// 打开调试信号
LED = 1;
// 初始化定时2,串口波特率发生器
Timer2Init();
// 初始化串口1
Uart1Init();
// 初始化SPI外设
QSPI_Init();
// 开总中断
EA = 1;
printf("QSPI Test !\n");
printf("W25Q_ReadJEDECID_9F %08lx\n", W25Q_ReadJEDECID_9F());
printf("SR1: %02bx\n", W25Q_ReadSR1_05());
printf("SR2: %02bx\n", W25Q_ReadSR2_35());
printf("SR3: %02bx\n", W25Q_ReadSR3_15());
// 启动测试信号
LED = 0;
if ((W25Q_ReadSR2_35() & 0x02) == 0) {
W25Q_WriteEnableVSR_50();
//W25Q80写SR2方法不同
if ((W25Q_ReadJEDECID_9F() & 0xffff) == 0x4014) {
W25Q_WriteSR12_01(0x0002);
} else {
W25Q_WriteSR2_31(0x02);
}
printf("SR2: %02bx\n", W25Q_ReadSR2_35());
}
printf("W25Q_Erase4K_20\n");
W25Q_Erase4K_20(0);
printf("W25Q_ReadData_03 ");
INIT_BUF();
W25Q_ReadData_03(0, buf, SIZE);
PRINT_BUF();
printf("W25Q_PageProgram_02\n");
SET_BUF();
W25Q_PageProgram_02(0, buf, SIZE);
printf("W25Q_ReadData_03 ");
INIT_BUF();
W25Q_ReadData_03(0, buf, SIZE);
PRINT_BUF();
// 单线模式
printf("W25Q_FastRead_0B ");
INIT_BUF();
W25Q_FastRead_0B(0, buf, SIZE);
PRINT_BUF();
// 双线模式
printf("W25Q_FastRead_3B ");
INIT_BUF();
W25Q_FastRead_3B(0, buf, SIZE);
PRINT_BUF();
// 四线模式
printf("W25Q_FastRead_6B ");
INIT_BUF();
W25Q_FastRead_6B(0, buf, SIZE);
PRINT_BUF();
while (1);
}W25Q128中地址0 开始的32个单元,预先通过编程器写入00~1F数据,测试结果:

工程文件(使用Keil5.28开发):串口_QSPI_W25Q128.zip
我要赚赏金
