代码的移植性问题
(1)用宏定义代替直接IO操作
我觉得最典型的例子就是蜂鸣器,4KHZ驱动的交流蜂鸣器,如果蜂鸣器接在 P50 口,那么驱动的代码就应该是:
mov a,@0x01
xor 0x05,a
代码很简单,0x01 和 P5口异或出来的结果,就是 P50 口取反,不断的取反那么得到的是 P50 口输出方波,用C语言来描述就是:
PORT5 ^= 0x01
好了,这个代码的移植性超级差,如果我的蜂鸣器现在需要修改到 P62口,那么代码也必须相应的修改为:
mov a,@0x04
xor 0x06,a
当然了,我们这里只需要一处,还不见得麻烦,如果你的代码中有50处,乃至100处需要修改,我想你肯定要抓狂。所以这种不可移植的代码必须扔掉。
修改版1:
通过定义蜂鸣器的IO口来处理
buz_port EQU 0x05
mov a,@0x01
xor buz_port,a
这里用 buz_port 这个名字代替了蜂鸣器的输出端口,那么现在移植性有了提高,如果修改了端口的话,我们只需要重新定义 buz_port 这个宏,就完成了对代码的所有的修改。
按照上面的描述,能解决了端口的问题,但是我们发现,问题还没有完全解决,mov a,@0x01 我们还得手工计算蜂鸣器在哪个引脚上面,而且还得在一个一个的修改,所以还需要改进。
修改版2:
buz_port EQU 0x05
buz_pin EQU 0
mov a,@1 xor buz_port,a 这个代码就真正实现了所谓的移植性。用C语言来解释一下 buz_port ^= 1 如果C语言过关的同学应该对这个表达式很熟悉了。1 例如 1<0 得到的结果是 1 (00000001b) 1<3 得到的结果是 8 (00001000b) 道理是这样,但是使用起来一点也不负责,可以说是很好用。可以直接和IO的名字对应起来,例如前面说的 P62 的话,那么定义就应该为: buz_port EQU 0x06 buz_pin EQU 2 只需要修改一下定义,程序当中所有使用了这个IO口的部分都不需要修改,这样移植性就非常好了。这个技巧虽然简单,但是是必须学会的。 (2)动态绑定IO口 思考一种情况,我们使用 3个IO口分别发不同占空比的PWM,驱动3个不同颜色的LED发光,形成彩灯效果。要求就是3个IO口独立控制,那么很自然的想法就是,3段程序,每一段程序都生成PWM,也就是说将1路的情况扩展到3路,分别控制。但是寄存器的消耗和ROM的消耗也相对应的变成了3倍,这是很好理解的。但是3段程序惊人的类似,很可能只是IO口输出部分修改了一下,我们思考,时候可以合在一起写呢?也就是说,用1个PWM程序生成PWM,分别输出到3个不同的IO口,我建议,在看下去之前先自己思考一下,敲一下程序,就能很深刻的理解到这个问题的难点。 类似的情况也不少见,例如RC测温,如果测1路的话很好办,但是如果测很多路呢?你不会真的需要将每一路都一份对应的程序吧?那绝对不可能,处理的办法类似,也就是说,用一个程序处理多个IO的输入数据,切换。这有点类似数字电路里面的数据选择器。 答案是:动态绑定IO口输入输出,途径是R0和R4配合的间接寻址。怎么实现?其实很简单,因为间接寻址本身能访问地址 0x05 和 0x06 ,也就是能直接访问 PORT5 和 PORT6 ,这样就很容易联想到,例如 PORT6 口输出状态,然后 PORT6 的输出状态修改为 0X0F (P60~P63高电平,P64~P67低电平)一般的做法是: mov a,@0x0f mov PORT6,a 如果通过间接寻址的办法,那么就是 mov a,@0x06 mov R4,a mov a,@0x0f mov R0,a 首先将要访问的寄存器地址 0x06放到地址寄存器 R4,然后将数据 0x0f 送到 R0中,那么实际的效果就是将 0xf 送到 PORT6 当中,用仿真器跑一下就OK了,很简单的。 懂了这个原理之后,那么所谓的“动态绑定”就很容易理解了,将原来用 PORT5 PORT6访问IO口的指令,变成用 R0 R4 间接寻址来访问,这样程序就可以变得很灵活。 例如有用回之前的那个蜂鸣器的例子 系统有两个蜂鸣器,P50和P62,那么下面看看怎么通过动态绑定将方波分别输出到这两个蜂鸣器当中。 分配两个寄存器,分别保存当前需要操作的端口信息。 REG_PORT == 0x10 REG_PIN == 0x11 假如当前需要对 P50输出 Mov a,@0x05 Mov REG_PORT,a Mov a,@1 Mov REG_PIN,a 那么蜂鸣器的驱动函数就应该做相应的修改,前面说了,原来是直接对PORT口操作,现在变成间接寻址 Mov a,REG_PORT Mov R4,a Mov a,REG_PIN Xor R0,a 可以理解么?其实很简单,首先确定当前需要操作的端口,前面设定了REG_PORT的值为0x05,也
代码移 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)