ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

面向对象编程基础

2022-02-25 23:03:03  阅读:169  来源: 互联网

标签:面向对象编程 PIN read void 基础 int key GPIO


RTOS嵌入式系统框架进阶

第一章 嵌入式常用裸机编程框架
第二章 面向对象编程基础


文章目录


前言

学习韦东山老师的七天物联网实战及直播课相关内容,以其课程笔记为骨,记录一下学习的过程,可能会加入一些自己的感想。
最后欢迎点赞、收藏与评论交流!


面向对象的总体思想来源《代码大全》的第5章,他把程序设计分为这以下几个层次:

  • 第1层:软件系统,就是整个系统、整个程序
  • 第2层:分解为子系统或包。比如我们可以拆分为:输入子系统、显示子系统、业务系统
  • 第3层:分解为类。在C语言里没有类,可以使用结构体来描述子系统。
  • 第4层:分解成子程序:实现那些结构体(结构体中有函数指针)。

为了方便阅读,本文从底层开始介绍代码,由底向上进行介绍,这样更方便阅读。本文主要介绍第4层与第3层的内容。


1、未使用面向对象编程的程序

1.1、库函数编程

以按键为例进行说明:

硬件原理图

以下代码实现以下功能,key值代表是否按下按键PF6。如果按下按键,就点亮LED灯;若没有按下按键,则关闭LED。

void main(void)
{
    GPIO_PinState key;
    while (1)
    {
        key = HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_6);
        if (key == GPIO_PIN_RESET)
            HAL_GPIO_WritePin(GPIOF, GPIO_PIN_5, GPIO_PIN_RESET);
        else
            HAL_GPIO_WritePin(GPIOF, GPIO_PIN_5, GPIO_PIN_SET);
    }
}

但这样写代码有明显的缺陷:

  • 需要结合原理图、需要有硬件知识
  • 很难进行今后的代码维护和扩展

1.2、使用子函数

为了使自己的代码尽量远离硬件知识,我们在程序中加入大量的子函数。这样预留的API可以大大提高程序的可阅读性。方便以后自己代码的扩展,也方便与上层的算法人员进行代码的交流。

// main.c
void main(void)
{
    int key;
    while (1)
    {
        key = read_key();
        if (key == UP)
            led_on();
        else
            led_off();
    }
}

// key.c
int read_key(void)
{
    GPIO_PinState key;
    key = HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_6);
    if (key == GPIO_PIN_RESET)
        return 0;
    else
        return 1;
}

// led.c
void led_on(void)
{
    HAL_GPIO_WritePin(GPIOF, GPIO_PIN_5, GPIO_PIN_RESET);
}

void led_off(void)
{
    HAL_GPIO_WritePin(GPIOF, GPIO_PIN_5, GPIO_PIN_SET);
}

但此时我们仅完成了

第4层:分解成子程序:实现那些结构体(结构体中有函数指针)。

当程序中包含特别多的子函数时,有串口的,LED灯的,按键的,CAN口、SPI等等,这时候大量的子函数放到一起就会很头痛,因此我们想要将一些功能相似的函数耦合起来,这样更上一层楼到进到第三层:

  • 第3层:分解为类。在C语言里没有类,可以使用结构体来描述子系统。

2、使用面向对象编程的程序

面向对象编程的基础是结构体与函数指针,因此在本节中我们先对函数指针和结构体进行介绍。

2.1、 函数指针

指针是C语言的灵魂,是必须掌握的内容,在此我先进行简单的介绍,如果后期看的人多并且点赞多的话,我会写专门的文章进行说明。

指针的基本概念是指向地址的变量,而指针也有相应的类型:例如int *P表示的是指针,并且大小为4个字节的内存的内容。其他数据类型有类似的效果。

而函数指针代表的是指向函数入口的指针变量,通过调用指针就可以找到函数入口,从而实现函数的调用。

假如有两个版本的按键读取函数,通过函数指针来确定哪一个使用哪一个版本的代码,代码如下(示例):

int (*read_key)(void);

// 返回值: 0表示被按下, 1表示被松开
int read_key_ver1(void)
{
    GPIO_PinState key;
    key = HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_5);
    if (key == GPIO_PIN_RESET)
        return 0;
    else
        return 1;            
}

// 返回值: 0表示被按下, 1表示被松开
int read_key_ver2(void)
{
    GPIO_PinState key;
    key = HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_6);
    if (key == GPIO_PIN_RESET)
        return 0;
    else
        return 1;            
}

void key_init()
{
    int ver = read_hardware_ver();// 读取硬件版本,版本1读PF5,版本2读PF6
    if (ver == 1)
        read_key = read_key_ver1;
    else
        read_key = read_key_ver2;
}

// main.c
void main(void)
{
    int key;
    
    key_init();
    
    while (1)
    {
        key = read_key();
        if (key == UP)
            led_on();
        else
            led_off();
    }
}

2.2、 结构体

面向对象的初衷是为了解决一类问题,因此要解决的是一类问题,即:
- 第3层:分解为类。在C语言里没有类,可以使用结构体来描述子系统。
在本文中就是要表达所有的按键处理函数。

本例中代表一个系统共有两个按键,通过结构体的表述代码如下所述(示例):

// key.c
// 返回值: 0表示被按下, 1表示被松开
int read_key(int which)
{
    GPIO_PinState key;
    switch (which)
    {
        case 0:
			key = HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_6);
            if (key == GPIO_PIN_RESET)
                return 0;
            else
                return 1;
            break;
            
        case 1:
			key = HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_7);
            if (key == GPIO_PIN_RESET)
                return 1;
            else
                return 0;
            break;
            
    }
}

该方法在小的系统代码中使用较多,但是不太容易进行扩展,如果想要加K3的话仍然需要再写一个case分支。

改进方法是通过结构体进行函数的编写,在结构体中包含指针函数的成员,这样关于按键的操作基本都被一个结构体所包含了。具体过程如下所述:

定义一个结构体变量代码示例如下:

typedef struct key {
	char *name;
    void (*init)(struct key *k);
    int (*read)(struct key *k);
}key, *p_key;

每个按键都实现一个key结构体:

// key1.c
key k1 = {"k1", NULL, read_key1};

// key2.c
key k2 = {"k2", NULL, read_key2};

// key_net.c
key k_net = {"net", NULL, read_key_net};

总结

本文主要讲述了子函数、指针函数和结构体体的内容,主要完成的是代码第3和第4层的内容;

  • 第3层:分解为类。在C语言里没有类,可以使用结构体来描述子系统。
  • 第4层:分解成子程序:实现那些结构体(结构体中有函数指针)。

为接下来的代码分层打下基础,在下一篇文章中我们将主要介绍第2和1层的内容。如有不清楚的,欢迎提问或指出错误。

标签:面向对象编程,PIN,read,void,基础,int,key,GPIO
来源: https://blog.csdn.net/gudao07/article/details/123128080

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有