一些说明:
Hardware.h作为公用头文件,它的作用主要是:
1.(一处)设置所选用的MCU,用以选择对应的 外设函数实现——因为它们含有一组统一的调用接口;
2.一些对应相应MCU下,一些共用的设置,比如说,基本数据类型的字长等——使得其上不再直接使用基本数据类型,如char,short等,而是U8,U16等,避免不同机器字长之间的区别,妨碍了程序的通用性和方便移植性。
外设头文件及其源文件(框架图中没有体现出 对应源文件)
以具体的gpio外设为例——注:此处的“外设”的定义用以区别“模块”。
仍以例子说明,比方说,对gpio的基本设置和读写操作,被认为是属于gpio外设的操作;
而使用gpio显示LED,读取按键,这种使用gpio完成的操作则认为是 使用了gpio外设的某某模块的操作;如此区分,是因为,gpio的读写和设置是对于任何在其之上的使用都需要的基本,更底层的操作。
首先,我们需要 重定义 一些数据类型。
因为stm8s采用了一套自己的 数据类型,比如gpio port,gpio pin的都有一个重定义的数据类型,而我们,如果要保证gpio对外有一套通用的数据接口,首先就保证一组通用的 数据类型。
见 文件中的 gpio.h,Line 20 ~ Line 25
类似的,还有,当然这是针对gpio这一个外设本身所独有的——也就是说,在我们做这些通用框架程序之前,我们一定要首先尽可能考虑(或者说在不断深入了解之后,不断完善)这个外设本身,有一些什么共性的内容,然后使它们对外保持一种通用的接口,或者宏定义。
比方说,gpio这个外设。
我们对它的基本操作无非是 设置方向(除了传统51,基本上任何一款MCU都有IO口读写方向的区分); 然后是,读io口状态;写io口状态;
于是,我们对应的需要 一组宏,表示不同的io口模式(方向包含在其中)——当然,你还可以有别的方式实现,比如stm的架构,直接用enum枚举结构体实现——但要注意的是,这次,stm架构是enum,那下次,如果换了430呢?如果是51呢?所以,在不甚明了的情况下,并且区别不大的情况下,我会选择宏定义。
又比如,目前,据我所知道,有两种给gpio/IO口编号的方法:
一种是 P0,P1,P2;
一种是PA PB PC(或者GPIOA GPIOB,应该是类似的。当然,跟其具体硬件的实现或者底层固件库的实现方法有关系。比如stm8s的,GPIOA GPIOB就是 结构体,但PIC的PA PB如何,我则不知道了。)
为了统一,我采取的办法是,PA(或者GPIOA)就对应P0,其他依次对应这个顺序——当然,后来我觉得,这种对应实际上,从我的实现方式来看,对应不对应并没太大关系,只看我怎么处理——但我保留这种方式,也许有一天我会想到更好的一一对应方便实现的办法,即使这种方法现在看不出非常明显的必要,但至少——逻辑上是更好的选择。
有了这个,我们还要考虑,如何定义一个引脚,因为它实际上,包含了两个信息,一个是port口,一个是pin口,从最一般的情况来看,我们在安排IO口时,它们可能是都不相同。
这里暂时没有想到更加好的办法,采用的办法仍然是先前提到的。
以带参宏 把一个GPIO口的port数和pin脚按照 8位一个port的组织方式换算出一个编号,再在调用时,反算出其所属的port口和pin脚。
具体代码 详见
gpio.h Line 45 ~ Line 48
在这里,我实际上没有想到更好地实现方法,目前采用的办法是switch开关切换选择对不同port口操作,因为stm8s这个GPIOA的结构体指针,实现起来真不如这个简单,而且速度指不定更优于结构体指针寻址方式。
实现方法,请参考 代码:
gpio.c的SetGpioMode()函数,或者WriteGpioPin()函数
gpio.c Line 70 ~ Line 133
目前做的工作只有这么多。
因为还不涉及具体模块,故而,直接在main.c中直接调用这些函数,以观察这种封装是否真的如愿实现。
main.c的内容作为试验代码。(Application Layer往往就只是一个main.c以及其他与其并行的中断函数而已。)
然后是我今天保存的 程序备份版本。
引用: samos2011 发表于 2015-8-6 20:56
楼主,3年过去了,技术进步到什么地步了啊?看好你!
引用: 辛昕 发表于 2015-8-7 11:21
刚扯了一通,也许你要的并不是这个问题方面的 “进展”。
我想一般点地说就是。这几年的进步主要体现在
...
引用: hb1012 发表于 2012-6-20 17:11
谢谢版主分享,刚转到开发部门,软件架构以及如何编写比较茫然!有待进一步学习,另外一个帖子看到版主下载 ...