Keil 写 C51 是个大坑
0x00 是单片机课设
最近和同学在折腾单片机课的课设。我突发奇想的要用 LCD1602 做一个24点的游戏。虽然另一位小伙伴开始不太同意,不过最终还是确定了这个题目。经历了一个月的间歇性痛苦挣扎后,我们的作品终于初步完成了。
0x01 年轻人第一次做嵌入式
令人头痛的串行口驱动安装先略去不说,我们使用 Keil uVision4 和 C 来编写 STC89C52RC 的程序。STC89C52RC 有 512 bytes 的片内内存和 EEPROM 功能。开始我以为只要用C语言的程序就好了,然而在编写过程中却问题不断。
C 标准
Keil C51 以 ANSI C90 作为 C 标准。像 for (int i = 0; i < 5; i++)
这样的语句是不能写的。另外main
函数内部不能声明任何变量,都要把它们统统放到全局变量中。
残念的printf
我是属于面向printf
调试那一类的,然而在 C51 中,printf
被无情的剥夺了。毕竟单片机没有什么标准的输出设备。这对于我的程序调试是个不小的打击。所以我后来只能把其中可能有问题的部分复制出来,改成正常的 C 代码,编译调试。找到错误之后再改掉原来的 C51 代码。
扩展关键字
这里是让我最崩溃的地方了。Keil C51 有许多用于内存控制的扩展关键字,下面说一下让我头疼的两个关键字:
reentrant
这是由于我需要用到函数指针才碰到的问题。程序报错之后我上网搜索,很快发现了解决办法。虽然还是会有警告,但是程序的确正常执行了。
以下代码最后一行要添加 reentrant
才能在 Keil 中编译通过。
|
|
idata
这是最让我迷惑的关键词了。它的解释是:间接寻址,包括整个内部 RAM 区 00H~FFH。然而,它和某个令我抓狂的问题联系在了一起—— ADDRESS SPACE OVERFLOW。开始的时候我以为是程序太复杂内存不够用了,但现在看来并不是这样(因为 data=146.1)。原本我的程序中有一个函数有 7 层循环,无论我怎么改,程序就是会报 ADDRESS SPACE OVERFLOW 错误(各种地方都会)。后来在我把 7 层循环改为 4 层之后才能正常编译。
有时候加上idata
关键字会消除上面的问题,但有时候又会导致其他错误,包括程序显示不正常这种错误。所以说,现在我也还是没搞懂这里面的症结在哪。
贫瘠的标准库
标准库太少,连 time.h 都没有,想做个随机数就这么难吗?
以上有一部分参考了这里和这儿,里面有些对以上问题的深入解释。
0x02 完成了
虽然有这样那样的问题,甚至有几次想要放弃换题了。但是我们还是幸运的完成了~虽然还是存在许许多多的问题,不过已经可以称它为一款游戏了。
哒哒哒疯狂按键
我们采用了高逼格的游标选择模式,就像以前的功能机那样。虽然确实麻烦了一些,但是按起来很爽!
check your answer
内置强大的计算功能,能够对你输入的任何算式进行计算,检查你的结果是否正确!这里使用的是调度场算法。
那个 “Left!” 更是彰显了本组的英语水平(雾)。
哪里不会就多点几次
甚至内置了自动解题装置,在你算错之后再点击一次就可以查看正确答案了!
0x03 遗留的问题
- 随机数问题,由于随机数种子是固定的,每次题目也是固定的。
- 按键问题,有些按键不太灵敏或者容易连击。
- 选择模式问题,现有的游标选择模式较为繁琐,按键布局也需要改进。
- 小数问题,目前内部生成题目不会出现中间结果出现分数解法的题目。检查结果中间运算也都是整数。会出现
1 / 3 == 0
的问题。 - 全排列问题,现在生成的 4 个数字未经过打乱处理,缺少很多题目。