在V-USB中(也就是以前的AVRUSB)中,我们可以看到有新的一些宏使用方法,非常独特。例如在文件hardware.h中,定义端口的方式是:
#define HWPIN_ISP_RESET B, 0
#define HWPIN_ISP_MOSI B, 3
#define HWPIN_ISP_MISO B, 4
#define HWPIN_ISP_SCK B, 5
这样做有什么好处呢?在前面的一篇Blog中,我们可以看到每种MCU的IO都是由几个寄存器进行控制的。在程序移植时,如果修改一个端口,就需要同时将对应的几个寄存器都进行修改,这样就比较麻烦,特别在需要修改的IO比较多,或者程序直接引用的地方比较多的时候,比较容易出错。使用宏就可以比较好的解决这个问题。在V-USB的文件utils.h中,我们可以看到下面的宏定义:
#define UTIL_CONCAT(a, b) a ## b |
调用时方式如下:
PORT_DDR_SET(HWPIN_ISP_SCK); /* enable programming I/O pins */
PORT_DDR_SET(HWPIN_ISP_MOSI);
PORT_DDR_SET(HWPIN_ISP_RESET);
timerTicksDelay(ispClockDelay); /* stabDelay may have been 0 */
PORT_PIN_SET(HWPIN_ISP_RESET); /* give positive RESET pulse */
如果把宏替换,上面的语句就是
DDRB |= (1 << 5);
DDRB |= (1 << 3);
DDRB |= (1 << 0);
PORTB |= (1 << 0);
其实和以前的写法没有什么区别。但是这样的好处也很明显,在移植程序时,只需要修改IO的定义,不需要手工修改相关寄存器了,减少了移植时的难度,降低了代码维护量。缺点是代码看起来有些复杂,类似伪代码。
在其他MCU中,我们也可以使用类似的方法。下面是我将这种方法移植到MSP430的代码,基于IAR5.10开发环境。
#define LEDRED P1, 0
#define LEDGREEN P1, 6
#define PIN_INPUT 0
#define PIN_OUTPUT 1
#define MC_ARG1(a, b) a
#define MC_ARG2(a, b) b
#define MC_CON_CAT(a, b) a##b
#define MC_CONCAT(a, b) MC_CON_CAT(a, b)
#define MSP_PINDIR(PIN) MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), DIR_bit.), MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), DIR_), MC_ARG2(PIN)))
#define MSP_PININ(PIN) MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), IN_bit.), MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), IN_), MC_ARG2(PIN)))
#define MSP_PINOUT(PIN) MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), OUT_bit.), MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), OUT_), MC_ARG2(PIN)))
#define MSP_PINREN(PIN) MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), REN_bit.), MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), REN_), MC_ARG2(PIN)))
#define MSP_PINSEL(PIN) MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), SEL_bit.), MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), SEL_), MC_ARG2(PIN)))
#define MSP_PINIE(PIN) MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), IE_bit.), MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), IE_), MC_ARG2(PIN)))
#define MSP_PINIES(PIN) MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), IES_bit.), MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), IES_), MC_ARG2(PIN)))
#define MSP_PINIFG(PIN) MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), IFG_bit.), MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), IFG_), MC_ARG2(PIN)))
#define MSP_PINIFGSET(PIN) MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), IFG_bit.), MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), IFG_), MC_ARG2(PIN))) = 1
#define MSP_PINIFGCLR(PIN) MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), IFG_bit.), MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), IFG_), MC_ARG2(PIN))) = 0
#define LEDON(PIN) MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), OUT_bit.), MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), OUT_), MC_ARG2(PIN))) = 1
#define LEDOFF(PIN) MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), OUT_bit.), MC_CONCAT(MC_CONCAT(MC_ARG1(PIN), OUT_), MC_ARG2(PIN))) = 0
MSP_PINDIR(LEDRED) = 1;
MSP_PINDIR(LEDGREEN) = 1;
LEDON(LEDRED);
LEDOFF(LEDGREEN);
附件中是完整的例子,基于TI的LaunchPad开发板和MPS430G2231:
文章评论(0条评论)
登录后参与讨论