文章目录
- STC - 同时外挂扩展RAM和12864时, C库函数失效的问题
- 概述
- 笔记
- 原理图 - 外挂XRAM
- 原理图 - 12864
- 错误现象
- 总结
- END
STC - 同时外挂扩展RAM和12864时, C库函数失效的问题
概述
在写STC15实验箱4的出厂测试程序.
发现memset(buf, 0, 256)一片256字节的xdata内存时, 无法将这片内存全部清0, 只清了不到0x20个字节.
其他标准C库函数e.g. sprintf, strlen 也不好使. 这咋玩啊?
后来通过换件法得知, 是外挂的32KXRAM和外挂的ST7920-12864都在使用P0和P2口引起的问题.
STC官方整出这样的原理图, 真是败笔.
怪不得我买的其他STC官方板子, 都没有焊接外挂RAM的芯片…
尝试分析和折中解决这个问题.
笔记
看看官方原理图关于外挂XRAM和ST7920-12864这块.
原理图 - 外挂XRAM
XRAM用到了P0, P2, P4.2, P4.4, P4.5,
原理图 - 12864
可以看到按照官方原有连接, 用到了P0, P2
如果是并口通讯, 就用到P0, P2
如果是串行通讯, 就用到P2
那理论上, 访问xdata时, 就会动到P0, P2.
那保不准12864的上的P0, P2就会不是高阻状态, 如果12864给了P0, P2新的值, 就会对xdata的访问造成错误.
错误现象
初始化外部RAM时, 开始用了 ExternalRAM_enable();
只使用外部RAM, 内部扩展RAM范围(0 ~ 0x6ff)不用.
当初始化buf时, 从memset可以看到, 只清了不到0x20个字节.
#define TMP_BUFFER_LEN 256
// ...
u8 xdata g_tmp_buf[TMP_BUFFER_LEN];
// ...
BUS_SPEED_1T(); //1T 2T 4T 8T 3V@22MHZ用1T会访问错误
ExternalRAM_enable(); // 只使用外部RAM, 不使用内部扩展RAM(0x0 ~ 0x6ff)
EA = 1;
my_memset(g_tmp_buf, 0, sizeof(g_tmp_buf));
现在只允许了外部RAM操作, 还没执行memest
将g_tmp_buf放到memory窗口中, 查看到的内容是随机的乱码.
单步进入my_memset, 观察清buf前后, g_tmp_buf在memory窗口中的内容差别.
步过C库函数 memset, 本来要清0x100个字节, 但是只清了不到0x20个字节.
将LCD-12864硬件摘掉, 再执行这个测试, 可以看到清掉了0x100个字节, memset是正常的.
这说明, 12864连接到P0, P2口时, 对xdata的访问是有影响的.
STC的资料上有说到, 如果使能内部扩展RAM:
当xdata地址小于0x6ff, 会使用内部扩展RAM.
当xdata地址大于0x6ff时, 会自动使用片外口扩展RAM.
尝试使能片内扩展RAM, 再试试memset操作.
可以看到, 是可以正常清掉xdata中定义的buf.
总结
如果外挂的12864和外扩的XRAM都使用P0, P2, 那一定是有冲突的.
如果是自己画的新板子, 可以考虑将12864用串行通讯, 将串口通讯用到的几个引脚用闲散的GPIO来代替, 然后使用SPI的方式来通讯.
如果是使用已有的板子(e.g. 买的或自己做的STC15实验箱4), 硬件没办法改. 此时只能是尝试使能内部扩展RAM.
当然, 如果xdata的地址超过0x6ff时, 还是会引起xdata操作失败.
如果非要使用32KB的外挂XRAM, 必须要摘掉12864.
如果非要使用12864, 那么XRAM就只能使用内部的扩展XRAM地址范围(0x0~0x6ff), 外部挂的32KBXRAM就没法用了.
因为STC使能内部扩展RAM后, 如果地址超出0x6ff, 就会自动使用外接的32KB的XRAM, 所以不需要特意执行ExternalRAM_enable().
ExternalRAM_enable()这个函数就是废的, 没有需求调用这个函数.