搜索
bottom↓
回复: 5

请教模块化中的接口如何实现更合理?

[复制链接]

出0入0汤圆

发表于 2014-1-10 11:49:39 | 显示全部楼层 |阅读模式
本帖最后由 sochen1987 于 2014-1-10 11:52 编辑

以串口为例子,如果我想做一个串口的硬件抽象层,接口怎么实现?请教各位看官.

意思是应用层使用串口,仅从硬件抽象层处耦合而无需关心具体的硬件平台.

我目前的做法是xxx.c, xxx.h, xxxcfg.h, 其中.c是实现(只读)和.h是声明(只读),通过xxxcfg.h(可读写) 靠宏来实现接口耦合.

中断回调的例子.
uart.c                                            uartcfg.h                                           hal_com.c                                          hal_comcfg.h
void Uart_Isr(void)                           #define UART_ISRCALLBACK \             void Hal_ComIsr(void)                          #define  HAL_COMISRCALLBACK
{                                                   Hal_ComIsr                                        {                                          
    UART_ISRCALLBACK;                                                                             HAL_COMISRCALLBACK;
}                                                                                                          }

我也见过有一种做法是通过一个xxximp.c来实现接口耦合.

有没有更合理的方法?

阿莫论坛20周年了!感谢大家的支持与爱护!!

阿莫论坛才是最爱国的,关心国家的经济、社会的发展、担心国家被别国牵连卷入战争、知道珍惜来之不易的和平发展,知道师夷之长,关注世界的先进文化与技术,也探讨中国文化的博大精深,也懂得警惕民粹主义的祸国殃民等等等等,无不是爱国忧民的表现。(坛友:tianxian)

出0入0汤圆

发表于 2014-1-10 12:49:19 | 显示全部楼层
发表一点个人观点,本人小白,我认为,抽象的概念,其实就是利用分层,降底底层的硬件和上层软件的耦合度,即使当更换平台,应用程序也不用更改,同样以串口为例,从用户的角度看,假如用户只是用普通的功能,我就应该为用户提供最为简单的接口,如:uart_write, uart_read等,这些接口简单,用户不需要关心你去检查了什么标志,也不关心FIFO是否满了,还是空了,而且不需要和寄存器打交道,这样就在无形中在用户的代码和底层寄存器之间加了一个门,用户并不需要知道门后面是什么东西,所以,我认为从用户的角度出发去设计模块的接口也许更合理些。
其实再细说一点,如果用户需要的只是一个通讯口,并且经常更换协议,那么就需要在增加一层,
比如定义一个宏:
#define WRITE(__DATA) \
        uart_write(__DATA)
那么即使当你更换的协议,也只需要更换这个宏定义,其他的代码基本不需要更改,本人水平有限,谢谢!!!

出0入296汤圆

发表于 2014-1-10 17:35:45 | 显示全部楼层
楼主不要从驱动开发人员的角度来设计这类接口,要从驱动使用人员的角度来考虑这类接口。
从开发人员的角度,你就会想,我要怎么处理中断,我要怎么处理系统时钟源之类;
从使用者角度,你只会想,我要一个发送接口和一个接收接口,然后一个配置接口可以设定
波特率之类的帧格式就足够了。再高档一点,可以有接收事件的处理程序注册接口和发送完成
事件的注册接口之类的。

你看完全不同。原则上说,让驱动开发人员去设计接口就好比 裁判员去踢球, 实际上最好的
应该是让驱动的用户去提出接口,然后和开发人员一起商量。但说实话,在这种商量的过程中
用户应该是最终说了算的。

如果你不幸驱动只有自己用……我只能说,呵呵……你看着办吧,如果你想把接口推广给别人用
什么时候推广,什么时候请用户来给你好好扶正扶正。

出0入0汤圆

 楼主| 发表于 2014-1-10 20:52:01 来自手机 | 显示全部楼层
Gorgon_Meducer 发表于 2014-1-10 17:35
楼主不要从驱动开发人员的角度来设计这类接口,要从驱动使用人员的角度来考虑这类接口。
从开发人员的角度 ...

恩,立场确实比较重要。有时候会混起来,因为又是设计者又是使用者。

出0入0汤圆

发表于 2014-1-10 22:03:47 | 显示全部楼层
之前看MDK 5.0自带的驱动,全部打包起来,封装N层进进出出,好麻烦.不过确实跨平台的很彻底.
这里照猫画虎来个简单的:

HAL层的对下接口UartDrv.C中:
typedef struct UART_Drv{
///Fields
UART_DrvType DrvInfo;
__IO U32 uartConf_1;
__IO U32 uartConf_2;
...
///Functions
bool *Config;
CallBackType *UartReceived;
CallBackType *UartSend;
CallBackType *UartTimeOut;
...
///Operation objects &attributes
U8 *ReadBuffer;
U8 *SendBuffer;
}UartDrvStructure;
里面每个字段,方法,对象都在C文件这里实现,实现不了的往底层走直接从底层包装方法上来.

HAL层的对上接口UartDrv.h就负责将C文件里面需要暴露的东西做成接口给上层用.


然后呢,user.c里面就是
UartDrvStructure USART2_Drv;(针对特定平台的HAL可以直接把这个USART2_Drv的内容固化下来成一个const的结构,然后再用typedef包装一层)
USART2_Drv.Config(*argument...);
USART2_Drv.UartSend(*string...);

最近在写C#,借鉴一下OO的思想,UartDrv就是一个完整的类,只写在C里面的就是privet的,写在H里面的就是public的,函数就是方法,静态方法和内部方法神马的不说,正常函数,但是属性和代理这些高级点的玩意都可以用CallBack实现,用以实现更灵活的方法.

出0入0汤圆

发表于 2015-2-1 15:54:28 | 显示全部楼层
hal的前缀用的很好
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-16 22:01

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表