以做LED闪烁功能为例如何实现单片机软硬件分离一种简单方法
以做LED闪烁功能为例如何实现单片机软硬件分离一种简单方法
软硬件分离的思想本质是一种面向对象编程的思想
为什么要实现软硬件分离,这样做的好处是什么?
软件代码的重复利用,防止重复造论子
让专业的人干专业的事
可以让代码bug进一步减小
现在举一个例子详细阐明这一点
假设我们有一个充电宝,里面有四个灯,充电那一刻四个灯闪3秒然后熄灭,充电0.25一个灯亮,充电0.5两个灯亮,依次类推....
那么面向对象的如何思想这一个过程?
首先我们应该知道我们需要什么如何定义这样一个对象
对象 = 属性 + 方法
那么C语言如何实现这样一个过程:
首先定义两个函数指针,这个函数指针就是我们对象的方法:
typedef uchar (*gpio_init)(void); //方法一
typedef uint8_t (*gpio_function)(uint8_t gpio_port,uint8_t mode,uint8_t state); //方法二
方法一初始化GPIO有关的IO口
方法二LED的应该有哪些功能,这里我们传入三个控制参数(属性)分别是IO口,LED的闪烁模式,LED当前的状态。
下面我们构造一个这样的结构体:
typedef struct gpio_object{
uchar *gpio_port; //里面包含A11 B11 C11 D11 all_led 四个字符
uint8_t mode; //灯亮的模式
Uint16_t delay; //亮灭间隔多少毫秒
uint8_t count; //当前灯的状态持续多久
gpio_function gpio_app;
gpio_init gpio_inital;
} GPIO_OBJECT,*GPIO_OBJECT_PTR;
如何巧妙的设计一个简洁易用包含功能多变量少的结构体是新手与高手的分界线,好的结构体可以让编程更简单,代码更改量更少。
//实例化对象
GPIO_OBJECT s_gpio_object1;
//初始化对象
GPIO_OBJECT s_gpio_object1={
.gpio_port = ‘A11’,
.mode = 0,
.delay = 1000ms,
.count = 0,
.gpio_app = gpio_bsp_function,
.gpio_inital = gpio_bsp_init,
};
//方法一的实现
uchar gpio_bsp_init(void)
{
//gpio初始化
}
//方法二的实现
uint8_t gpio_bsp_function(uchar *gpio_port,uint8_t mode,uint16_t delay,uint8_t count)
{
//功能实现
}
以上都是跟硬件有关部分的代码?那么我们的上层应该如何使用我们的对象?
我们上层的代码是根据充电宝当前的电量来判断我们应该怎样闪烁?
Int main_app()
{
gpio_object1.gpio_inital(); //LED初始化
If(test插到了电源)
gpio_object1.gpio_app(“all_led”,1,1000,0.02min);
//所有的灯间隔1s闪烁
Switch(当前电量百分比处于哪范围)
Case 0.25
gpio_object1.gpio_app(“A11”,2,1000,1000min); break;
Case 0.5
gpio_object1.gpio_app(“A11”,2,1000,1000min); break;
Case 0.75
gpio_object1.gpio_app(“A11”,2,1000,1000min); break;
Case 1
gpio_object1.gpio_app(“A11”,2,1000,1000min); break;
Default: break;
}
这样做有什么好处呢?
假设项目经理突然改变需求,说我们的灯闪的功能形式太少了
大家想想: 我们只需要改变gpio_bsp_function的机制和 上层控制方式。 这样负责下层的人只需要多加个机制, 做上层的只需要gpio_object1.gpio_app(“A11”,2,1000,1000min); 这个函数的调用方法稍微改一下。 这就是软硬件分层的魅力!! 这样我们整个系统是一个耦合系统,每个部分之间通过参数联系在一起。不会出现一个地方出问题整个系统出问题。