好久没更帖子了,写这篇帖子有点底气不足,毕竟没有太深厚的内力(功底),算是借鉴心法总纲出来抛砖引玉吧,希望给道友们打开一片新的世界。
第一个疑惑点:单片机大部分情况下都是使用C语言进行开发,虽然IDE也支持C++,但是真正要用到C++的几乎微乎其微,提起面向对象,脑子里第一个词可能就是:C++。其实告诉你一个小秘密,linux操作系统绝大部分都是用C语言开发的,同样应用了大量的面向对象的设计,也就是说,C语言的威力可能超乎我们的想象。
本篇帖子是以RT-thread中设备IO驱动框架的实现为例子(心法总纲)来聊一聊单片机的中分层技术和面向对象:
上图是设备管理层的构架图(分层思想一目了然),面向对象的类与继承应用最多,这里我们只关注设备驱动框架层以下的三层,因为用到的是pin设备,比较特殊,她并没有应用I/O设备管理层。
其实设备驱动的核心就是抽象出了一个设备对象,一切都围绕着设备驱动对象展开,pin设备抽象类(结构体实现)如下:
Pin设备对象的定义如下:static struct rt_device_pin _hw_pin;
这里定义了一个设备实例,但是没有对实例对象初始化,还无法具体的操作,因为其内部结构体成员为空。
接下来需要进行关键的一步,就是设备实例的初始化。
以下函数中进行hw_pin设备实例的初始化:
关键的在于调用rt_device_pin_register函数,这个函数来自于设备驱动框架层,其中hw_pin对象也来自于设备驱动框架层。
输入参数有注册设备名称”pin”,设备操作函数结构体指针_stm32_pin_ops,这两个参数,通过上层注册函数将hw_pin对象与底层的设备的操作函数建立联系。
关于_stm32_pin_ops的结构体(其实C语言中的结构体,在面向对象中可以看作是类,结构体与实例,对应于类与对象的概念)原型如下:
接下来看一下rt_device_pin_register函数:
_hw_pin的parent成员是device类型对象,pin设备并没有用到设备管理层API ,而是直接用的设备驱动框架层提供的API函数:
主要有以下几个:
void rt_pin_mode(rt_base_t pin, rt_base_t mode); //设置引脚模式
void rt_pin_write(rt_base_t pin, rt_base_t value); //引脚电平输出设置
int rt_pin_read(rt_base_t pin); //引脚电平输入读取
设备对象注册函数rt_device_register(&_hw_pin.parent,name,RT_DEVICE_FLAG_RDWR);完成了对象管理器相关的注册(实际是链表相关的操作):
执行之后,当系统运行起来以后,我们可以在shell命令窗口输入list_device命令,查看系统当前所有的设备,会发现我们的设备成功注册:
到这里,扔出来的砖就结束了,其实很想能够将自己想表达的东西传递给大家,但是读完写的帖子又总觉得差强人意,如果筒子们对嵌入式软件感兴趣,一定要尝试着去玩玩RTT,她会带给你很多意想不到的收获,底子扎实的又有机会的可以直接晋级嵌入式linux领域(其实多数RTOS都是linux的皮毛,学术角度,当然各有所长),她不止能带给你高大上的赶脚: