嵌入式裸机设计思想

您所在的位置:网站首页 stm32软件分层 嵌入式裸机设计思想

嵌入式裸机设计思想

2024-07-14 09:27| 来源: 网络整理| 查看: 265

前言

(1)如果有嵌入式企业需要招聘校园大使,湖南区域的日常实习,任何区域的暑假Linux驱动实习岗位,可C站直接私聊,或者邮件:[email protected],此消息至2025年1月1日前均有效 (2)在MCU开发的时候,很多入门者会固执的认为,做项目一定要上实时操作系统。但是真的是这样的吗? (3)我曾经阅读过一位10年嵌入式开发经验的大佬分享的公众号,这位大佬感叹到,其实对于绝大多数时候,MCU开发不需要上操作系统。只要任务分配的合理,百分之九十的项目不上操作系统都是能够跑的。 (4)今天我就分享一下我之前备赛期间所搭建基于TM4C123的工程模板。不过这个模板问题还是有很多,比如模块之间耦合很严重,当时没有这个意识,现在才发现写的有多垃圾。虽说如此,但本人认为还是有优点的地方。 (5)注意:本文需要一点函数指针,结构体,枚举的知识,不了解的同学请先去补充好基础再来看

正文 状态机

(1)状态机其实很好理解,说白了就是一个switch()语句。根据情况将一个任务拆分成多种。例如,在我的代码中,有一个OLED显示程序。因为OLED显示是非常浪费时间的,为了不因为一个这样的程序,而影响到其他任务的执行,我们可以将OLED显示任务分成多个,依次显示。

static void Display(void) { static uint8_t gray_display_state=2; switch(gray_display_state) { case 2:gray_display_state++;break; case 3:gray_display_state++;break; case 4:gray_display_state++;break; case 5:gray_display_state++;break; case 6:gray_display_state++;break; default:gray_display_state = 2; } }

(2)上面那种其实是最简单的形式,整个状态是呈现圆圈型状的状态机。但是,我们有时候会遇到一些情况,他的状态有很多种任务流程,例如洗衣机,有待机状态,运行状态,运行结束之后的自动停止进入待机状态,手动关停状态,因一些异常情况引起的停止状态。因此,状态机也是一个很好的思路。

在这里插入图片描述

enum Washer_State_List { off, //待机状态 run, //运行机状态 automatic_stop, //自动停止 hand_stop, //手动关停状态 malfunction //故障 }; static void washer_control(void) { static uint8_t washer_state=2; switch(washer_state) { case off: LCD_show("stop"); if(operation_key == true) washer_state = run; break; case run: LCD_show("runing"); //如果手动关停 if(hand_stop_key == true) washer_state = hand_stop; //如果计时结束 if(time-- == over) washer_state = automatic_stop; //识别到了异常 if(err == true) goto err; break; case automatic_stop: //显示洗衣机已经关闭 LCD_show("Finished washing"); washer_state = off; break; case hand_stop: //关闭洗衣机 washer_stop(); //显示洗衣机已经手动关闭 LCD_show("Manually closed"); washer_state = off; break; case malfunction: err : //关闭洗衣机 washer_stop(); //报警 alarm_system(on); //显示机器故障 LCD_show("Machine failure"); washer_state = off; break; default:gray_display_state = 2; } } 时间片轮裸机开发架构

(1)这个机制名字很多,有些人叫做软定时器,有些叫做Easy51RTOS,具体叫做什么,我们就不深究了。 (2)新手入门MCU裸机开发,肯定都是一股脑的采用while(1)死循环,然后一直跑。如果是开发稍微复杂一点点的任务时候,你就会深刻的感受到,这样写究竟有多垃圾。 (3)一股脑的while(1)死循环,然后里面堆一大堆的任务,这样做有一下几种问题: 在后续的维护中非常复杂。想找到目标任务找起来很费力。 并不是所有的任务都需要频繁执行,例如OLED显示,就是一个非常费时间,但是又没有必要一直保持刷新的任务。他只要能够做到50ms刷新一次就能够做动画了。因此这种任务放在while(1)无脑执行无疑是对CPU的浪费,导致真正需要CPU执行的任务没有有效的照顾。 (4)为了优化上面这些问题,大佬们于是提出了基于时间片的裸机开发架构,我们可以利用一个定时器提供心跳,不断的进行计数。然后当定时时间一到,那么就可以开始执行相应的任务了。 (5)时间片轮转的裸机架构看起来是不是很完美?NO,不是的,他确实比无脑while(1)优秀很多,但是我们需要知道,每个任务的执行时间不能超出一次时间片。(例如我们上面的滴答定时器是2ms定时,所以时间片是2ms) (6)因此,我们需要大概估计每个任务的执行时间,这里有很两种做法: 利用滴答定时器,当任务开始记录当前时间,任务结束记录当前时间然后两者相减。 进入函数,让某个引脚为高电平,函数结束让他为低电平,然后用示波器捕捉这个引脚的上升沿和下降沿。(这个方法感觉有点麻烦,我是使用的第一个) (7)时间片轮裸机开发框架机制确实非常好,但是毕竟还是软件实现的任务调度,实时性只能说相对于只有一个while(1)好,对于其他的机制还是不太行。所以我个人还是建议,只有不重要的任务,对整个项目影响不大的任务可以放在这个框架里面,例如OLED显示,按键扫描。

/*------------------------------------------------*/ /*------------------- systick.c ------------------*/ /*------------------------------------------------*/ /* 滴答定时器中断,每2毫秒进入一次,count表示过了多少个2毫秒,最多计时2366多个小时*/ static void SycTickHandler(void) { counter++; task_remarks(); //用于任务调度,此任务执行时间在5us之内 } /*------------------------------------------------*/ /*-------------------- Task.h --------------------*/ /*------------------------------------------------*/ #ifndef _Task__H #define _Task__H // 任务结构 typedef struct { uint8_t run; // 程序运行标记:0:不运行,1:运行 uint16_t timer; // 定时器,用于自减 单位:ms uint16_t itv_time; // 任务运行间隔时间 单位:ms void (*hook)(void); // 要运行的任务函数 } task_params_t; /***** 函数声明 *******/ void task_proc(void); //任务执行处理 void task_remarks(void); //任务标志位处理 #endif /*------------------------------------------------*/ /*-------------------- Task.c --------------------*/ /*------------------------------------------------*/ static void SW_Scan(void); // 任务清单 enum TASK_LIST { TASK1_SW_Scan, // 任务2,按键扫描 TASK2_Display, // 任务3,OLED显示 TASKS_NUM // 任务总数 }; //任务列表 static task_params_t s_task_params[TASKS_NUM] = { {0, Task_interval_ms(20), Task_interval_ms(20), SW_Scan }, //任务2 {0, Task_interval_ms(10), Task_interval_ms(10), Display }, //任务3 }; /* ********************************************************************************************************* * 函 数 名: task_proc * 功能说明: 任务处理 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void task_proc(void) { uint8_t i = 0; for(i = 0; i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3