FreeRTOS入门——STM32下完成一个基于FreeRTOS的多任务程序

2023-05-16

文章目录

  • 一、 什么是FreeRTOS
  • 二、裸机系统与多任务系统
    • 1、裸机系统
    • 2、多任务系统
    • 3、系统之间的对比
  • 三、实验要求
  • 四、实验准备
  • 五、在KEIL新建 FreeRTOS 工程
    • 1、新建本地工程文件夹
    • 2、使用 KEIL 新建工程
    • 3、在 KEIL 工程里面新建文件组
    • 4、在 KEIL 工程里面添加文件
  • 六、移植FreeRTOS到STM32
    • 1、获取 STM32 的裸机工程模板
    • 2、下载 FreeRTOS V9.0.0 源码
    • 3、往裸机工程添加 FreeRTOS 源码
    • 4、添加 FreeRTOS 源码到工程组文件夹
  • 七、实现多任务程序
    • 1、创建任务句柄
    • 2、编写主程序main.c
    • 3、运行并烧录程序
    • 4、运行结果
  • 八、总结

一、 什么是FreeRTOS

● 我们看一下FreeRTOS的名字,可以分为两部分:Free和RTOS,Free就是免费的、自由的、不受约束的意思,RTOS全称是Real Time Operating System,中文名就是实时操作系统。可以看出FreeROTS就是一个免费的RTOS类系统。这里要注意,RTOS不是指某一个确定的系统,而是指一类系统。比如UCOS,FreeRTOS,RTX,RT-Thread等这些都是RTOS类操作系统。

● 操作系统允许多个任务同时运行,这个叫做多任务,实际上,一个处理器核心在某一时刻只能运行一个任务。操作系统中任务调度器的责任就是决定在某一时刻究竟运行哪个任务,任务调度在各个任务之间的切换非常快!这就给人们造成了同一时刻有多个任务同时运行的错觉。

● 操作系统的分类方式可以由任务调度器的工作方式决定,比如有的操作系统给每个任务分配同样的运行时间,时间到了就轮到下一个任务,Unix操作系统就是这样的。RTOS的任务调度器被设计为可预测的,而这正是嵌入式实时操作系统所需要的,实时环境中要求操作系统必须对某一个事件做出实时的响应,因此系统任务调度器的行为必须是可预测的。像FreeRTOS这种传统的RTOS类操作系统是由用户给每个任务分配一个任务优先级,任务调度器就可以根据此优先级来决定下一刻应该运行哪个任务。

● FreeRTOS是RTOS系统的一种,FreeRTOS十分的小巧,可以在资源有限的微控制器中运行,当然了,FreeRTOS不仅局限于在微控制器中使用。但从文件数量上来看FreeRTOS要比UCOSII和UCOSⅢI小的多。

二、裸机系统与多任务系统

1、裸机系统

裸机系统通常分成轮询系统前后台系统
①轮询系统
在裸机编程的时候,先初始化好相关的硬件,然后让主程序在一个死循环里面不断循环,顺序地做各种事情。只需要顺序执行代码且不需要外部事件来驱动的就能完成的事情。
②前后台系统
在轮询系统的基础上加入了中断。外部事件的响应在中断里面完成,事件的处理还是回到轮询系统中完成,中断在这里我们称为前台,main 函数里面的无限循环我们称为后台。

2、多任务系统

多任务系统的事件响应也是在中断中完成的,但是事件的处理是在任务中完成的。在多任务系统中,任务跟中断一样,也具有优先级,优先级高的任务会被优先执行。当一个紧急的事件在中断被标记之后,如果事件对应的任务的优先级足够高,就会立马得到响应。多任务系统与前后台系统的区别在于对于事件的处理位置不同。

3、系统之间的对比

在这里插入图片描述

三、实验要求

学习FreeRTOS原理,在STM32下完成一个基于FreeRTOS的多任务程序,执行3个周期性task,具体任务如下:

● task1:每间隔500ms闪烁(变化)一次LED;
● task2:每间隔2000ms,向串口发送一次指令数据“helloworld!";
● task3:每间隔5000ms,从AHT20采集一次温湿度数据(不考虑硬件情况,仅写出整个多任务框架模拟代码)。

四、实验准备

1、开发环境:MDK或IAR

2、开发板:野火指南者(STM32F103)

3、从官网下载最新版的FreeRTOS源码,下面的网址是官方最新源码的下载地址:
https://sourceforge.net/projects/freertos/files/latest/download?source=files
目前官方提供的最新版本是v9.0.0, FreeRTOS源码在解压目录下的路径为FreeRTOS_V9.0.0rc2\FreeRTOS\Source

五、在KEIL新建 FreeRTOS 工程

1、新建本地工程文件夹

在开始新建工程之前,我们先在本地电脑端新建一个文件夹用于存放工程。文件夹名字我们取为“新建 FreeRTOS 工程—软件仿真”(名字可以随意取),然后再在该文件夹下面新建各个文件夹和文件,有关这些文件夹的包含关系和作用具体见表格:
在这里插入图片描述在这里插入图片描述

2、使用 KEIL 新建工程

(1)新建工程
打开 KEIL5 软件,新建一个工程,工程文件放在目录 Project 下面,名称命名为Fire_FreeRTOS,名称可以随便取,但是必须是英文,不能是中文,切记。
在这里插入图片描述

(2)选择处理器
当命名好工程名称,点击确定之后会弹出 Select Device for Target 的选项框,让我们选择处理器,这里我们选择 ARMCM3(ARMCM4 或 ARMCM7)
在这里插入图片描述

(3)选择好处理器,点击 OK 按钮后会弹出 Manage Run-Time Environment 选项框。这里在 CMSIS 栏选中 CORE 和 Device 栏选中 Startup 这两个文件即可
在这里插入图片描述
点击 OK,关闭 Manage Run-Time Environment 选项框之后,刚刚我们选择的 CORE 和Startup 这两个文件就会添加到我们的工程组里面。
在这里插入图片描述

3、在 KEIL 工程里面新建文件组

(1)鼠标右键 Target1,在弹出的选项里面选择 Add Group…新建文件组
在这里插入图片描述
(2)在工程里面添加 user、rtt/ports、rtt/source 和 doc 这几个文件组,用于管理文件
在这里插入图片描述

4、在 KEIL 工程里面添加文件

双击文件组,把 readme.txt 文件添加到 doc 组,main.c 添加到 user 组
在这里插入图片描述

六、移植FreeRTOS到STM32

1、获取 STM32 的裸机工程模板

STM32 的裸机工程模板我们直接使用野火 STM32 开发板配套的固件库例程即可。
在这里插入图片描述

2、下载 FreeRTOS V9.0.0 源码

FreeRTOS 的源码获取地址:
https://sourceforge.net/projects/freertos/files/FreeRTOS/
在这里插入图片描述FreeRTOS的源码的具体介绍见链接:http://www.openedv.com/thread-77593-1-1.html

3、往裸机工程添加 FreeRTOS 源码

(1)在STM32裸机工程模板根目录(Source)下新建一个文件夹 ,命名为FreeRTOS。在FreeRTOS文件夹下新建两个空文件夹,分别命名为srcport
● src 文件夹用于保存 FreeRTOS 中的核心源文件(‘.c 文件’)。
● port 文件夹用于保存内存管理以及处理器架构相关代码,这些代码FreeRTOS 官方已经提供给我们的,直接使用即可。

(2)打开 FreeRTOS V9.0.0 源码,在FreeRTOSv9.0.0\FreeRTOS\Source目录下找到
所有的‘.c 文件’,将它们拷贝到我们新建的 src 文件夹中
在这里插入图片描述
(3)打开 FreeRTOS V9.0.0 源码,在FreeRTOSv9.0.0\FreeRTOS\Source\portable
录下找到MemMang文件夹与RVDS文件夹,将它们拷贝到我们新建的port 文件夹中
在这里插入图片描述
(4)打开 FreeRTOS V9.0.0 源码,在FreeRTOSv9.0.0\ FreeRTOS\Source目录下找到include文件夹,它是我们需要用到 FreeRTOS 的一些头文件,将它直接拷贝到我们新建的 FreeRTOS 文件夹中,完成这一步之后就可以看到我们新建的FreeRTOS 文件夹已经有 3 个文件夹,这 3 个文件夹就包含 FreeRTOS 的核心文件。
在这里插入图片描述
至此,FreeRTOS 的源码就提取完成

4、添加 FreeRTOS 源码到工程组文件夹

(1)选中工程,右键选择Manage Project Items
在这里插入图片描述
(2)添加头文件路径
在这里插入图片描述

七、实现多任务程序

1、创建任务句柄

/* 创建任务句柄 */
static TaskHandle_t AppTaskCreate_Handle = NULL;
/* 创建LED1句柄 */
static TaskHandle_t LED1_Task_Handle = NULL;//task1,每间隔500ms闪烁(变化)一次LED;
/* 创建hello句柄 */
static TaskHandle_t hello_Task_Handle = NULL;//task2,每间隔2000ms,向串口发送一次指令数据“helloworld!";
/* 创建AHT20句柄 */
static TaskHandle_t AHT_Task_Handle = NULL;//task3,每间隔5000ms,从AHT20采集一次温湿度数据(不考虑硬件情况,仅写出整个多任务框架模拟代码)。 

2、编写主程序main.c

#include "FreeRTOS.h"
#include "task.h"
#include "bsp_led.h"
#include "bsp_usart.h"

static TaskHandle_t AppTaskCreate_Handle = NULL;
static TaskHandle_t LED1_Task_Handle = NULL;
static TaskHandle_t hello_Task_Handle = NULL;
static TaskHandle_t AHT_Task_Handle = NULL;

static void AppTaskCreate(void);
static void LED1_Task(void* pvParameters);
static void hello_Task(void* pvParameters);
static void AHT_Task(void* pvParameters);
static void BSP_Init(void);
int main(void)
{	
  BaseType_t xReturn = pdPASS;
  BSP_Init();
  printf("这是一个多任务程序实验!\r\n");
  xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate,  
                        (const char*    )"AppTaskCreate",
                        (uint16_t       )512,  
                        (void*          )NULL,
                        (UBaseType_t    )1, 
                        (TaskHandle_t*  )&AppTaskCreate_Handle);         
  if(pdPASS == xReturn)
    vTaskStartScheduler(); 
  else
    return -1;  
  while(1); 
}
static void AppTaskCreate(void)
{
  BaseType_t xReturn = pdPASS;
    taskENTER_CRITICAL();
  xReturn = xTaskCreate((TaskFunction_t )LED1_Task,
                        (const char*    )"LED1_Task",
                        (uint16_t       )512,
                        (void*          )NULL,	
                        (UBaseType_t    )2,	 
                        (TaskHandle_t*  )&LED1_Task_Handle);
  if(pdPASS == xReturn)
    printf("创建LED1_Task任务成功!\r\n");
    
  xReturn = xTaskCreate((TaskFunction_t )hello_Task, 
                        (const char*    )"hello_Task",
                        (uint16_t       )512,  
                        (void*          )NULL,	
                        (UBaseType_t    )3,	 
                        (TaskHandle_t*  )&hello_Task_Handle);
  if(pdPASS == xReturn)
    printf("创建hello_Task任务成功!\r\n");
  
  xReturn = xTaskCreate((TaskFunction_t )AHT_Task, 
                        (const char*    )"AHT_Task",
                        (uint16_t       )512,  
                        (void*          )NULL,
                        (UBaseType_t    )3,	  
                        (TaskHandle_t*  )&AHT_Task_Handle);
  if(pdPASS == xReturn)
    printf("创建AHT_Task任务成功!\r\n");
  
  vTaskDelete(AppTaskCreate_Handle); 
  
  taskEXIT_CRITICAL();   
}
static void LED1_Task(void* parameter)
{	
    while (1)
    {
        LED1_ON;
        vTaskDelay(500);   
        printf("LED1_Task Running,LED1_ON\r\n");
        
        LED1_OFF;     
        vTaskDelay(500);   		
        printf("LED1_Task Running,LED1_OFF\r\n");
    }
}
static void hello_Task(void* parameter)
{	
    while (1)
    {
        vTaskDelay(2000);  
        printf("hello World!\n");
            
    }
}
static void AHT_Task(void* parameter)
{	
    
     /*无硬件,之后实现*/   
                
}
static void BSP_Init(void)
{
	NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
	LED_GPIO_Config();
	USART_Config(); 
}

3、运行并烧录程序

(1)编译运行,检查错误
在这里插入图片描述
(2)顺利通过之后,需要向STM32里烧录,由于我所用的是ST-Link线来连接电脑和开发板,所以在选项设置选择如下:
在这里插入图片描述
之后点击“setting",选项设置如下:
在这里插入图片描述

4、运行结果

任务一实现LED灯闪烁:
在这里插入图片描述任务二向串口发送一次指令数据“hello world!":在这里插入图片描述

八、总结

以上就是本节STM32下基于FreeRTOS的多任务程序所学的全部内容。本实验一定不要忘记初始化函数的添加,特别是对串口的初始化,如果没有初始化,程序可能不会报错,但是使用串口调试助手进行数据接收就什么也不会显示。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS入门——STM32下完成一个基于FreeRTOS的多任务程序 的相关文章

  • 1086:角谷猜想(C C++)

    题目描述 谓角谷猜想 xff0c 是指对于任意一个正整数 xff0c 如果是奇数 xff0c 则乘3加1 xff0c 如果是偶数 xff0c 则除以2 xff0c 得到的结果再按照上述规则重复处理 xff0c 最终总能够得到1 如 xff0
  • 渗透测试工具之Metasploit Framework(MSF)

    一 Metasploit Framework xff08 MSF xff09 简介 Metasploit是当前信息安全与渗透测试领域最流行的术语 xff0c 它的出现颠覆了以往的已有的渗透测试的方式 几乎所有流行的操作系统都支持Metasp
  • Test Case Framework (TCF) 简介

    TCF is a system that simplifies the creation and execution of test cases automation for that matter with minimal setup e
  • 小菜鸡的第一天

    1 CPU分配 xff0c i5四核所以给Linux分配两个核 2 内存分配 xff0c 有16GB所以分配8个g 3 硬盘 xff0c 需要创立一个独立的分区 xff0c 最好300G以上 xff08 由于个人原因分配了60G xff09
  • 小菜鸡的第二天

    绝对路径 xff1a 以 开头 代表当前路径 xff0c 或者 代表上一级目录 xff0c 或者 插入U盘之后 xff0c 在 dev文件夹下输入 ls sd 可以看到U盘信息 xff0c 要想知道插入的U盘是哪个 xff0c 重新插拔再次
  • 小菜鸡的第三天

    压缩与解压 tar vcjf 43 文件名 tar bz2 xxx xxx是要压缩的文件名 压缩命令 tar vxjf 43 xxx tar bz2 xxx是要解压缩的文件名 解压缩命令 f xff1a 使用归档文件或ARCHIVE设备 c
  • 初级算法:判断数组是否存在重复元素

    qsort函数原型是 void qsort xff08 void base size t num size t width int cdecl compare const void const void xff09 4个参数 xff1a v
  • 初级算法:删除排序数组中的重复项

    因为数组是排序的 xff0c 只要是相同的肯定是挨着的 xff0c 我们只需要遍历所有数组 xff0c 然后前后两两比较 xff0c 如果有相同的就把后面的给删除 双指针解决 使用两个指针 xff0c 右指针始终往右移动 xff0c 如果右
  • 运算符重载

    加号运算符重载 作用 xff1a 实现两个自定义数据类型相加的运算 span class token keyword class span span class token class name Person span span class
  • .在python中的作用

    的作用 点把前后连起来 xff0c 构成一种索引机制 前面是库 后面是函数 ex xff1a pybullet setAdditionalSearchPath是指在pybullet的库中引用setAdditionalSearchPath这个
  • ROS服务通信(七)C++、Python实现

    目录 简介 理论模型 服务通信自定srv 创建srv 编辑配置文件 C 43 43 实现 vscode配置 服务端实现 客户端实现 优化 Python实现 服务端实现 客户端实现 简介 服务通信也是ROS中一种极其常用的通信模式 xff0c
  • ROS中的API:C++、Python(十)实现及理解

    目录 简介 C 43 43 初始化 话题与服务相关对象 回旋函数 ros xff1a xff1a spinOnce xff08 xff09 ros xff1a xff1a spin xff08 xff09 时间相关API 时刻 持续时间 持
  • ROS Gazebo安装入门及仿真室内环境和小车实现(十九)

    目录 安装 简介 URDF与Gazebo基本集成流程 创建功能包 编写URDF文件 启动Gazebo并显示模型 launch 文件实现 命令行启动 xff08 去掉launch中的第三行加载模型 xff09 集成到launch里启动 URD
  • Test Case Framework (TCF) tcf 参数

    root 64 embargo ww13 tcf help usage tcf h v log pid tid log time config file CONFIG FILE py p CONFIG PATH state path STA
  • 第一章操作系统引论测验错题整理(二)

    中断和特权级 计算机系统中判断是否有外部中断事件发生应该在 xff09 A 进程切换时 B 执行完一条指令后 C 执行一条指令过程中 D 由用户态转入内核态时 B 解析 xff1a 因果关系 xff0c 指令执行了才知道 从用户态到内核态的
  • 多旋翼飞行器设计与控制(三)—— 机架设计

    多旋翼飞行器设计与控制 xff08 三 xff09 机架设计 一 布局设计 1 机身基本布局 共有三种 xff1a 环型 43 字型 X字型 常用X字型 xff1a 机动性更强前视相机的视场角不容易被遮挡 环形的特点 xff1a 刚性更大避
  • 路径规划与轨迹优化 —— Dijkstra算法寻找最短路径

    一 算法思路 Dijkstra算法是一种用来寻找最短路径的算法 xff0c 其中涉及的思想有贪心 动态规划 广度优先搜索等 图中g n 代表的时代价 xff0c 在机器人路径规划中可以理解为距离 二 代码 源码来源于Github xff0c
  • VSCode远程连接免密登录

    配置了VSCode远程连接服务器 xff0c 但每次打开project都需要重新输入密码 xff0c 比较麻烦 xff0c 所以下面就介绍一下如何免密码登入 在上一篇blog里面配置好VSCode远程连接服务器之后按照如下操作 步骤如下 x
  • raspberry(树莓派)的简介及实验

    提示 xff1a 文章写完后 xff0c 目录可以自动生成 xff0c 如何生成可参考右边的帮助文档 文章目录 前言一 树莓派是什么 xff1f 二 使用步骤 1 主要Pin脚的编号2 使用硬件3 连接树莓派Pin位4 使用代码实验 总结
  • 深度学习环境配置Anaconda+cuda+cudnn+PyTorch——李沐大神《动手学深度学习》环境配置(巨详细,持续迭代)

    李沐大神 动手学深度学习 安装篇 通用AI 深度学习 机器学习环境 Anaconda 43 cuda 43 cudnn 43 Pytorch 手把手教你安装深度学习环境 xff09 这里是GPU 43 PyTorch版本 文章目录 李沐大神

随机推荐

  • FreeRTOS-任务间共享数据的管理框架

    本文章介绍一种在FreeRTOS项目中任务间共享数据的管理框架 xff0c 思路比较简单 任务在更新和获取共享数据时利用互斥量进行上锁保护数据 xff0c 操作完之后进行解锁 xff0c 并且当共享数据使用setting 更新时调用对应的回
  • 树莓派、Jetson nao在ROS下进行darknet深度学习识别物体大致方向及流程

    目标成果 xff1a 在linux设备中启用darknet ros 0 如何获得darknet ros源码 xff1a 渠道1 xff1a github的darknet ros 渠道2 xff1a gitee的darknet ros xff
  • 如何重新设置Ubuntu20.04用户密码以及管理员密码

    当我们在Windows上安装VMwareWorkstation虚拟机上运行Linux系统发现一件尴尬的事情 那就是 忘记密码了 解决方法具体如下 一 在VMwareWorkstation虚拟机上方工具栏选中重新启动客户机 xff0c 启动后
  • STM32CubeMX 修改下载文件(固件包)的存储路径

    当我们在使用STM32CubeMX 的过程中 xff0c 会有一些文件下载像各种STM32Cube FW固件开发包 如果安装了CubeMxIDE这个图形化工具 xff0c 我们就不用去官方下载了 可极大的节省开发效率 在win10和win7
  • Test Case Framework (TCF) tcf 刷机/AC/KVM 基本使用(一)

    移除属于我的机器 tcf alloc rm tcf alloc ls q u self 查看机器版本 tcf ls vv targetname 串口log tcf console read spr40s01 c log flash bios
  • 多线程CompletableFuture之常用方法示例

    文章目录 前期准备1 runAsync2 supplyAsync3 thenRunAsync4 thenAcceptAsync5 runAfterBothAsync6 thenCombineAsync7 exceptionally8 han
  • 算法题解-- stl

    周末舞会 题目描述 假设在周末舞会上 xff0c X 名男士和 Y 名女士进入舞厅时 xff0c 各自排成一队 xff0c 并分别按顺序编号 跳舞开始时 xff0c 依次从男队和女队的队头上各出一人配成舞伴 规定每个舞曲只能有一对跳舞者 跳
  • 简说spring 的设计模式

    spring 的设计模式 xff08 23种 xff08 面试题 xff09 说说BeanFactory和FactoryBean的实现原理和区别 xff1f spring 中你还知道哪些设计模式 xff1f xff1f 1 简单工厂模式 实
  • 【转载】MathGL中报错:undefined reference to `mgl_create_graph‘的解决方法

    概述 xff1a 在环境 xff1a ubuntu 20 04 中 成功下载好了mathGL xff0c 但是最后编译却报错 undefined reference to 96 mgl create graph 39 如下 xff1a 各种
  • 第十三届蓝桥杯 C/C++ 大学B组 题解

    第十三届蓝桥杯 C C 43 43 大学B组 题解 A 进制计算简单模拟 span class token macro property span class token directive hash span span class tok
  • Android12系统源码目录简单分析

    在这里插入图片描述 https img blog csdnimg cn 07a0627ec4754074b5b621cb3e4dae4d png 上面这么多文件夹 xff0c 有些是一直不需要去理会的 xff0c 比如说接触较多的文件夹 x
  • 应用层与内核层的区别

    应用层 xff1a 主要操作用户空间 xff0c 主要编写逻辑 xff0c 打印信息调用标准库里面的printf函数 内核层 xff1a 主要操作内核空间 xff0c 实现五大管理 xff1a 进程管理 xff0c 内存管理 xff0c 文
  • ubuntu软件:录制视频和截图工具,压缩视频

    1 自带录制视频工具 xff1b 使用方式 xff1a 无需下载 开始录屏 结束录屏 xff1a Ctrl 43 Alt 43 Shift 43 r 当看到 Ubuntu 桌面的右上方多了一个红色的小圆点 xff0c 代表正在录制 注意 x
  • Eth-trunk :LACP模式链路聚合实战

    Eth trunk LACP模式链路聚合实战 需求描述 PC1和PC3数据vlan10 xff0c 网段为192 168 10 0 24PC2和PC4数据vlan20 xff0c 网段为192 168 20 0 24确保设备之间互联互通 x
  • Test Case Framework (TCF) tcf itp 基本使用(二)

    查看机器是否支持itp tcf ls v interfaces power itp0 instrument
  • PDF发送短信2

    SMS是由Esti 所制定的一个规范 xff08 GSM 03 40 和 GSM 03 38 xff09 有两种方式来发送和接收SMS消息 xff1a 文本模式或者PDU xff08 protocol description unit xf
  • maven 打包资源文件需要注意的问题

    初衷 我写这篇博客的目的是想让大家了解一些 maven 项目的结构以及打包后是什么样子的 xff0c 方便大家在实际项目中去排查问题 比如 xff1a 我明明在 src main java 下把 mybatis 的 xml 写上了 xff0
  • Linux服务器Ubuntu上搭建Jenkins+Pytest+Gitee+Allure自动化

    一 安装Jenkins和Java Jenkins 是一个开源自动化服务器 xff0c 它可以自动执行软件持续集成和交付中涉及的重复性技术任务 Jenkins 易于安装且基于 Java xff0c 此外 xff0c 可以使用 Web 界面轻松
  • Python Cookbook学习总结

    第一章 xff1a 数据结构和算法 任何序列 xff08 可迭代的对象 xff09 都可以通过一个简单的赋值操作来分解为单独的变量 xff0c 唯一的要求是变量的总数和结构要与序列相吻合 xff08 比如对于存储二维坐标等的二维数组 xff
  • FreeRTOS入门——STM32下完成一个基于FreeRTOS的多任务程序

    文章目录 一 什么是FreeRTOS二 裸机系统与多任务系统1 裸机系统2 多任务系统3 系统之间的对比 三 实验要求四 实验准备五 在KEIL新建 FreeRTOS 工程1 新建本地工程文件夹2 使用 KEIL 新建工程3 在 KEIL