我们学习MCU开发,大部分都是面向过程的开发,但实际项目一般要求我们有面向对象(模块化)的方式来开发。

刚学习C语言开发的朋友,应该常常听说面向对象,但实际对于面向对象开发可能还是不太了解。

为了初学者进一步理解,本文结合实际项目(LEDs状态灯)给大家带来比较基础的模块化设计。

关于C语言的模块化

对于MCU的开发,大部分人都还是习惯性用的C语言,原因之一在于C语言具有高效的特点。

可以了解一下,许多操作系统的内核使用的编程语言,其实都用到了C语言,这就是C语言的优点,也是C语言这么多年不衰败的原因。

说回来,对于MCU的开发,除了C语言,当然还可以其它语言,像C++有许多人就用上了。

C++语言本身就是面向对象的开发语言,定义一个类,可以包含许多成员。站在C语言的角度,可以理解成定义一个结构体,里面包含许多数据类型。 如下面要说的LEDs数据结构体:

typedef struct
{uint8_t  Mode;                  //模式(常灭 常亮 闪烁)uint8_t  Status;                //当前状态(灭 亮)uint16_t OffTimes;              //灭时间(xLED_COUNT_PERIOD毫秒)uint16_t OnTimes;               //亮时间uint16_t Counter;               //计数(计时)void (*OffFun)(void);           //灭函数接口void (*OnFun)(void);            //亮函数接口
}LED_TypeDef;

可以看到,结构体里面包含整型变量,函数指针。

补充,指针函数与函数指针的区别

1、指针函数:本质是一个函数,函数返回类型是某一类型的指针。

格式:  类型标识符    *函数名(参数表)

如:int *f(x,y);

2、函数指针:本质是一个指针,指向函数的指针变量。

格式:类型说明符 (*函数名)(参数)

如:int (*f) (int x);

为什么要模块化设计

假如一个系统中做的事情非常多,比如:采集两个增量式编码器、两个绝对值编码器、控制4个电机、控制多个LED状态灯、通信收发数据,采集温度、湿度、超声波雷达等···许多模块,那么问题来了,这么多模块,你的软件该如何设计

答案就是需要模块化设计。

模块化设计,包含底层驱动,中间接口函数,应用程序等。对于MCU级别的开发,为了规范,建议大家从底层设计到应用层设计都按照模块化的方式来设计。

简单的来说,模块化就是源文件、数据结构、变量、函数命名等需要按照模块的方式来设计。比如LEDs状态灯:IO口的定义用LED(模块),文件名用led,变量、函数名抬头用LED,定义一个LED数据结构(模块的数据结构)等。

模块化的设计优点在于:便于源代码管理、移植、理解等等。(相信有许多自己写的代码,放一段时间之后,重新再次阅读,可能看了半天都不明白源代码的意思。)

LEDs实例讲述

为方便大家理解,拿一个简单的LEDs状态灯的实例来分析。里面使用到了RTOS简单系统延时(本文不讲述关于RTOS的知识)。文末提供例程下载地址。

1.描述

绿、黄、红三个(可以自己添加许多个)LED状态灯,可独自实现常灭、常亮、闪烁三个模式。

闪烁:灭、亮时间可设置(提供函数接口修改)。

在一个线程(任务)里面执行。

3个LED不同亮灭时间效果

2.数据结构

typedef struct
{uint8_t  Mode;                  //模式(常灭 常亮 闪烁)uint8_t  Status;                //当前状态(灭 亮)uint16_t OffTimes;              //灭时间(xLED_COUNT_PERIOD毫秒)uint16_t OnTimes;               //亮时间uint16_t Counter;               //计数(计时)void (*OffFun)(void);           //灭函数接口void (*OnFun)(void);            //亮函数接口
}LED_TypeDef;

为了方便理解,只使用一个数据结构(实际大的项目可能有多个包含,类似C++继承关系)。

3.底层LED函数接口

void LEDGreen_Off(void);

void LEDGreen_On(void);

void LEDYellow_Off(void);

void LEDYellow_On(void);

void LEDRed_Off(void);

void LEDRed_On(void);

主要就是亮灭函数接口,这里提供三组LED(根据需求可添加)。

4.定义局部变量

static LED_TypeDef sLEDG_Structure;              //绿灯
static LED_TypeDef sLEDY_Structure;              //黄灯
static LED_TypeDef sLEDR_Structure;              //红灯

5.初始化变量

/************************************************
函数名称 : LED_Data_Init
功    能 : 数据初始化
参    数 : 无
返 回 值 : 无
作    者 : strongerHuang
*************************************************/
static void LED_Data_Init(void)
{/* 绿灯 */sLEDG_Structure.Mode = LED_MODE_FLICKER;       //初始化为闪烁sLEDG_Structure.OffTimes = 50;                 //灭亮时间sLEDG_Structure.OnTimes = 50;sLEDG_Structure.Counter = 0;                   //计数归零sLEDG_Structure.OffFun = LEDGreen_Off;         //灭函数接口sLEDG_Structure.OnFun = LEDGreen_On;           //亮函数接口/* 黄灯 */sLEDY_Structure.Mode = LED_MODE_ON;            //初始化为常亮sLEDY_Structure.OffTimes = 0;                  //灭亮时间sLEDY_Structure.OnTimes = 0;sLEDY_Structure.Counter = 0;                   //计数归零sLEDY_Structure.OffFun = LEDYellow_Off;        //灭函数接口sLEDY_Structure.OnFun = LEDYellow_On;          //亮函数接口/* 红灯 */sLEDR_Structure.Mode = LED_MODE_ON;            //初始化为常亮sLEDR_Structure.OffTimes = 0;                  //灭亮时间sLEDR_Structure.OnTimes = 0;sLEDR_Structure.Counter = 0;                   //计数归零sLEDR_Structure.OffFun = LEDRed_Off;           //灭函数接口sLEDR_Structure.OnFun = LEDRed_On;             //亮函数接口/* 对外调用接口(例子) */LEDG_Set(LED_MODE_FLICKER, 50, 50);LEDY_Set(LED_MODE_FLICKER, 50, 10);LEDR_Set(LED_MODE_FLICKER, 20, 30);
}

这里重要的就是要初始化灭亮函数接口。

6.LEDs任务(线程)

/************************************************
函数名称 : LED_Task_Proc
功    能 : 状态灯任务程序
参    数 : pvParameters --- 可选参数
返 回 值 : 无
作    者 : strongerHuang
*************************************************/
static void LED_Task_Proc(void *pvParameters)
{static TickType_t xLastWakeTime;xLastWakeTime = xTaskGetTickCount();  for(;;){//间隔固定计数周期(采样时间)vTaskDelayUntil(&xLastWakeTime, LED_COUNT_PERIOD);    /* 浏览LEDs */LED_Scan(&sLEDG_Structure);LED_Scan(&sLEDY_Structure);LED_Scan(&sLEDR_Structure);}
}

流程图:

7.LED浏览(或者说处理)

/************************************************
函数名称 : LED_Scan
功    能 : 状态灯扫描(修改状态)
参    数 : LED_Struct --- 状态灯数据结构
返 回 值 : 无
作    者 : strongerHuang
*************************************************/
static void LED_Scan(LED_TypeDef *LED_Struct)
{/* 1.常灭模式 */if(LED_MODE_OFF == LED_Struct->Mode){LED_Struct->Status = LED_STATUS_OFF;         //状态置为"灭"LED_Struct->OffFun();                        //灭灯}/* 2.常亮模式 */else if(LED_MODE_ON == LED_Struct->Mode){LED_Struct->Status = LED_STATUS_ON;          //状态置为"亮"LED_Struct->OnFun();                         //亮灯}/* 3.闪烁模式 */else if(LED_MODE_FLICKER == LED_Struct->Mode){/* 在灭的状态 */if(LED_STATUS_OFF == LED_Struct->Status){LED_Struct->Counter++;      if(LED_Struct->Counter >= LED_Struct->OffTimes){LED_Struct->Counter = 0;LED_Struct->OnFun();                     //亮灯LED_Struct->Status = LED_STATUS_ON;      //状态置为"亮"}}/* 在亮的状态 */else if(LED_STATUS_ON == LED_Struct->Status){LED_Struct->Counter++;      if(LED_Struct->Counter >= LED_Struct->OnTimes){LED_Struct->Counter = 0;LED_Struct->OffFun();                    //灭灯LED_Struct->Status = LED_STATUS_OFF;     //状态置为"灭"}}else{LED_Struct->Status = LED_STATUS_OFF;       //状态置为"灭"}}/* 4.未知模式 */else{LED_Struct->Status = LED_STATUS_OFF;         //状态置为"灭"LED_Struct->OffFun();                        //灭灯}
}

源代码工程下载地址:

链接:https://pan.baidu.com/s/1cNtwJDdCOfyYwsvKCclFyw

密码:kk74

推荐阅读:

MDK-ARM编译器从V5升级到V6需要做哪些工作?

重温经典PID算法

最后

  1. 置顶公众号,不怕找不到我;

  2. 记得给我点赞哦!

  3. 微信搜索“strongerHuang” 或者扫描下面二维码、关注,在我的底部菜单查看更多精彩内容!

长按识别二维码 关注

赞赏是对作者的认可与支持!

LEDs状态灯任务(线程)设计(基于RTOS)相关推荐

  1. 温故知新(一)——基于 RTOS 的软件开发理论

    目录 前言 1 RTOS的特点 2 任务设计 2.1 任务的特性 2.2 任务划分的方法 2.2.1 设备依赖性任务 2.2.2 关键任务 2.2.3 紧迫任务 2.2.4 数据处理任务 2.2.5 ...

  2. 基于单片机的交通灯信号控制器设计

    基于单片机的交通灯信号控制器设计 一:功能要求 设计一个基于单片机的交通灯信号控制器.已知东.西.南.北四个方向各有红黄绿色三个灯,在东西方向有两个数码管,在南北方向也有两个数码管.要求交通灯按照表1 ...

  3. 基于单片机的智能交通灯系统的设计

    目 录 1绪论 1 2课题的设计要求和设计方案 2 2.1设计要求 2 2.1.1 题目概述 2 2.1.2 设计任务 2 2.1.3 设计要求 2 2.2设计方案 2 2.2.1供电方案 2 2.2 ...

  4. 基于AT89C51单片机的交通灯控制系统的设计

    一.前言 本文中交通灯系统采用MSC-51单片机AT89C51核心来设计交通灯控制器,利用单片机的外围扩展,显示电路构成基本硬件,编程实现对定时.控制.显示电路的控制,调试仿真,完成设计.本系统实现了 ...

  5. 【019】基于51单片机的交通灯Proteus仿真设计

    一.资料内容 (1).基于51单片机的交通灯proteus仿真设计一份: (2).基于51单片机的交通灯proteus仿真设计keli源代码一份: (3).基于51单片机的交通灯proteus仿真设计 ...

  6. 基于STM32F103单片机WIFI无线APP控灯亮度灭设计

    基于STM32F103单片机WIFI无线APP控灯亮度灭设计 一.功能 由STM32F103C8T6单片机核心电路+两位白色高亮LED灯电路+WIFI模块ESP8266电路++电源电路组成. 1.st ...

  7. 单片机串口中断控制流水灯c语言,基于单片机AT89C51控制的中断控制流水灯_课程设计报告...

    <基于单片机AT89C51控制的中断控制流水灯_课程设计报告>由会员分享,可在线阅读,更多相关<基于单片机AT89C51控制的中断控制流水灯_课程设计报告(25页珍藏版)>请在 ...

  8. 计算机网络课程设计--基于TCP协议网上聊天程序--python实现带图形界面--socket--多线程

                                              基于TCP协议网上聊天程序 引言 21世纪是一个以网络为核心的信息时代,要实现信息化,就必须依靠完善的网络.而随着计 ...

  9. VHDL交通灯控制器的设计

    主要内容: 设计主干道的交叉路口交通信号灯无人自动管理的控制系统.将路口红绿灯的各种亮灯情况定义不同的状态,路口状况定义为触发条件,组成有限状态机. 1.设计的目的 本次课程设计的目的是通过设计交通灯 ...

最新文章

  1. npm 卸载_GitHub 收购 npm:天下开源是一家,有个爸爸叫微软
  2. intellij_使用IntelliJ ..已经2周了,到目前为止还算不错
  3. 从零学习 vim 一个多月, 感觉最有用的三个教程
  4. 美国人的网站推广方式千奇百怪
  5. python打包不能在其他电脑打开、找不到指定模块,pyinstaller打包移植到别的电脑报错OSError: [WinError 126] 找不到指定的模块。...
  6. 一年学遍吴恩达、李飞飞、周志华等16大精品课!(ML、CV、NLP一应俱全)
  7. P3804 【模板】后缀自动机
  8. 如何从Java EE无状态应用程序连接到MongoDB
  9. 最长单调递增子序列 [转]
  10. 首个智能风控国际标准发布,蚂蚁风控技术入局全球
  11. listview中有按钮、图片等需要不同点击处理的控件如何处理
  12. 刷题记录 kuangbin带你飞专题九:连通图
  13. 照着官网来安装openstack pike之glance安装
  14. modelsim安装_Modelsim10.5安装教程
  15. 【经验总结—2】:深度学习数据集下载网站总结
  16. hibernate官网下载
  17. Hashcat密码破解
  18. python解决鸡兔同笼_python解决鸡兔同笼问题
  19. 选购国外虚拟主机的一些心得体会
  20. 四十七、使用bootstrap中的选项卡制作产品特色页面

热门文章

  1. win系统加入方舟服务器秒退,win10方舟生存进化进服务器闪退解决方法
  2. 2.SPSS入门基础——数据录入数据管理编程规则图表可视化
  3. 再捐1亿元种树治沙:蚂蚁集团持续七年支持内蒙古生态治理
  4. 有道笔记Markdown快捷键
  5. 炒股赚钱最重要的是炒股心态和纪律
  6. Typora+PicGo+Gitee
  7. JDK 商用正式免费、Log4j2 爆核弹级漏洞、LayUI 下线...2021 发生的 10 件大事。。。
  8. ZOOM——C++软件开发岗(实习)——视频面试一面
  9. js验证手机号、身份证号
  10. cad打开卡死_求助,cad 一打开就卡死,完全没办法运行,怎么处理