0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

嵌入式C语言中结构体封装函数详解

CHANBAEK 来源:南山府嵌入式 作者:编外人员 2023-04-14 11:50 次阅读

说明:

嵌入式系统中,结构体封装函数可以用于对于嵌入式硬件资源进行抽象和封装,从而提高软件的可维护性和可移植性。 结构体封装函数通常包含数据和行为,并提供了对数据的访问和操作方法。

比如可以将硬件驱动函数封装在结构体中,方便对外提供统一的API接口,同时也便于代码的移植和扩展。 另外,结构体封装函数还可以用于实现状态机、任务调度等复杂的系统功能。

C语言中,结构体不仅可以封装数据,还可以封装函数指针。 这种方式可以用于实现回调函数、状态机等,提高代码的复用性和可维护性。 特别是在嵌入式当中,应用是非常多的。

结构体封装函数的作用:

  1. 将函数指针和参数打包成一个结构体,实现了代码的模块化和可复用性。
  2. 在结构体中可以定义多个函数指针,实现了对函数的分类管理和调用。
  3. 结构体可以作为函数的参数或返回值,传递和返回函数指针和参数。

结构体封装函数的应用:

  • 回调函数:将函数指针和参数打包成一个结构体,传递给API函数,在API函数内部执行该函数。
  • 状态机:将每个状态对应的处理函数封装成一个结构体,根据当前状态调用相应的处理函数。
  • 事件驱动:将事件处理函数封装成一个结构体,通过事件触发调用相应的处理函数。
  • 线程池:将任务处理函数封装成一个结构体,加入任务队列后由线程池调用执行

结构体封装函数的好处:

  • 更好的隐藏实现细节:结构体封装函数使得函数的实现细节被封装在结构体内部,只有结构体暴露给外部的函数指针,实现了良好的封装和信息隐藏。
  • 更加灵活的函数调用:函数指针可以被动态修改,从而实现动态的函数调用。 例如,在状态机中,根据不同的状态,可以将相应的处理函数指针赋值给一个函数指针变量,从而实现状态的转换和函数的调用。
  • 更加方便的扩展性:结构体封装函数可以轻松地添加新的函数指针,从而扩展功能。 在需要添加新功能时,只需要定义一个新的函数指针,并添加到结构体中,就可以实现功能的扩展,而不需要修改原有的代码。
  • 更加通用的代码:结构体封装函数可以使用于各种不同的编程范式,例如面向对象编程(OOP)和函数式编程(FP),从而实现通用的代码。 例如,在OOP中,结构体可以被看作是一个对象,函数指针可以被看作是对象的方法,从而实现OOP编程的思想。
  • 更加易于维护:结构体封装函数使得代码更加清晰、易于维护和修改。 由于函数指针的定义和使用都在结构体内部,因此修改或调整代码时,只需要修改结构体中的函数指针定义或调用方式,而不需要修改其他部分的代码,从而使得代码更加健壮、易于维护和修改
  • 模块化:通过结构体封装函数,可以将多个函数和数据结构组合成一个模块,以便于模块化设计和维护。 这种方法可以将代码的复杂性分解到不同的模块中,降低了代码的耦合性,提高了代码的可读性和可维护性。
  • 代码复用:结构体封装的函数可以通过传递结构体的方式重用同一个函数。 这种方式可以大大减少代码量,提高代码的复用性和可维护性。
  • 可扩展性:当需要增加新的功能时,只需增加新的函数和数据结构,而不需要修改现有代码。 这种方式可以大大减少代码的修改和调试时间,提高代码的可扩展性和可维护性。
  • 保护数据:通过结构体封装函数,可以将数据和函数封装在一个结构体中,防止外部代码对数据的非法访问和修改。
  • 提高安全性:将函数和数据封装在一个结构体中,可以防止其他函数对数据的非法操作,从而提高程序的安全性。

举例1

1/* 定义封装函数结构体由外部调用*/
 2typedef struct {
 3    int x;
 4    int y;
 5    void (*move_up)(int steps);
 6    void (*move_down)(int steps);
 7    void (*move_left)(int steps);
 8    void (*move_right)(int steps);
 9} Point;
10
11// 定义结构体中的函数
12void move_up(int steps) {
13    // 向上移动steps个单位
14    // ...
15}
16
17void move_down(int steps) {
18    // 向下移动steps个单位
19    // ...
20}
21
22void move_left(int steps) {
23    // 向左移动steps个单位
24    // ...
25}
26
27void move_right(int steps) {
28    // 向右移动steps个单位
29    // ...
30}
31
32int main() {
33    // 初始化结构体
34    Point point = {
35        .x = 0,
36        .y = 0,
37        .move_up = move_up,
38        .move_down = move_down,
39        .move_left = move_left,
40        .move_right = move_right
41    };
42
43    // 调用结构体中的函数
44    point.move_up(10);
45    point.move_right(5);
46
47    return 0;
48}

在上面的示例代码中,我们定义了一个结构体Point,其中包含了两个整型变量xy,以及四个函数指针move_upmove_downmove_leftmove_right。 每个函数指针指向一个移动函数,用于在平面坐标系中移动点的位置。 通过使用结构体封装函数,我们可以将函数和数据封装在一起,方便地进行操作和管理。

main()函数中,我们首先通过初始化的方式,将结构体中的成员变量和函数指针初始化。 然后,我们使用结构体中的函数指针,调用了move_up()move_right()函数,分别将点向上移动10个单位和向右移动5个单位。

值得注意的是,在实际应用中,我们需要根据实际情况修改函数的实现,以及结构体中的成员变量和函数指针的数量和类型。 同时避免滥用。

举例2

1typedef struct {
 2    void (*init)(void);
 3    void (*write)(uint8_t data);
 4    uint8_t (*read)(void);
 5} spi_t;
 6
 7void spi_init(void) {
 8    /* SPI初始化代码 */
 9}
10
11void spi_write(uint8_t data) {
12    /* SPI写入数据 */
13}
14
15uint8_t spi_read(void) {
16    /* SPI读取数据 */
17}
18
19int main(void) {
20    spi_t spi = {spi_init, spi_write, spi_read};
21
22    spi.init();
23    spi.write(0xAA);
24    uint8_t data = spi.read();
25
26    return 0;
27}

在举例2这个例子中,我们定义了一个spi_t类型的结构体,它包含了三个成员函数指针,分别对应SPI总线的初始化、写入和读取操作。 在main函数中,我们定义了一个spi结构体变量,并且初始化它的函数指针成员。 接下来,我们通过spi结构体变量的函数指针成员,分别调用了SPI总线的初始化、写入和读取操作。

使用结构体封装函数可以使代码更加清晰明了,减少了代码的冗余和重复,同时也方便代码的扩展和维护。

举例3

假设我们需要控制一个LED灯的亮度,可以使用PWM(脉冲宽度调制)技术来实现。 为了方便控制,我们可以使用一个结构体来封装控制LED灯的函数和变量。

1typedef struct {
 2    uint8_t duty_cycle;     // 占空比
 3    void (*set_duty_cycle)(uint8_t duty_cycle);  // 设置占空比的函数指针
 4    void (*start)(void);    // 启动PWM输出的函数指针
 5    void (*stop)(void);     // 停止PWM输出的函数指针
 6} pwm_control_t;
 7
 8// 设置占空比
 9void set_duty_cycle(uint8_t duty_cycle) {
10    // 设置占空比的代码
11}
12
13// 启动PWM输出
14void start_pwm(void) {
15    // 启动PWM输出的代码
16}
17
18// 停止PWM输出
19void stop_pwm(void) {
20    // 停止PWM输出的代码
21}
22
23int main(void) {
24    pwm_control_t pwm;
25
26    pwm.duty_cycle = 50;   // 设置占空比为50%
27    pwm.set_duty_cycle = set_duty_cycle;
28    pwm.start = start_pwm;
29    pwm.stop = stop_pwm;
30
31    pwm.set_duty_cycle(pwm.duty_cycle);  // 设置占空比
32    pwm.start();  // 启动PWM输出
33
34    while (1) {
35        // 循环执行其他任务
36    }
37}

在上面的代码中,我们定义了一个名为pwm_control_t的结构体,其中包含了一个占空比成员变量duty_cycle和三个函数指针set_duty_cyclestartstopset_duty_cycle函数用于设置占空比,start函数用于启动PWM输出,stop函数用于停止PWM输出。

main函数中,我们创建了一个pwm_control_t类型的结构体变量pwm,并分别给结构体的成员变量和函数指针赋值。 接着,我们调用了set_duty_cyclestart函数来设置占空比和启动PWM输出。

结构体封装函数的好处在于,我们可以通过创建不同的结构体变量来控制多个LED灯,而且不同的LED灯可以使用不同的PWM参数。 此外,如果需要修改PWM输出的实现方式,只需要修改startstop函数即可,而不需要修改每个LED灯。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    5068

    文章

    19008

    浏览量

    302919
  • 嵌入式系统
    +关注

    关注

    41

    文章

    3563

    浏览量

    129202
  • C语言
    +关注

    关注

    180

    文章

    7597

    浏览量

    136115
  • 函数
    +关注

    关注

    3

    文章

    4303

    浏览量

    62409
  • 结构体
    +关注

    关注

    1

    文章

    129

    浏览量

    10832
收藏 人收藏

    评论

    相关推荐

    C语言中数组和结构的内存表示和布局

    C语言中,数组和结构都可以代表一块内存,但为什么结构可以直接赋值,而数组不可以?这个问题涉及
    发表于 08-28 10:54 1447次阅读

    C语言入门书籍《嵌入式Linux C语言程序设计基础教程》全本下载!!

    的数据、数据的输入和输出、运算符和表达式、程序结构和控制语句。第6章到主要讲解了嵌入式Linux C语言中的数组,包括一维数组、多维数组、字符数组和字符串等。第7章主要讲解了
    发表于 03-02 17:09

    嵌入式C语言C语言的区别

    嵌入式C语言C语言的区别:最常用的系统编程语言C
    发表于 10-27 06:52

    嵌入式C语言结构设计_实验二

    主要介绍嵌入式C语言结构设计,从基础讲起,非常合适入门
    发表于 02-22 15:45 2次下载

    嵌入式C实现延时程序的不同变量的区别 几种Linux嵌入式开发环境的简单介绍

    嵌入式C实现延时程序的不同变量的区别 几种Linux嵌入式开发环境的简单介绍 ARM嵌入式开发基础 对话微软MVP:走进嵌入式软件开发 在
    发表于 04-14 07:24 1619次阅读
    <b class='flag-5'>嵌入式</b><b class='flag-5'>C</b>实现延时程序的不同变量的区别 几种Linux<b class='flag-5'>嵌入式</b>开发环境的简单介绍

    嵌入式C语言中如何判断数据是否损坏

    C语言中结构是非常有用的复合数据类型,正是有了结构C
    发表于 08-19 11:46 774次阅读
    <b class='flag-5'>嵌入式</b><b class='flag-5'>C</b><b class='flag-5'>语言中</b>如何判断数据是否损坏

    嵌入式C语言中的union语法的作用是什么

    C语言中结构语法是非常重要,也是非常有用的,相信看了最近几节的读者应该明白。事实上,在实际的C语言
    发表于 08-29 17:10 1835次阅读

    标准c语言嵌入式,嵌入式C语言C语言的区别

    嵌入式C语言C语言的区别:最常用的系统编程语言C
    发表于 10-20 14:06 6次下载
    标准<b class='flag-5'>c</b><b class='flag-5'>语言</b>与<b class='flag-5'>嵌入式</b>,<b class='flag-5'>嵌入式</b><b class='flag-5'>C</b><b class='flag-5'>语言</b>与<b class='flag-5'>C</b><b class='flag-5'>语言</b>的区别

    C语言嵌入式培训 嵌入式C语言程序设计基础

      学习嵌入式的基础语言C语言,因此先掌握C语言对于后续
    发表于 11-03 21:06 32次下载
    <b class='flag-5'>C</b><b class='flag-5'>语言</b><b class='flag-5'>嵌入式</b>培训  <b class='flag-5'>嵌入式</b><b class='flag-5'>C</b><b class='flag-5'>语言</b>程序设计基础

    嵌入式C语言知识总结

    了一些这方面的经验和思考,就希望总结下来,系统的阐述嵌入式C语言的重要知识点,就是这篇文章的由来。本文以自己在嵌入式上的实践为基础,在结合相关资料, 阐述
    发表于 12-20 19:44 12次下载
    <b class='flag-5'>嵌入式</b><b class='flag-5'>C</b><b class='flag-5'>语言</b>知识总结

    简单介绍嵌入式C语言中常用的位操作

    嵌入式C语言中,使用位操作程序有很好的可读性。以下就简单介绍以下常用的位操作。
    的头像 发表于 02-23 10:36 977次阅读

    嵌入式C语言中堆和栈的区别

    嵌入式C语言中,堆和栈都是用来存储变量的内存区域,但它们在存储和使用变量方面有很大的区别。
    的头像 发表于 04-14 11:45 1329次阅读

    嵌入式C语言结构封装函数说明

    嵌入式系统中,结构封装函数可以用于对于嵌入式硬件资源进行抽象和
    发表于 05-20 15:00 1037次阅读

    嵌入式C语言结构特点

    过程中,不论是基于寄存器开发还是基于库开发,深入理解和掌握嵌入式C语言函数、指针、结构是学习
    的头像 发表于 11-24 16:16 637次阅读
    <b class='flag-5'>嵌入式</b><b class='flag-5'>C</b><b class='flag-5'>语言</b>的<b class='flag-5'>结构</b>特点

    嵌入式系统中C语言结构的基础实现与应用

    C语言中的数组只能允许程序员定义存储相同类型数据。但是结构C语言编程中允许您存储不同数据类型的数据。
    发表于 03-12 14:29 430次阅读
    <b class='flag-5'>嵌入式</b>系统中<b class='flag-5'>C</b><b class='flag-5'>语言</b><b class='flag-5'>结构</b><b class='flag-5'>体</b>的基础实现与应用