TMF单片机开发框架精简版入门

TMF单片机开发框架精简版入门前言 无论在面向过程 还是面向对象的开发过程中 都要借助自顶向下模块化思想 按照合适的粒度 把业务需求分解成若干功能单元 然后这些功能单元转化成函数以供调用 当业务比较简单 例如某个按键被按下 我们直接调用 led on 这样做貌似很合理

大家好,我是讯享网,很高兴认识大家。


前言

        无论在面向过程,还是面向对象的开发过程中,都要借助自顶向下模块化思想,按照合适的粒度,把业务需求分解成若干功能单元,然后这些功能单元转化成函数以供调用。当业务比较简单,例如某个按键被按下,我们直接调用led_on(),这样做貌似很合理,但果真如此吗?我们再细想一下,会发现这样写耦合程度很高。按键扫描函数和LED功能函数通常在不同的文件中实现,如果前者直接调用后者,会出现文件功能强依赖,不利于代码复用。另外在某些场合,例如中断服务程序,执行时间要尽可能的短,以便单片机执行其它指令。假设在串口中断服务程序中,需要接收许多来自上位机不同的指令,不能直接调用太多外部函数,做过多耗时的操作。至少保证在下一次中断来临前必须退出中断,否则会导致数据丢失。如果设置某些状态位来对应不同的指令状态,然后在主程序的while循环中,轮询这些状态位,当状态置位时,我们就去执行某些指令或调用某个函数,这样代码耦合程度就大大降低了。事实上,好多小伙伴已经这样做了。

        那么问题来了,这些状态位该如何管理呢?如果搞很多变量保存状态,在while循环中进行判断,再加上函数调用,会造成main函数十分臃肿,如何优雅的实现呢?

一、Why TMF精简版?

        TMF精简版作为一个入门级功能框架,仅实现状态置位和轮询功能,没有时间片和应答交互等功能,对于业务简单的单片机程序来说已经足够了。本篇文章先以TMF精简版为例,来实现按键控制一个LED的亮和灭。TMF独立于任何单片机平台,精简版资源要求较低,51单片机都可能使用。

二、代码编写步骤

1.创建tmf_task_list.h

#ifndef TMF_TASK_LIST_H #define TMF_TASK_LIST_H 任务列表 typedef enum { / Add Task Definition here All tasks are named as TMF_TASK_ModuleName_TaskActionName / //LED TMF_TASK_TURN_LED_ON=0, TMF_TASK_TURN_LED_OFF, / Do not Delete the TMF_TOTAL_TASKS here / TMF_TOTAL_TASKS //任务总数,不要删除 } TMF_Task_List_t; //执行结果 typedef enum { TASK_EXE_NONE = 0, //未执行 TASK_EXE_SUCCESS, //执行成功 TASK_EXE_FAIL //执行失败 } Task_Exe_Result_t; #endif /* TMF_TASK_LIST_H */

讯享网

        上面定义了TMF_TASK_TURN_LED_ON和TMF_TASK_TURN_LED_OFF两个任务,分别表示LED点亮和LED熄灭。可以根据实际情况进行增减,其它地方不要修改。

2.创建tmf.h

讯享网#ifndef TMF_H #define TMF_H / #include "tmf_task_list.h" #define TMF_Task_ID_t uint16_t / typedef struct { unsigned char needToExec; //执行状态 unsigned char execResult; //执行结果 void (*exeEntry)(); //函数入口 } TMF_data_t; // //定义TMF结构体数组 // extern TMF_data_t tmf[TMF_TOTAL_TASKS]; // //TMF初始化函数 void TMF_Init(void); //TMF轮询函数 void TMF_Poll(void); // //TMF执行函数 // void TMF_Executor(TMF_Task_ID_t TMF_Task_ID); // TMF状态检查函数 IN: TMF_Task_ID // void TMF_Checker(TMF_Task_ID_t TMF_Task_ID); // TMF状态清除函数 IN: TMF_Task_ID // void TMF_Cleaner(TMF_Task_ID_t TMF_Task_ID); // TMF任务唤醒函数 IN: TMF_Task_ID // void TMF_ExeEvoker(TMF_Task_ID_t TMF_Task_ID); // //TMF设置执行结果 IN: TMF_Task_ID // void TMF_SetExeResult(TMF_Task_ID_t TMF_Task_ID, unsigned char ExeResult); #endif /* TMF_H */


讯享网

3.创建tmf.c

#include "tmf.h" //TMF初始化函数 void TMF_Init(void) { TMF_Task_ID_t i; /// TMF Nodes init /// for (i = 0; i < TMF_TOTAL_TASKS; i++) { tmf[i].needToExec = FALSE; tmf[i].execResult = TASK_EXE_NONE; tmf[i].exeEntry = NULL; } } //TMF轮询函数 void TMF_Poll(void) { TMF_Task_ID_t i; for (i = 0; i < TMF_TOTAL_TASKS; i++) { if (tmf[i].needToExec == TRUE) { TMF_Checker(i); } } } // //TMF执行函数 IN: TMF_Task_ID // void TMF_Executor(TMF_Task_ID_t TMF_Task_ID) { if(tmf[TMF_Task_ID].exeEntry!=NULL) { tmf[TMF_Task_ID].exeEntry(); } } // TMF任务检查 IN: TMF_Task_ID // void TMF_Checker(TMF_Task_ID_t TMF_Task_ID) { if (tmf[TMF_Task_ID].execResult == TASK_EXE_SUCCESS) { TMF_Cleaner(TMF_Task_ID); } else if (tmf[TMF_Task_ID].needToExec == TRUE) { TMF_Executor(TMF_Task_ID); } } // //TMF任务清除 IN: TMF_Task_ID // void TMF_Cleaner(TMF_Task_ID_t TMF_Task_ID) { tmf[TMF_Task_ID].needToExec = FALSE; tmf[TMF_Task_ID].execResult = TASK_EXE_NONE; } // //TMF任务唤醒 IN: TMF_Task_ID // void TMF_ExeEvoker(TMF_Task_ID_t TMF_Task_ID) { tmf[TMF_Task_ID].needToExec = TRUE; } // //TMF任务结果 //IN: TMF_Task_ID // void TMF_SetExeResult(TMF_Task_ID_t TMF_Task_ID, unsigned char ExeResult) { tmf[TMF_Task_ID].execResult = ExeResult; }

4.创建key.h

讯享网#ifndef __KEY_H #define __KEY_H #include "tmf_task_list.h" #include "tmf.h" typedef struct { unsigned char key_status;//按键状态 unsigned char enter_times;//进入次数 unsigned char led_status;//灯状态位 }Key_Data_t; typedef enum { KEY_STATUS_PRESSED=0, KEY_STATUS_RELEASED }Key_Status_t; typedef enum { LED_STATUS_ON=0, LED_STATUS_OFF }Led_Status_t; //按键检测间隔 ms //需要结合定时器,本示例没有用 #define KEY_DETECT_DELAY 20 //读取按键,请修改成具体单片机的端口 #define READ_KEY RA5 extern Key_Data_t key; void Key_Init(void); void Key_Scan(void); #endif 

5.创建key.c

#include "key.h" void Key_Init(void) { //按键端口初始化为输入 //to do //假设按下为低电平,上拉使能或使用外部上拉电阻 //to do key.key_status=KEY_STATUS_RELEASED; key.led_status=LED_STATUS_OFF; } void Key_Scan(void) { //假设按下为低电平 if(READ_KEY==0) { if(key.key_status==KEY_STATUS_RELEASED)//防抖处理 { key.key_status=KEY_STATUS_PRESSED; key.enter_times=1; } else if(key.key_status==KEY_STATUS_PRESSED) { key.enter_times++; if(key.enter_times==2) { if(key.led_status==LED_STATUS_OFF) { key.led_status=LED_STATUS_ON; //唤醒任务 TMF_ExeEvoker(TMF_TASK_TURN_LED_ON); } else if(key.led_status==LED_STATUS_ON) { key.led_status=LED_STATUS_OFF; //唤醒任务 TMF_ExeEvoker(TMF_TASK_TURN_LED_OFF); } } } } else { key.key_status=KEY_STATUS_RELEASED; } } 

6.创建led.h

讯享网#ifndef __LED_H #define __LED_H //包含必要的头文件 //#include <...> void led_init(void); void led_on(void); void led_off(void); #endif

7.创建led.c

#include "led.h" void led_init(void) { //端口初始化为输出 //设置初始电平,使灯关闭 } void led_on(void) { //改变引脚电平,使灯亮 } void led_off(void) { //改变引脚电平,使灯灭 }

8.创建tmf_led_init.h

讯享网#ifndef __TMF_LED_INIT_H #define __TMF_LED_INIT_H // #include "tmf_task_list.h" #include "tmf.h" #include "led.h" // void tmf_led_init(void); void tmf_led_on(void); void tmf_led_off(void); #endif

9.创建tmf_led.init.c

#include "tmf_led_init.h" void tmf_led_init(void) { tmf[TMF_TASK_TURN_LED_ON].exeEntry=tmf_led_on; tmf[TMF_TASK_TURN_LED_OFF].exeEntry=tmf_led_off; } void tmf_led_on(void) { led_on(); TMF_SetExeResult(TMF_TASK_TURN_LED_ON,TASK_EXE_SUCCESS); } void tmf_led_off(void) { led_off(); TMF_SetExeResult(TMF_TASK_TURN_LED_OFF,TASK_EXE_SUCCESS); }

10.修改tmf.h

        在#include "tmf_task_list.h" 下面增加#include "tmf_led_init.h"。

11.修改tmf.c

讯享网//TMF初始化函数 void TMF_Init(void) { TMF_Task_ID_t i; /// TMF Nodes init /// for (i = 0; i < TMF_TOTAL_TASKS; i++) { tmf[i].needToExec = FALSE; tmf[i].execResult = TASK_EXE_NONE; tmf[i].exeEntry = NULL; } //新增初始化代码 tmf_led_init(); }

12.创建main.h

#ifndef __MAIN_H #define __MAIN_H #include "tmf_task_list.h" #include "tmf.h" #include "key.h" #include "led.h" Key_Data_t key; // #endif

13.创建main.c

讯享网#include "main.h" void main(void) { TMF_Init(); Key_init(); led_init(); while(1) { TMF_Poll();//轮询 Key_Scan();//按键扫描 } } 


总结

    以上就是今天要讲的内容,本文仅仅简单介绍了TMF简化版的使用,请大家根据实际平台作必要修改。

小讯
上一篇 2025-03-11 10:04
下一篇 2025-03-08 11:08

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/24009.html