您现在的位置是:人工智能 >>正文
表驱动法在STM32中的应用
人工智能7448人已围观
简介概念所谓表驱动法(Table-Driven Approach)简而言之就是用查表的方法获取数据。此处的“表”通常为数组,但可视为数据库的一种体现。根据字典中的部首检字表查找读音未知的汉字就是典型的表驱 ...
所谓表驱动法(Table-Driven Approach)简而言之就是表驱用查表的方法获取数据。此处的动法“表”通常为数组,但可视为数据库的表驱一种体现 。
根据字典中的动法部首检字表查找读音未知的汉字就是典型的表驱动法,即以每个字的表驱字形为依据,计算出一个索引值,动法并映射到对应的表驱页数。云计算相比一页一页地顺序翻字典查字 ,动法部首检字法效率极高。表驱
具体到编程方面,动法在数据不多时可用逻辑判断语句(if…else或switch…case)来获取值;但随着数据的表驱增多,逻辑语句会越来越长,动法此时表驱动法的表驱优势就开始显现。
简单示例上面讲概念总是动法枯燥的,我们简单写一个C语言的表驱例子 。下面例子功能:传入不同的数字打印不同字符串。
使用if…else逐级判断的服务器租用写法如下 :
复制void fun(int day){ if (day == 1) { printf("Monday\n"); } else if (day == 2) { printf("Tuesday\n"); } else if (day == 3) { printf("Wednesday\n"); } else if (day == 4) { printf("Thursday\n"); } else if (day == 5) { printf("Friday\n"); } else if (day == 6) { printf("Saturday\n"); } else if (day == 7) { printf("Sunday\n"); }}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.使用switch…case的方法写 。
复制void fun(int day){ switch (day) { case 1: printf("Monday\n"); break; case 2: printf("Tuesday\n"); break; case 3: printf("Wednesday\n"); break; case 4; printf("Thursday\n"); break; case 5: printf("Friday\n"); break; case 6: printf("Saturday\n"); break; case 7:printf("Sunday\n"); break; default: break; }}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.使用表驱动法实现。
复制char weekDay[] = { Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday};void fun(int day){ printf("%s\n",weekDay[day]);}1.2.3.4.5.看完示例 ,可能“恍然大悟”,一拍大腿 ,原来表驱动法就是这么简单啊。是的 ,它的核心原理就是这个简单,如上面例子一样。
如果上面的亿华云例子还没get这种用法的好处,那么再举一个栗子 。
统计用户输入的一串数字中每个数字出现的次数 。
常规写法
复制int32_t aDigitCharNum[10] = { 0}; /* 输入字符串中各数字字符出现的次数 */int32_t dwStrLen = strlen(szDigits);int32_t dwStrIdx = 0;for (; dwStrIdx < dwStrLen; dwStrIdx++){ switch (szDigits[dwStrIdx]) { case 1: aDigitCharNum[0]++; break; case 2: aDigitCharNum[1]++; break; //... ...
case 9: aDigitCharNum[8]++; break; }}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.表驱动法
复制
for(; dwStrIdx < dwStrLen; dwStrIdx++){ aDigitCharNum[szDigits[dwStrIdx] - 0]++;}1.2.3.4.5.偶尔在一些开源项目中看到类似的操作 ,惊呼“骚操作” ,其实他们有规范的叫法 :表驱动法。
在MCU中应用在MCU中的应用示例,怎么少的了点灯大师操作呢?首先来点一下流水LED灯吧。模板下载
常规写法
复制void LED_Ctrl(void){ static uint32_t sta = 0; if (0 == sta) { LED1_On(); }else
{ LED1_Off(); } if (1 == sta) { LED2_On(); }else
{ LED2_Off(); } /* 两个灯,最大不超过2 */ sta = (sta + 1) % 2;}/* 主函数运行 */int main(void){ while (1) { LED_Ctrl(); os_delay(200); }}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.表驱动法
复制extern void LED1_On(void);extern void LED1_Off(void);extern void LED2_On(void);extern void LED2_Off(void);struct tagLEDFuncCB
{ void (*LedOn)(void); void (*LedOff)(void);};const static struct tagLEDFuncCB LedOpTable[] ={ { LED1_On, LED1_Off}, { LED2_On, LED2_Off},};void LED_Ctrl(void){ static uint32_t sta = 0; uint8_t i; for (i = 0; i < sizeof(LedOpTable) / sizeof(LedOpTable[0]); i++) { (sta == i) ? (LedOpTable[i].LED_On()) : (LedOpTable[i].LED_Off()); } sta = (sta + 1) % (sizeof(LedOpTable) / sizeof(LedOpTable[0]));}int main(void){ while (1) { LED_Ctrl(); os_delay(200); }}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.这样的代码结构紧凑,因为和结构体结合起来了 ,方便添加下一个LED灯到流水灯序列中,这其中涉及到函数指针,详细请看《回调函数》,只需要修改LedOpTable如下 :
复制const static struct tagLEDFuncCB LedOpTable[] ={ { LED1_On, LED1_Off}, { LED2_On, LED2_Off}, { LED3_On, LED3_Off},};1.2.3.4.5.6.这年头谁还把流水灯搞的这么花里胡哨的啊 ,那么就举例在串口解析中的应用,之前的文章推送过《回调函数在命令解析中的应用》,下面只贴一下代码:
复制
typedef struct
{ rt_uint8_t CMD; rt_uint8_t (*callback_func)(rt_uint8_t cmd, rt_uint8_t *msg, uint8_t len);} _FUNCCALLBACK;_FUNCCALLBACK callback_list[] ={ { cmd1, func_callback1}, { cmd2, func_callback2}, { cmd3, func_callback3}, { cmd4, func_callback41},...
};void poll_task(rt_uint8_t cmd, rt_uint8_t *msg, uint8_t len){ int cmd_indexmax = sizeof(callback_list) / sizeof(_FUNCCALLBACK); int cmd_index = 0; for (cmd_index = 0; cmd_index < cmd_indexmax; cmd_index++) { if (callback_list[cmd_index].CMD == cmd) { if (callback_list[cmd_index]) { /* 处理逻辑 */ callback_list[cmd_index].callback_func(cmd, msg, len); } } }}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.除上述例子 ,免费模板表驱动法在UI界面中也有良好的应用 ,如下:
结构体封装
复制typedef enum{ stage1 = 0, stage2, stage3, stage4, stage5, stage6, stage7, stage8, stage9,} SCENE;typedef struct
{ void (*current_operate)(); //当前场景的处理函数
SCENE Index; //当前场景的标签
SCENE Up; //按下Up键跳转的场景
SCENE Down; //按下Down键跳转的场景
SCENE Right; //按下Left键跳转的场景
SCENE Left; //按下Right键跳转的场景
} STAGE_TAB;1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.函数映射表
复制STAGE_TAB stage_tab[] = {
//operate Index Up Down Left Right
{ Stage1_Handler, stage1, stage4, stage7, stage3, stage2},
{ Stage2_Handler, stage2, stage5, stage8, stage1, stage3},
{ Stage3_Handler, stage3, stage6, stage9, stage2, stage1},
{ Stage4_Handler, stage4, stage7, stage1, stage6, stage5},
{ Stage5_Handler, stage5, stage8, stage2, stage4, stage6},
{ Stage6_Handler, stage6, stage9, stage3, stage5, stage4},
{ Stage7_Handler, stage7, stage1, stage4, stage9, stage8},
{ Stage8_Handler, stage8, stage2, stage5, stage7, stage9},
{ Stage9_Handler, stage9, stage3, stage6, stage8, stage7},
};1.2.3.4.5.6.7.8.9.10.11.12.定义两个变量保存当前场景和上一个场景 。
复制char current_stage=stage1;char prev_stage=current_stage;1.2.按下Up按键 跳转到指定场景current_stage的值根据映射表改变。
复制current_stage =stage_tab[current_stage].Up;1.场景改变后 根据映射表执行相应的函数Handler 。
复制if(current_stage!=prev_stage){ stage_tab[current_stage].current_operate(); prev_stage=current_stage;}1.2.3.4.5.这是一个简单的菜单操作 ,源码库结合了表驱动法 。在MCU中表驱动法有很多很多用处 ,本文的例子已经过多了 ,如果在通勤路上用手机看到这里,已经很难了。
后记这篇文章我也看到网上一遍表驱动法的后总结的笔记 ,可能也有很多同学和我一样,在自己的项目中熟练应用了这种“技巧”,但今天才知道名字 :表驱动法 。
Tags:
转载:欢迎各位朋友分享到网络,但转载请说明文章出处“信息技术视野”。http://www.bziz.cn/news/846f299151.html
相关文章
了解勒索软件攻击的三个阶段及迹象以降低企业面临的风险
人工智能当谈到勒索软件攻击时,大多数时候没有“确凿的证据”来提示防御者发生了什么。相反,在攻击的不同阶段,往往有许多不同的危害迹象,当单独来看时,这些指标似乎是良性的。因此,重要的是尽早确定尽可能多的危害迹象 ...
【人工智能】
阅读更多小米Note2(一部能与大品牌媲美的高性能手机)
人工智能在如今的智能手机市场上,小米Note2无疑是一款备受瞩目的产品。作为小米公司旗下的明星机型,小米Note2以其出色的性能和优秀的用户体验,吸引了众多消费者的眼球。本文将从多个角度深入探讨小米Note2 ...
【人工智能】
阅读更多红米2乐蛙系统的使用体验(功能强大、操作简便的红米2乐蛙系统让你爱不释手)
人工智能随着智能手机的普及,手机操作系统的选择变得越来越重要。红米2乐蛙系统作为一款功能强大、操作简便的系统,备受用户欢迎。本文将详细介绍红米2乐蛙系统的各项功能和使用体验,帮助读者更好地了解和使用这一系统。 ...
【人工智能】
阅读更多
热门文章
最新文章
友情链接
- 10 款酷酷的 Android 应用
- 努比亚Z9mini开启手掌锁屏方法
- 魅族mx4usb调试在哪儿打开?魅族mx4usb调试使用方
- 老桃毛装系统教程(掌握老桃毛装系统,赋予家居独特魅力)
- 苹果7充电的实用指南(从选择充电器到延长电池寿命,助你解决苹果7充电难题)
- 以梅捷主板装机教程为主题的详细指南(从选购到装配,助你轻松打造个人电脑)
- 探索B85主板性能和特点(了解B85主板的关键特征和优势)
- 笔记本电脑运行缓慢的解决方法(15个简单步骤让你的笔记本电脑恢复高效)
- 简单三步 Android 5.0版本就能更省电
- 详解 Android 虚拟机 ART 运行时库 分析 企业服务器亿华云源码库香港物理机云服务器b2b信息平台网站建设