当前位置: 首页 > article >正文

使用STM32CubeMX和Keil在STM32上创建并运行一个简单的FreeRTOS多任务程序

目标

利用FreeRTOS运行两个任务,分别为点灯和OLED屏的显示。

利用STM32CubeMX生成Keil工程和相关初始化代码

知识回顾

之前已经利用STM32CubeMX生成过Keil工程和相关初始化代码了,可以去回顾一下,详情见:https://blog.csdn.net/wenhao_ir/article/details/146909781

选择芯片

打开STM32CubeMX,然后按下面的截图依次操作:
在这里插入图片描述
STM32F103C8T6:
在这里插入图片描述

在这里插入图片描述
双击上图红线的部分启动创建工程:
在这里插入图片描述

System Core配置

配置RCC(时钟源选择)

在这里插入图片描述
在这里插入图片描述

配置SYS(调试接口选择)

在这里插入图片描述

配置GPIO(配置PC组的第13个引脚为输出引脚)

接下来对GPIO的PC组的第13个引脚进行选择配置。
首先切换到“Pinout&Configuration项”:

在这里插入图片描述
然后按下面的操作找到引脚:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
设置成输出引脚:
在这里插入图片描述
在这里插入图片描述
这样对GPIO引脚的配置就完了。

配置I2C1控制器

在这里插入图片描述
在这里插入图片描述
参数那里用默认的配置就行了。

Clock Configuration(时钟配置)

在这里插入图片描述
在这里插入图片描述
输入完后点击回车键:
在这里插入图片描述
计算完成后的截图如下:
在这里插入图片描述

配置FreeRTOS

FreeRTOS的版本选择

在这里插入图片描述
在这里插入图片描述

FreeRTOS的核心参数配置

各界面尺寸调整下,把“Config parameters”调整到方便查看的大小:
在这里插入图片描述
看下FreeRTOS的关键参数对不对:
在这里插入图片描述

FreeRTOS的任务管理配置

使用 STM32CubeMX,可以手工添加任务、队列、信号量、互斥锁、定时器等等。但是本
课程不想严重依赖 STM32CubeMX,所以不会使用 STM32CubeMX 来添加这些对象,而是手写代
码来使用这些对象。
使用 STM32CubeMX 时,有一个默认任务,此任务无法删除,只能修改其名称和函数类型,
如下图所示:
在这里插入图片描述

工程项的配置

K003_FreeRTOS_my1
在这里插入图片描述
这里说明一下为什么Firmware Package Name and Version那里要改为V1.8.5,因为V1.8.6与之前在博文 https://blog.csdn.net/wenhao_ir/article/details/146674379 中安装的STM32F1xx_DFP不兼容。

在这里插入图片描述

生成工程

以上内容配置完成后,就可以点击生成工程了。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

用Keil打开生成的工程并配置好Debugger

用Keil打开生成的工程

在这里插入图片描述

配置好Debugger

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

添加LED的driver代码并进行测试

添加LED的相关C文件到工程

在工程目录E:\Keil_project\K003_FreeRTOS_my1\Drivers中新建目录my_driver
在这里插入图片描述

下载并解压:01_freertos_template.zip
在这里插入图片描述

在这里插入图片描述
把下面这4个文件复制到目录E:\Keil_project\K003_FreeRTOS_my1\Drivers\my_driver
在这里插入图片描述

在这里插入图片描述
说明一下,其实这里我们是想用driver_led.c,但是driver_led.c用到了driver_timer.c,所以driver_timer.c也要一并复制过来。

工程中增另一个group来添加以上文件:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
把目录E:\Keil_project\K003_FreeRTOS_my1\Drivers\my_driver添加到工程 的include目录中:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

主函数中添加相关代码

打开文件E:\Keil_project\K003_FreeRTOS_my1\Core\Src\freertos.c
然后加入下面的代码:

# include "driver_led.h"......Led_Test();

在这里插入图片描述

编译工程

在这里插入图片描述
在这里插入图片描述

烧写测试

在这里插入图片描述
在这里插入图片描述
然后发现绿灯一闪一炒了~~~~测试成功。

添加OLED的driver代码并进行测试

先把OLED模块插到开发板上

在这里插入图片描述

添加OLED的相关C文件到工程

注意:以下的操作是在上一个目录的基础上进行的。

复制下面4个文件到目录E:\Keil_project\K003_FreeRTOS_my1\Drivers\my_driver
在这里插入图片描述
在这里插入图片描述

然后工程中添加上文件driver_lcd.cdriver_oled.c
在这里插入图片描述
说明一下:driver_lcd.c是对driver_oled.c进行调用,也就是说driver_lcd.c是更抽象的一层。
在这里插入图片描述
在这里插入图片描述

复制字库文件到相关目录

在这里插入图片描述
上面这个文件复制到:E:\Keil_project\K003_FreeRTOS_my1\Drivers\my_driver
在这里插入图片描述

主函数中添加相关代码

# include "driver_lcd.h"
......
LCD_Test();

在这里插入图片描述
在这里插入图片描述

编译工程

在这里插入图片描述
在这里插入图片描述
上面的警告不用管。

烧写测试

在这里插入图片描述
此时发现OLED屏有显示了。

编写程序实现两个测试程序同时运行

代码修改和编写

因为我们在工程中引入了FreeRTOS,所以虽然两个测试程序都是while循环,所以还是可以同时运行:
在这里插入图片描述
在这里插入图片描述
具体的源码分析见视频的第2分44秒开始看…

修改E:\Keil_project\K003_FreeRTOS_my1\Core\Src\freertos.c的函数StartDefaultTask,函数StartDefaultTask是第一个任务的回调函数:
在这里插入图片描述
依照已有的 defaultTaskHandle再创建一个名叫LcdTask的任务:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

freertos.c修改后的完整源代码

修改后的E:\Keil_project\K003_FreeRTOS_my1\Core\Src\freertos.c完整源代码如下:

/* USER CODE BEGIN Header */
/********************************************************************************* File Name          : freertos.c* Description        : Code for freertos applications******************************************************************************* @attention** Copyright (c) 2025 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header *//* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
# include "driver_led.h"
# include "driver_lcd.h"/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables *//* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
osThreadId_t LcdTaskHandle;const osThreadAttr_t defaultTask_attributes = {.name = "defaultTask",.stack_size = 128 * 4,.priority = (osPriority_t) osPriorityNormal,
};const osThreadAttr_t LcdTask_attributes = {.name = "LcdTask",.stack_size = 128 * 4,.priority = (osPriority_t) osPriorityNormal,
};/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */void LcdTask(void *argument);/* USER CODE END FunctionPrototypes */void StartDefaultTask(void *argument);void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) *//*** @brief  FreeRTOS initialization* @param  None* @retval None*/
void MX_FREERTOS_Init(void) {/* USER CODE BEGIN Init *//* USER CODE END Init *//* USER CODE BEGIN RTOS_MUTEX *//* add mutexes, ... *//* USER CODE END RTOS_MUTEX *//* USER CODE BEGIN RTOS_SEMAPHORES *//* add semaphores, ... *//* USER CODE END RTOS_SEMAPHORES *//* USER CODE BEGIN RTOS_TIMERS *//* start timers, add new ones, ... *//* USER CODE END RTOS_TIMERS *//* USER CODE BEGIN RTOS_QUEUES *//* add queues, ... *//* USER CODE END RTOS_QUEUES *//* Create the thread(s) *//* creation of defaultTask */defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... */LcdTaskHandle = osThreadNew(LcdTask, NULL, &LcdTask_attributes);/* USER CODE END RTOS_THREADS *//* USER CODE BEGIN RTOS_EVENTS *//* add events, ... *//* USER CODE END RTOS_EVENTS */}/* USER CODE BEGIN Header_StartDefaultTask */
/*** @brief  Function implementing the defaultTask thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{/* USER CODE BEGIN StartDefaultTask *//* Infinite loop */Led_Test();/* USER CODE END StartDefaultTask */
}void LcdTask(void *argument)
{LCD_Test();
}/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application *//* USER CODE END Application */

再修改下driver_oled.c

然后我们把E:\Keil_project\K003_FreeRTOS_my1\Drivers\my_driver\driver_oled.c中的函数OLED_Test也修改一下,使最终我们的OLED屏上能不断计数。
在这里插入图片描述

void OLED_Test(void)
{int cnt = 0;OLED_Init();// 清屏OLED_Clear();while (1){// 在(0, 0)打印'A'OLED_PutChar(0, 0, 'A');// 在(1, 0)打印'Y'OLED_PutChar(1, 0, 'Y');// 在第0列第2页打印一个字符串"Hello World!"OLED_PrintString(0, 2, "Hello World!");OLED_PrintSignedVal(0, 4, cnt++);}
}

编译运行

在这里插入图片描述
在这里插入图片描述

下载测试

在这里插入图片描述
在这里插入图片描述
然后我们发绿色的LED在闪,同时OLED屏上也不断在计数…
在这里插入图片描述

附完整工程文件

https://pan.baidu.com/s/17m8R7hpnigDqcmNST8Pd_w?pwd=h9rx

相关文章:

使用STM32CubeMX和Keil在STM32上创建并运行一个简单的FreeRTOS多任务程序

目标 利用FreeRTOS运行两个任务,分别为点灯和OLED屏的显示。 利用STM32CubeMX生成Keil工程和相关初始化代码 知识回顾 之前已经利用STM32CubeMX生成过Keil工程和相关初始化代码了,可以去回顾一下,详情见:https://blog.csdn.ne…...

从查重报告入手的精准论文降重秘籍

每个同学在使用论文查重时,为何同一篇文章,可能重复率从10%—30%不等?归根结底还是使用了不同查重系统。其实不同的论文查重与论文AIGC检测系统的算法、数据及模型都不一样,那如何针对这些系统的“个性”精准降重,这篇…...

车辆控制解决方案

车辆控制解决方案 /* * Purpose: 优化车辆控制的功能 -> 用户在控制车辆状态时,实现控制按钮点击状态改变只触发一次onSwitchChange事件,不再下发控制指令,同时清除加载车辆实时状态的定时器status_interval直到有返回值再开启&#xff0…...

【机器学习】嘿马机器学习(算法篇)第14篇:决策树算法,学习目标【附代码文档】

本教程的知识点为:机器学习算法定位、 K-近邻算法 1.4 k值的选择 1 K值选择说明 1.6 案例:鸢尾花种类预测--数据集介绍 1 案例:鸢尾花种类预测 1.8 案例:鸢尾花种类预测—流程实现 1 再识K-近邻算法API 1.11 案例2:预测…...

Uubuntu20.04复现SA-ConvONet步骤

项目地址: tangjiapeng/SA-ConvONet: ICCV2021 Oral SA-ConvONet: Sign-Agnostic Optimization of Convolutional Occupancy Networks 安装步骤: 一、系统更新 检查系统是否已经更新到最新版本: sudo apt-get update sudo apt-get upgra…...

设计模式 三、结构型设计模式

一、代理模式 代理设计模式(Proxy Design Pattern)是一种结构型设计模式,它为其他对象提供了一个代理,以控制对这个对象的访问。 代理模式可以用于实现懒加载、安全访问控制、日志记录等功能。简单来说,代理模式 就是通…...

C语言函数实战指南:从零到一掌握函数设计与10+案例解析(附源码)

一、函数基础:程序的“积木块” (一)什么是函数? 函数是可重复使用的代码块,用于实现特定功能。如同乐高积木,通过组合不同函数,可快速构建复杂程序。例如: #include <stdio.h>// 函数定义:计算两数之和 int add(int a, int b) {return a + b; }int main() {…...

Prompt攻击是什么

什么是Prompt攻击 Prompt攻击(Prompt Injection/Attack) 是指通过精心构造的输入提示(Prompt),诱导大语言模型(LLM)突破预设安全限制、泄露敏感信息或执行恶意操作的攻击行为。其本质是利用模型对自然语言的理解漏洞,通过语义欺骗绕过防护机制。 Prompt攻击的精髓:学…...

【Linux网络#18】:深入理解select多路转接:传统I/O复用的基石

&#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;Linux—登神长阶 目录 一、前言&#xff1a;&#x1f525; I/O 多路转接 为什么需要I/O多路转接&#xff1f; 二、I/O 多路转接之 select 1. 初识 select2. select 函数原型2.1 关于 fd_set 结…...

华院计算3项应用成果入选钢铁行业智能制造解决方案推荐目录(2024年)

近日&#xff0c;中国钢铁工业协会发布《钢铁行业智能制造解决方案推荐目录&#xff08;2024年&#xff09;》。由中国钢铁工业协会、钢铁行业智能制造联盟共同开展了2024年钢铁行业智能制造解决方案及数字化转型典型场景应用案例遴选、智能制造创新大赛&#xff08;钢铁行业赛…...

python使用cookie、session、selenium实现网站登录(爬取信息)

一、使用cookie 这段代码演示了如何使用Python的urllib和http.cookiejar模块来实现网站的模拟登录&#xff0c;并在登录后访问需要认证的页面。 # 导入必要的库 import requests from urllib import request, parse# 1. 导入http.cookiejar模块中的CookieJar类&#xff0c;用…...

vector模拟实现2

文章目录 vector的模拟实现erase函数resize拷贝构造赋值重载函数模版构造及其细节结语 我们今天又见面啦&#xff0c;给生活加点impetus&#xff01;&#xff01;开启今天的编程之路 今天我们来完善vector剩余的内容&#xff0c;以及再探迭代器失效&#xff01; 作者&#xff…...

观察者模式在Java单体服务中的运用

观察者模式主要用于当一个对象发生改变时&#xff0c;其关联的所有对象都会收到通知&#xff0c;属于事件驱动类型的设计模式&#xff0c;可以对事件进行监听和响应。下面简单介绍下它的使用&#xff1a; 1 定义事件 import org.springframework.context.ApplicationEvent;pu…...

详解相机的内参和外参,以及内外参的标定方法

1 四个坐标系 要想深入搞清楚相机的内参和外参含义&#xff0c; 首先得清楚以下4个坐标系的定义&#xff1a; 世界坐标系&#xff1a; 名字看着很唬人&#xff0c; 其实没什么大不了的&#xff0c; 这个就是你自己定义的某一个坐标系。 比如&#xff0c; 你把房间的某一个点定…...

在线sql 转 rust 模型(Diesel、SeaORM),支持多数据 mysql, pg等

SQL 转 Rust 在 Rust 语言中&#xff0c;常用 Diesel 和 SeaORM 进行数据库操作。手写 ORM 模型繁琐&#xff0c;gotool.top 提供 SQL 转 Diesel、SeaORM 工具&#xff0c;自动生成 Rust 代码&#xff0c;提高开发效率。 特色 支持 Diesel / SeaORM&#xff0c;生成符合规范…...

高并发内存池(二):Central Cache的实现

前言&#xff1a;本文将要讲解的高并发内存池&#xff0c;它的原型是Google的⼀个开源项⽬tcmalloc&#xff0c;全称Thread-Caching Malloc&#xff0c;近一个月我将以学习为目的来模拟实现一个精简版的高并发内存池&#xff0c;并对核心技术分块进行精细剖析&#xff0c;分享在…...

[Windows] VutronMusic v1.6.0 音乐播放器纯净版,可登录同步

VutronMusic-简易好看的PC音乐播放器 链接&#xff1a;https://pan.xunlei.com/s/VOMq7P_fTyhLUXeGerDVhrCTA1?pwduvut# VutronMusic v1.6.0 音乐播放器纯净版&#xff0c;可登录同步...

macvlan 和 ipvlan 实现原理及设计案例详解

一、macvlan 实现原理 1. 核心概念 macvlan 允许在单个物理网络接口上创建多个虚拟网络接口&#xff0c;每个虚拟接口拥有 独立的 MAC 地址 和 IP 地址。工作模式&#xff1a; bridge 模式&#xff08;默认&#xff09;&#xff1a;虚拟接口之间可直接通信&#xff0c;类似交…...

【蓝桥杯】每日练习 Day19,20

目录 前言 蒙德里安的梦想 分析 最短Hamilton路径 分析 代码 乌龟棋 分析 代码 松散子序列 分析 代码 代码 前言 今天不讲数论&#xff08;因为上课学数论真是太难了&#xff0c;只学了高斯消元&#xff09;所以今天就不单独拿出来讲高斯消元了。今天讲一下昨天和…...

《AI大模型应知应会100篇》第7篇:Prompt Engineering基础:如何与大模型有效沟通

第7篇&#xff1a;Prompt Engineering基础&#xff1a;如何与大模型有效沟通 摘要 Prompt Engineering&#xff08;提示工程&#xff09;是与大模型高效沟通的关键技能。通过精心设计的Prompt&#xff0c;可以让模型生成更准确、更有用的结果。本文将从基础知识到高级策略&…...

微服务架构技术栈选型避坑指南:10大核心要素深度拆解

微服务架构的技术栈选型直接影响系统的稳定性、扩展性和可维护性。以下从10大核心要素出发&#xff0c;结合主流技术方案对比、兼容性评估、失败案例及优化策略&#xff0c;提供系统性选型指南。 1. 服务框架与通信 关键考量点 扩展性&#xff1a;框架需支持定制化扩展&#x…...

Elasticsearch 正排索引

一、正排索引基础概念 在 Elasticsearch 中&#xff0c;正排索引用于存储完整的文档内容&#xff0c;以便通过文档ID 快速定位文档的字段值。正排索引通过 Doc Values 和 Store Fields 两种形式&#xff0c;为聚合、排序、脚本计算等场景提供高效支持。Doc Values 的列式存储设…...

Spring实现WebScoket

SpringWeb编程方式分为Servlet模式和响应式。Servlet模式参考官方文档&#xff1a;Web on Servlet Stack :: Spring Framework&#xff0c;响应式&#xff08;Reacive&#xff09;参考官方文档&#xff1a;Web on Reactive Stack :: Spring Framework。 WebSocket也有两种编程方…...

Token是什么?

李升伟 整理 “Token” 是一个多义词&#xff0c;具体含义取决于上下文。以下是几种常见的解释&#xff1a; 1. 计算机科学中的 Token 定义&#xff1a;在编程和计算机科学中&#xff0c;Token 是源代码经过词法分析后生成的最小单位&#xff0c;通常用于编译器和解释器。 …...

odoo-045 ModuleNotFoundError: No module named ‘_sqlite3‘

文章目录 一、问题二、解决思路 一、问题 就是项目启动&#xff0c;本来好好地&#xff0c;忽然有一天报错&#xff0c;不知道什么原因。 背景&#xff1a; 我是在虚拟环境中使用的python3.7。 二、解决思路 虚拟环境和公共环境直接安装 sqlite3 都会报找不到这个库的问题…...

cesium加载CTB生成的地形数据

由于CTB生成的地形数据是压缩的&#xff08;gzip&#xff09;格式&#xff0c;需要在nginx加上特殊配置才可以正常加载&#xff0c;NGINX全部配置如下 worker_processes 1; events {worker_connections 1024; } http {include mime.types;default_type application/o…...

前端JS高阶技法:序列化、反序列化与多态融合实战

✨ 摘要 序列化与反序列化作为数据转换的核心能力&#xff0c;与多态这一灵活代码设计的核心理念&#xff0c;在现代前端开发中协同运作&#xff0c;提供了高效的数据通信与扩展性支持。 本文从理论到实践&#xff0c;系统解析&#xff1a; 序列化与反序列化的实现方式、使用…...

TS中的Class

基本用法 implements implements 关键字用于传递对类产生约束的数据类型 interface AnimalInfo{name:stringrace:stringage:number }interface AnimalCls{info:AnimalInfosayName():void} class Animal implements AnimalCls{info:AnimalInfoconstructor(info:AnimalInfo) {t…...

RustDesk 开源远程桌面软件 (支持多端) + 中继服务器伺服器搭建 ( docker版本 ) 安装教程

在需要控制和被控制的电脑上安装软件 github开源仓库地址 https://github.com/rustdesk/rustdesk/releases 蓝奏云盘备份 ( exe ) https://geek7.lanzouw.com/iPf592sadqrc 密码:4esi 中继服务器设置 使用docker安装 sudo docker image pull rustdesk/rustdesk-server sudo…...

【计网速通】计算机网络核心知识点与高频考点——数据链路层(二)

数据链路层核心知识点&#xff08;二&#xff09; 涵盖局域网、广域网、介质访问控制&#xff08;MAC层&#xff09;及数据链路层设备 上文链接&#xff1a;https://blog.csdn.net/weixin_73492487/article/details/146571476 一、局域网&#xff08;LAN,Loacl Area Network&am…...