文章目录
- STC15 - ExternalRAM_enable()/InternalRAM_enable()
- 概述
- 实验环境
- MCU的规格区别
- IAP15F2K61S2的使用限制
- 实验的组合
- 公用测试代码
- 1. 没有焊接外部RAM + ExternalRAM_enable()
- 2. 没有焊接外部RAM + InternalRAM_enable()
- 3. 焊接外部RAM + ExternalRAM_enable()
- 4. 焊接外部RAM + InternalRAM_enable()
- 总结
- END
STC15 - ExternalRAM_enable()/InternalRAM_enable()
概述
发现使用STC15的外部扩展内存和内部扩展内存时, 有一些问题(访问xdata不是100%好使, 这不是STC的问题, 而是使用问题). 实验总结一下.
实验环境
MDK5
STC15F2K60S2(直接跑程序)
IAP15F2K61S2(仿真单步调试)
STC15函数库
STC15实验箱4
MCU的规格区别
看看STC15F2K60S2和IAP15F2K61S2的规格区别
可以看出, IAP15比STC15程序空间大1K, 其他基本一致.
IAP15F2K61S2的使用限制
可以看出如果没有外接片外RAM, 只能使用0x400(1KB)大小的RAM(xdata)区域.
实验也能看出, 执行InternalRAM_enable(), 如果操作0x400之后的RAM, MDK工程就挂了(仿真器失去连接).
这个不看官方说明真不知道, 因为IAP15F2K61S2内部扩展RAM总共有0x700(1792)字节.
实验的组合
板子上是/否焊接了外部RAM + ExternalRAM_enable()/InternalRAM_enable()
一共4种组合, 看看访问0~32KB都是啥情况(是否读写正确, 是否会挂掉)
因为要单步调试, 都使用IAP15F2K61S2来实验
公用测试代码
根据组合的不同, 调用ExternalRAM_enable()/InternalRAM_enable()后, 再执行下面的公用测试代码(访问32KB的xdata)
u16 data i = 0; // !
// ExternalRAM_enable();
// InternalRAM_enable();
EA = 1;
// 最大可以访问的xram范围 32KB(如果焊接了32KB的外部RAM)
// 分为3个xram区域 低1KB(0 ~ 0x3ff), 中间的792B(0x400 ~ 0x6ff), 高区域到32KB(0x700 ~ 0x7fff)
// 访问xram区域-低1KB - 0x0 ~ 0x3ff
for (i = 0x0; i <= 0x3ff;)
{
pbuf = (u8 xdata*)i;
memset(pbuf, (u8)i, 0x100);
i += 0x100;
}
// 访问xram区域-中间792B - 0x400 ~ 0x6ff
for (i = 0x400; i <= 0x6ff;)
{
pbuf = (u8 xdata*)i;
memset(pbuf, (u8)i, 0x100);
i += 0x100;
}
// 访问xram区域-高至32KB - 0x700 ~ 0x7fff
for (i = 0x700; i <= 0x7fff;)
{
pbuf = (u8 xdata*)i;
memset(pbuf, (u8)i, 0x100);
i += 0x100;
}
1. 没有焊接外部RAM + ExternalRAM_enable()
调用ExternalRAM_enable()后, 再执行公用测试代码(访问32KB的xdata)
代码可以跑(没有挂掉), 但是没效果(没有将xdata区域memset成预期的值), 因为这时就没有实际的外部xram.
可以看出, 即使是0x0~0x400, 也使用的是外部扩展RAM.
2. 没有焊接外部RAM + InternalRAM_enable()
调用InternalRAM_enable()后, 再执行公用测试代码(访问32KB的xdata)
0x0 ~ 0x3ff 访问是正确的, 说明使用的是内部扩展RAM.
0x400 ~ 0x6ff访问异常, 当执行memset时, 单步调试失去响应. 因为从0x400~0x6ff是IAP15F2K61S2自己要用.
0x700 ~ 0x7fff, 代码可以跑(没有挂掉), 但是没效果(没有将xdata区域memset成预期的值), 因为这时就没有实际的外部xram.
综合以上实验效果, 可以看出, InternalRAM_enable()时, 0x0~ 0x6ff使用的就是内部扩展RAM.
3. 焊接外部RAM + ExternalRAM_enable()
0x0 ~ 0x3ff 访问正确
0x400 ~ 0x6ff访问正确, 这说明外接SRAM + ExternalRAM_enable()时, 完全使用的是外部RAM
而不是0~1792使用内部扩展RAM, 1792之外使用外部RAM
0x700 ~ 0x7fff, 访问正确
综合以上实验效果, 可以看出, ExternalRAM_enable()时, 0x0~ 0x7fff使用的都是外部扩展RAM.
4. 焊接外部RAM + InternalRAM_enable()
0x0 ~ 0x3ff 访问正确
0x400 ~ 0x6ff访问异常, 这说明InternalRAM_enable()时, 0x400 ~ 0x6ff使用的是内部扩展RAM
0x700 ~ 0x7fff, 访问正确, 说明即使时执行的InternalRAM_enable(), 超过内部扩展RAM边界(0x6ff)时, 如果接了物理上的外部RAM, 也会自动切到外部RAM上.
总结
- 如果执行了ExternalRAM_enable(), 访问的都是外部扩展RAM, 内部扩展RAM(0x0~ 0x6ff)就浪费掉了, 我们无法去使用.
- 如果执行了InternalRAM_enable(), 0x400 ~ 0x6ff就是IAP15F2K61S2自己用的, 我们不能用.
- 如果执行了InternalRAM_enable(), 如果此时有物理上的外部扩展RAM, 超过0x700后, 会自动切到外部扩展RAM.
- 如果接了外部扩展RAM, 还是执行ExternalRAM_enable()好一些, 可以使用外部扩展RAM的0x400~0x6ff.
如果外接了外部扩展RAM, 会占用P0(全部IO), P2口(部分IO), 此时, 就不建议在P0和用到的P2IO(被XRAM用到的部分IO)上外接设备(e.g. 12864), 会引起访问xram失败(读的不是真正的XRAM地址的值, 设置的XRAM地址的值, 读回来也不正确, 使用C库函数(e.g. strlen, sprint, memset效果都不正确). 像51单片机, 外接RAM, 是挺不划算的. 如果真是RAM不够, 就要考虑使用ARM, RISC-V类型的单片机.