模块推荐:/item.htm?ft=t&id=671629736762
32---SPI读写PSRAM64实验实验:
硬件需求:PC机,PCM模块一个,microUSB线,APS6404L芯片一个;
软件需求:PCM编译软件,电脑端串口调试助手;
供电方式:USB线接PC机供电;
连接电路:图41
图41 SPI读写PSRAM64实验电路
本实验演示如何通过SPI接口读写PSRAM芯片APS6404L芯片,连接电路参考图
41;
APS6404L支持SPI两线接口和四线接口(QSPI),最大支持时钟频率133MHz,本
实验使用SPI两线接口,慢速读写,采用20MHz的时钟频率;
APS6404L有8M字节的存储空间,字节地址从0到H7FFFFF,共3个字节的地址空
间。
实验中,每次4字节读写,在内存地址0处保存值0,在内存地址4处,保存值2,在
内存地址8处,保存值3......,依次类推,内存地址每次加4,写入值每次加1。写入后延迟
1S,然后读出,再延迟1S,循环下一次写入。当写入值大于16进制200000时,又从地
址0开始写入0,如此循环下去。
实验程序如下:
//写内存子程序,D0为要写入的内存地址,D1为要写入的字节数,写入的值存放在D10
//起始的寄存器中
1 subpro writeram
2 mov 0 d5//D5=0,字节地址清零
3 mov d0 d2//D2=D0, D2为要写入的内存地址,3个字节,共24位值
4 mov d1 d3//D3=D1,D3为要写入的字节数
5 mov 2 d4//D4=2,写内存命令
6 reset y0 //y0=0,片选使能
7 spiwrite d4//写入2,表示准备写入
8 spiwrite d2//写入内存地址,共3个字节,先写最低字节
9 movr d2 8 d2//地址右移8位,准备写入第2个字节
10 spiwrite d2//写入第2个字节
11 movr d2 8 d2//地址再右移8位,准备写入第3个字节
12 spiwrite d2//写入第3个字节
13 while d3//连续写
14 rbyte d10 d4 d5 //依次取出需要写入的字节值,保存到D4寄存器中
15 spiwrite d4 //写入内存,每次写入一个字节
16 inc d5 //字节地址加1
17 dec d3//要写入的字节数减1
18 endwhile
19 set y0 //y0=1,片选失能
20 endsub
//读内存子程序,D0为要读取内存地址,D1为要读取的字节数,读取的值存放在D20起
//始的寄存器中
21 subpro readram
22 mov 0 d5 //D5=0,字节地址清零
23 mov d0 d2//D2=D0, D2为要读取的内存地址,3个字节,共24位值
24 mov d1 d3//D3=D1,D3为要读取的字节数
25 mov 3 d4 //D4=3,读内存命令
26 reset y0 //y0=0,片选使能
27 spiwrite d4//写入3,表示准备读取
28 spiwrite d2 //写入内存地址,共3个字节,先写最低字节
29 movr d2 8 d2//地址右移8位,准备写入第2个字节
30 spiwrite d2 //写入第2个字节
31 movr d2 8 d2//地址再右移8位,准备写入第3个字节
32 spiwrite d2 //写入第3个字节
33 while d3 //连续读
34 spiread d4 //读取一个字节保存到D4寄存器中
35 wbyte d4 d20 d5//D20为读取的缓存地址,读取的值D4依次保存到缓存
//中,D5为缓存字节地址
36 inc d5 //字节地址加1
37 dec d3//要读取的字节数减1
38 endwhile
39 set y0 //y0=1,片选失能
40 endsub
41 subpro reset //复位RAM子程序,连续写入16进制的66,99,可以复位RAM
42 reset y0//y0=0,片选使能
43 mov h66 d4 //D4=H66
44 spiwrite d4//写入16进制的66
45 mov h99 d4//D4=H99
46 spiwrite d4 //写入16进制的99
47 set y0//y0=1,片选失能
48 endsub
49 subpro readid //读ID子程序,MF ID=H0D,KGD=H5D,EID=2
50 mov 0 d5//D5=0,字节地址清零
51 mov 0 d2 //D2=0,写入数据清零
52 mov 9 d3 //D3=9,读9个字节
53 mov h9f d4 //D4=H9F,读ID命令
54 reset y0 //y0=0,片选使能
55 spiwrite d4//写入16进制9f,
56 spiwrite d2//写入3个字节,全部写0
57 spiwrite d2
58 spiwrite d2
59 while d3//连续读9个字节
60 spiread d4//读取1个字节到D4
61 wbyte d4 d20 d5//读取的数据保存到D20读取缓存中
62 inc d5//字节地址加1
63 dec d3 //要读取的字节数减1
64 endwhile
65 set y0 //y0=1,片选失能
66 endsub
67 main
68 set y0//输出口Y0作为片选信号,
69 spi 1 9//模式1,20MHz频率,
70 call reset //调用复位子程序,复位RAM
71 call readid //读ID子程序,读取的数据在D20为起始的寄存器中
72 mov 0 d7//D7清零
73 rbyte d20 d6 d7//取出读缓存的第一个字节到D6寄存器中,即MF ID
74 prints "MF ID: %d\r\n" d6 //输出MF ID,值为16进制的0D,即10进制的13
75 inc d7//字节地址加1
76 rbyte d20 d6 d7//取出读缓存的第2个字节到D6寄存器中,即KGD
77 prints "KGD: %d\r\n" d6 //输出KGD,值为16进制的5D,10进制的93
78 inc d7 //字节地址加1
79 rbyte d20 d6 d7//取出读缓存的第3个字节到D6寄存器中
80 movr d6 5 d6 //右移5位即为EID值
81 prints "EID: %d\r\n" d6//输出EID,值为2
82 mov 0 d0 //D0为ram地址,初始化为0
83 mov 4 d1//D1为读取写入的字节数,初始化为4
84 mov 0 d6 //D6为要写入的数据,初始化为0
85 while 1
86 delay 1000//延时1S
87 mov d6 d10 //把D6的值放入写入缓存D10中。
88 call writeram //调用写ram子程序
89 prints "write addr 0x%x:%d\r\n" d0 d6//输出信息,d0为写入地址,D6为写
//入数据
90 delay 1000//延时1S
91 call readram//调用读RAM子程序,读出的数据在D20寄存器中
92 prints "read addr 0x%x:%d\r\n" d0 d20//输出信息,d0为读取地址,D20为
//读取数据
93 add d0 d1 d0 //D0地址加D1,即加4,因为每次写入4个字节
94 inc d6 //写入数据加1
95 if d6 >= h200000//当计数大于等H200000时,内存地址到达最大地址,
96 mov 0 d0//D0为ram地址,初始化为0
97 mov 0 d6 //D6为要写入的数据,初始化为0
98 endif
99 endwhile
100 endmain
程序中第1-20行,为内存写子程序,D0寄存器保存写入地址,D1为写入字节数,
D10为要写入数据的起始地址,即把要写入的数据放入D10开始的寄存器中;
第2-5行,初始化寄存器,字节地址清零,内存地址放入D2中,写入字节数放入D3
中,写内存命令2放入D4中;
第6-12行,首先Y0置低,使能片选端,然后写入命令码2,表示写命令,接着写入3
个字节的内存地址,内存地址由低到高写入。
第13-18行,循环写入内存数据,每次写一个字节。
第14行,把写缓存D10的数据读取到D4寄存器中,D5为字节地址;
第15行,写入内存,写入值为D4寄存器的值;
第16-18行,字节地址D5加1,写入字节数D3减1,然后跳回到13行,进行下一个字
节的写入;
第19行,数据写完后,Y0置1,片选端失能,结束整个写操作;
程序中第21-40行,为内存读子程序,D0寄存器保存要读取的内存地址,D1为要读
取的字节数,D20为读取的数据的起始地址,即读取的字节值放入D20开始的寄存器中;
第22-32行,与写子程序差不多,唯一的是读取命令码为3,所以要先写入3,然后
再写入要读取的内存地址;
第33-38行,循环读内存,每次读取一个字节,保存到D20起始的寄存器中;
第34行,读取一个字节保存到D4寄存器中;
第35行,把D4的值保存到读缓存D20寄存器中,D5为字节地址;
第36-38行,字节地址D5加1,字节数D3减1,然后跳到33行,继续读取下一个字
节;
第39行,数据读取完后,Y0置1,片选端失能,结束整个读操作;
第41-48行,为复位子程序,只需要连续写入16进制的66,99,共2个字节,即可以
复位芯片;
第49-66行,为读芯片ID子程序,读ID的命令码为16进制的9F。读取ID过程与读子
程序差不多,总共读取了13个字节,我们只需要查看前3个字节就可以了,此3个字节的
具体值可以参考芯片的数据手册。此子程序主要是为了测试与芯片的通讯是否正常,或
者芯片是否损坏;
第67-100行,为主程序,程序先初始化SPI接口,然后复位芯片,读ID并显示,最
后循环写入读出并输出显示;
第68行,Y0=1,失能片选;
第69行,初始化SPI接口为模式1,9表示速度为20MHz;
第70-81行,先复位芯片,然后读ID,并输出显示MF ID,KGD,EID这个3个数值;
第82-99行,在地址0写入数值0,延时1S后读取并输出显示,然后右在地址4写入数
值1,延时1S后读取并输出显示,如此循环,写入地址每次增加4,写入数值每次增加1.
当写入值大于16进制200000时,起始也是大于内存最大地址,然后又重新从地址0开始
写入数值0.
下图42为实验串口输出,可以看出写入值与读取值是一致的。
图42 SPI读写PSRAM64实验串口输出