一种嵌入式程序的模块设计规范
??
嵌入式程序中,有时一个功能模块的使用会跨越多个物理器件。比如DDS芯片9837至少会用到SPI和GPIO。对于这种情形,最简单的做法是直接将所用到的物理寄存器包含在这个模块内部,写死。这样做没有什么问题,但是这样写,系统本身的逻辑代码和物理寄存器读写代码纠缠在一起,可读性和可移植性都不好。
我们下面以代码实例展示一下: #ifndef GPIO_H #define GPIO_H #define MAX_CHANNEL 4 //回调函数 typedef void (*FUN_STD_GPIO)(void); typedef int (*FUN_CHK_GPIO)(void); typedef int GPIO_CH; //GPIO子系统初始化 void GPIO_Init(void); //GPIO通道初始化 int GPIO_Register(FUN_STD_GPIO fn_init,FUN_STD_GPIO fn_on,FUN_STD_GPIO fn_off,FUN_CHK_GPIO fn_is_on); //GPIO开启 void GPIO_On(GPIO_CH ch); //GPIO关闭 void GPIO_Off(GPIO_CH ch); //GPIO切换 void GPIO_Toggle(GPIO_CH ch); 上面的代码是gpio.h定义的GPIO器件的注册和访问接口。下面是源代码部分: #include "gpio.h" typedef struct _GPIO_CH_DESC { FUN_STD_GPIO init; FUN_STD_GPIO on; FUN_STD_GPIO off; FUN_CHK_GPIO is_on; }GPIO_CH_DESC,*PGPIO_CH_DESC; GPIO_CH_DESC gGpioCh[MAX_CHANNEL]; int gGpioNextCh = 0; //GPIO子系统初始化 void GPIO_Init(void) { } //GPIO通道初始化 int GPIO_Register(FUN_STD_GPIO fn_init,FUN_CHK_GPIO fn_is_on) { if(gGpioNextCh >= MAX_CHANNEL) return -1; gGpioCh[gGpioNextCh].init = fn_init; gGpioCh[gGpioNextCh].on = fn_on; gGpioCh[gGpioNextCh].off = fn_off; gGpioCh[gGpioNextCh].is_on = fn_is_on; fn_init(); return gGpioNextCh++; } //GPIO开启 void GPIO_On(GPIO_CH ch) { if(ch>=0 && ch<gGpioNextCh) gGpioCh[ch].on(); } //GPIO关闭 void GPIO_Off(GPIO_CH ch) { if(ch>=0 && ch<gGpioNextCh) gGpioCh[ch].off(); } //GPIO切换 void GPIO_Toggle(GPIO_CH ch) { if(ch>=0 && ch<gGpioNextCh) { if(gGpioCh[ch].is_on()) gGpioCh[ch].off(); else gGpioCh[ch].on(); } } 可以看到,上面的代码中未出现任何与寄存器读写相关的内容。因为寄存器读写涉及到具体寄存器操作,与GPIO这个接口层定义是无关的。 下面是一个具体的GPIO接口定义,首先是头文件: #ifndef GPIO_PIN80_H #define GPIO_PIN80_H //特定通道 extern int GPIO_PIN80; //初始化GPIO_PIN80模块; void GPIO_PIN80_Init(void); #endif 头文件中仅包含一个通道句柄,定义了一个特定管脚PIN80对应的GPIO通道号;以及一个初始化函数,初始化函数中不涉及任何与GPIO接口初始化相关的知识,这些东西仅对制作这个小模块的模块作者是可见的,对用户是隐藏的。最后是这个小模块的实现函数: #include "LPC17xx.h" #include "gpio.h" #include "gpio_pin80.h" int GPIO_PIN80 = -1; void GPIO_PIN80_Init_Inner(void); void GPIO_PIN80_On(void); void GPIO_PIN80_Off(void); int GPIO_PIN80_IsOn(void); void GPIO_PIN80_Init(void) { GPIO_PIN80 = GPIO_Register(GPIO_PIN80_Init_Inner,GPIO_PIN80_On,GPIO_PIN80_Off,GPIO_PIN80_IsOn); } void GPIO_PIN80_Init_Inner(void) { LPC_PINCON->PINSEL0 &= (~((0x11)<<10)); //pin80. p0.5 gpio LPC_GPIO0->FIODIR |= (1<<5); GPIO_PIN80_On(); } void GPIO_PIN80_On(void) { LPC_GPIO0->FIOCLR |= (1<<5); } void GPIO_PIN80_Off(void) { LPC_GPIO0->FIOSET |= (1<<5); } int GPIO_PIN80_IsOn(void) { return (LPC_GPIO0->FIOPIN & (1<<5)) ? 0 : 1; }
//... GPIO_PIN80_Init(); //... while(1) { GPIO_Toggle(GPIO_PIN80); //... }It'sbeautiful,right? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |