启明欣欣STM32开发板运行ThreadX

news2024/11/16 1:34:28

ThreadX是非常优秀的RTOS,微软收购了ThreadX后就开源了,后来又交给Eclipse基金会,
在这里插入图片描述

本文讲述如何在STM32上运行ThreadX,使用CubeMX来实现。本人环境如下,

  • CM4芯片:STM32F407ZGT6,内存192KB,flash是1MB,频率最高168M Hz
  • OS:Win11
  • CubeMX:6.12.0
  • Keil:5.40.0
  • 下载器:ST-Link V2

一 搭建工程

使用CubeMX搭建工程,打开CubeMX后点击ACCESS TO MCU SELECTOR,
在这里插入图片描述

在新界面里输入STM32F407ZGT6

在这里插入图片描述

此时在右侧会显示出MCU信息,这里点击第一个,然后点击右上角的Start Project来创建工程,

![[Pasted image 20240818081628.png]]

设置时钟

在新界面里的Pinout & Configuration里选择RCC,然后高速时钟和低速时钟都选择Crystal/Ceramic Resonator

![[Pasted image 20240818082030.png]]

PS:启明欣欣的板子,其外部接了2个晶振,一个8M,一个32.768K,前者用于高速时钟,后者用于低速时钟,如果低速时钟没有外接晶振,那么就选disable。

此时点击Clock Configuration

![[Pasted image 20240818082621.png]]

然后按照红框里的步骤一个个更改,

![[Pasted image 20240818082811.png]]

第4步输入频率后回车,CubeMX会自动调整,非常方便。另外,可以看到低速时钟LSE的输入频率是32.768K,这个也可以修改,需要结合实际。

设置SYS

回到Pinout & Configuration,然后点击SYS,右侧的选项按照如下进行选择,

![[Pasted image 20240818083603.png]]

设置输出引脚

开发板上有3个LED,如下,

![[Pasted image 20240817223755.png]]

LED连接在MCU的引脚上,连接情况如下,

  • LED0 ---- PE3
  • LED1 ---- PE4
  • LED2 ---- PG9

当引脚输出低电平灯就会点亮,输出高电平灯就会熄灭。美中不足的地方是这3个灯都是红灯,如果是不同颜色的灯就更好了。

回到Pinout & Configuration,然后在右侧的Pinout view里找到这三个引脚并设置为输出,可以在右下角的搜索框里输入引脚名,软件会自动定位到这个引脚,例如输入PE3,

![[Pasted image 20240818083706.png]]

PE3对应的引脚会闪烁黑色,单击该引脚会弹出配置选项,这里选择GPIO_Output

![[Pasted image 20240818084404.png]]

同理把PE4和PG9也配置为输出,然后点击左侧的GPIO,在右侧选择PE3,最后在下面的配置里把PE3设置为默认输出高,上拉,中等速度。

![[Pasted image 20240818084819.png]]

同理,对PE4和PG9进行相同配置。

引入ThreadX

Software Packs里点击Select Components

![[Pasted image 20240818085921.png]]

在弹出的界面里找到X-CUBE-AZRTOS-F4,如果第一次打开,右边会有个Install按钮,点击进行下载,本人因为已经下载过了,所以没有这个按钮

![[Pasted image 20240818090045.png]]

PS:如果你是别的芯片,可以根据实际情况选择对应的版本

点击后展开,然后勾选这个Core就可以了,最后点击右下角的OK,

![[Pasted image 20240818090255.png]]

回到主界面后点击展开Middleware and Software Packs,然后按照如下红框步骤引入ThreadX

![[Pasted image 20240818090441.png]]

工程配置

点击Project Manager,然后在Project里对红框标注的地方进行自定义修改

![[Pasted image 20240818090956.png]]

接着是Code Generator,按照如下勾选,也可以根据自己需要进行修改

![[Pasted image 20240818091151.png]]

设置完毕后点击右上角的GENERATE CODE来生成Keil工程

![[Pasted image 20240818091237.png]]


二 添加任务

在源码里打开app_thread.c,这个是ThreadX留给用户添加自定义任务的源文件,

![[Pasted image 20240817224221.png]]

打开后先在USER CODE BEGIN Includes下引入"main.h",

![[Pasted image 20240817224420.png]]

然后在USER CODE BEGIN PD下添加栈大小的宏定义,

![[Pasted image 20240817224800.png]]

然后在USER CODE BEGIN PV下添加栈空间数组和线程指针定义,总共3个,

![[Pasted image 20240817224930.png]]

接着在USER CODE BEGIN PFP里添加任务的函数声明,

![[Pasted image 20240817225226.png]]

接着在函数App_ThreadX_Init里使用tx_thread_create来创建三个任务,

![[Pasted image 20240817225355.png]]

最后是在USER CODE BEGIN 1里添加任务函数的定义,

![[Pasted image 20240817225918.png]]

三个函数里都有一个while循环,循环里以不同的间隔来闪烁LED灯。

最后完整源文件内容如下,

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    app_threadx.c
  * @author  MCD Application Team
  * @brief   ThreadX applicative file
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2021 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 "app_threadx.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "main.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define THREAD_STACK_SIZE   1024

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */

UCHAR thread_stack1[THREAD_STACK_SIZE];
TX_THREAD thread_ptr1;

UCHAR thread_stack2[THREAD_STACK_SIZE];
TX_THREAD thread_ptr2;

UCHAR thread_stack3[THREAD_STACK_SIZE];
TX_THREAD thread_ptr3;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */

VOID LED1_thread_entry(ULONG thread_input);
VOID LED2_thread_entry(ULONG thread_input);
VOID LED3_thread_entry(ULONG thread_input);

/* USER CODE END PFP */

/**
  * @brief  Application ThreadX Initialization.
  * @param memory_ptr: memory pointer
  * @retval int
  */
UINT App_ThreadX_Init(VOID *memory_ptr)
{
  UINT ret = TX_SUCCESS;
  TX_BYTE_POOL *byte_pool = (TX_BYTE_POOL*)memory_ptr;

  /* USER CODE BEGIN App_ThreadX_Init */
  (void)byte_pool;
  tx_thread_create(&thread_ptr1, "LED1_thread", LED1_thread_entry, 0, thread_stack1, THREAD_STACK_SIZE, 15, 15, 1, TX_AUTO_START);
  tx_thread_create(&thread_ptr2, "LED2_thread", LED2_thread_entry, 0, thread_stack2, THREAD_STACK_SIZE, 15, 15, 1, TX_AUTO_START);
  tx_thread_create(&thread_ptr3, "LED3_thread", LED3_thread_entry, 0, thread_stack3, THREAD_STACK_SIZE, 15, 15, 1, TX_AUTO_START);

  /* USER CODE END App_ThreadX_Init */

  return ret;
}

/**
  * @brief  MX_ThreadX_Init
  * @param  None
  * @retval None
  */
void MX_ThreadX_Init(void)
{
  /* USER CODE BEGIN  Before_Kernel_Start */

  /* USER CODE END  Before_Kernel_Start */

  tx_kernel_enter();

  /* USER CODE BEGIN  Kernel_Start_Error */

  /* USER CODE END  Kernel_Start_Error */
}

/* USER CODE BEGIN 1 */
VOID LED1_thread_entry(ULONG thread_input)
{
  while(1)
  {
    HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_3);
    HAL_Delay(100);
  }

}

VOID LED2_thread_entry(ULONG thread_input)
{
  while(1)
  {
    HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_4);
    HAL_Delay(300);
  }
}

VOID LED3_thread_entry(ULONG thread_input)
{
  while(1)
  {
    HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_9);
    HAL_Delay(500);
  }
}

/* USER CODE END 1 */


三 编译和运行

使用Keil进入编译,编译器记得选成6.x系列的,

![[Pasted image 20240817230313.png]]

为了加快编译速度,取消Browse Information的勾选,

![[Pasted image 20240817230348.png]]

编译完毕后把程序烧录到开发板上,然后复位一下,就可以发现3个LED灯以不同的频率进行闪烁。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2050042.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分布式事务方案——基于两阶段提交的 XA事务

分布式事务方案——基于两阶段提交的 XA事务 在这篇文章中深入理解分布式事务中的两阶段提交(2PC),什么是2PC,2PC原理是怎样?2PC有没有什么问题?解决方案?无法解决的情况? 我们详细…

24/8/18算法笔记 目标导向强化学习

目标导向强化学习(Goal-Oriented Reinforcement Learning,简称GORL)是强化学习的一个分支,它关注于智能体如何通过与环境的交互来实现特定的目标或任务。与传统的强化学习不同,目标导向强化学习更加关注目标的设定和达…

图像数据处理13

三、空域滤波 3.1滤波器的基本概念 什么是滤波? 简单来说就是从干扰信号中提取出有用的信号 3.1.1空域滤波(Spatial Domain Filtering) 空域滤波适用于简单的滤波任务,直接对图像的像素空间进行操作。它通过对图像中的每个像…

如何选择流量与商业潜力兼备的SEO关键词?

如何选择流量与商业潜力兼备的SEO关键词? 你选择的关键词可以成就或破坏你的SEO活动。 如果你明智地选择关键词,那么你制作的内容将有可能月复一月地吸引有价值的自然搜索流量。如果你选择了错误的关键词,你的内容将只能吸引低价值的流量&a…

Java流程控制07:增强for循环

本节内容视频链接:Java流程控制10:增强for循环_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV12J41137hu?p42&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 Java中的增强for循环(‌也称为“for-each”循环)‌是…

实用好软-----电脑端好用的免费音乐下载小工具 简单 快速

目前很多很多音乐软件都是收费的。要么是试听。前段时间分享了一款嗅探工具感觉很不错。今天分享的这款小工具超小。下载只有3M大小。解压后运行窗口简单。直接输入歌曲名字即可搜索出来。然后选择下载即可 界面 测试了下还是比较好用的。而且下载很快 ,不过软件显…

Ajax-02.Axios

Axios入门 1.引入Axios的js文件 <script src"js/axios-0.18.0.js"></script> Axios 请求方式别名: axios.get(url[,config]) axios.delete(url[,config]) axios.post(url[,data[,config]]) axios.put(url[,data[,config]]) 发送GET/POST请求 axios.get…

PROLOG实现亲属关系小型演绎数据库

问题 试编写一个描述亲属关系的PROLOG程序&#xff0c;然后给出一些事实数据&#xff0c;建立一个小型演绎数据库。 代码实现 % 基本事实 father(john, mike). father(john, lisa). father(boluo, ana). father(boluo, peter).mother(mary, mike). mother(mary, lisa). mother…

大厂进阶五:React源码解析之深度剖析Diff算法

本文主要针对React源码进行解析&#xff0c;内容有&#xff1a; 1、Diff算法原理、两次遍历 2、Diff瓶颈及限制 3、Diff更新之单节点和多节点原理 一、Diff源码解析 以下是关于 React Diff 算法的详细解析及实例&#xff1a; 1、React Diff 算法的基本概念和重要性 1.1 概念…

【串口助手开发】--温度曲线图实时显示功能,全流程小白教程,zedgraph控件的使用方法,Visual Studio 软件C#语言

1、ZedGraph.dll 控件下载 链接&#xff1a;下载ZedGraph&#xff08;ZedGraph.dll 和ZedGraph.Web.dll文件&#xff09; 打开链接后&#xff0c;图中红框显示的是仅下载zedgraph控件&#xff0c;本文所需的文件是ZedGraph.dll。 2、ZedGraph.dll 控件添加进Visual Studio 软…

【Arduino】ATmega328PB 连接 LSM6DS3 姿态传感器,并读数据(不确定 ESP 系列是否可行,但大概率是可行的)

总览 1.初始化 ATmega328PB&#xff0c;默认大家已经完成了 328 的配置准备工作&#xff0c;已经直接能够向里面写入程序 2.接线&#xff0c;然后验证 mega328 的 I2C 设备接口能否扫描到 LSM6DS3 3.编写代码&#xff0c;上传&#xff0c;查看串口数据。完成。 一、初始化 AT…

履带无人车+无人机+自组网:空地一体化技术详解

履带无人车、无人机与自组网技术的结合&#xff0c;构成了空地一体化技术的核心框架&#xff0c;这种技术在多个领域展现出巨大的潜力和应用价值。以下是对该技术的详细解析&#xff1a; 一、技术概述 空地一体化技术巧妙融合了履带无人车、无人机以及自组网技术&#xff0c;…

EPIC Institute of Technology Round August 2024 (Div. 1 + Div. 2)

前言 又是一场压线不掉分的比赛。 Standings&#xff1a;2706 题目链接&#xff1a;Dashboard - EPIC Institute of Technology Round August 2024 (Div. 1 Div. 2) - Codeforces A. Distanced Coloring 题意&#xff1a; 给一个 n * m 的矩阵&#xff0c;涂色&#xff0c;要…

pkg 打包后运行报错 Cannot mkdir in a snapshot. Try mountpoints instead.

把项目中使用到的 __dirname 类似这样的 join(__dirname, ./config)替换为 process.cwd() __dirname&#xff1a;获取的是当前文件目录路径&#xff0c;二进制文件内部的文件(pkg打包的二进制文件是快照文件&#xff0c;里面的文件只能读不能修改新增)&#xff0c;比如&#x…

区块链基础

1、区块链定义 区块链技术本质上是一个去中心化的数据库&#xff0c;它是比特币的核心技术与基础架构&#xff0c;是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。狭义来讲&#xff0c;区块链是一种按照时间顺序将数据区块以顺序相连的方式组合…

XSS-跨站脚本攻击

目录 XSS简介 XSS分类 反射型XSS&#xff08;非持久型XSS&#xff09; 存储型XSS&#xff08;持久型XSS&#xff09; DOM型XSS HTML文档解析过程 例题 HTML解析 字符实体(character entities) HTML字符实体(HTML character entities) 字符引用&#xff08;character…

程序员如何写PLC程序

PLC是可编程逻辑控制器的简称&#xff0c;常用的编程语言是IEC61131-3&#xff08;梯形图、结构化文本、指令表、功能块、顺序功能图&#xff09;和西门子的SCL。程序员常用的编程语言是JS、Java、Python、C/C、Go等。PLC广泛采用编程工具有codesys、博图等。程序员常用的编程工…

用Python实现9大回归算法详解——06. K近邻回归算法

1. K近邻回归的基本概念 K近邻回归&#xff08;K-Nearest Neighbors Regression, KNN Regression&#xff09;是一种基于实例的学习方法。与传统的回归模型不同&#xff0c;KNN回归不通过显式的函数来建模数据之间的关系&#xff0c;而是通过查找输入样本的“邻居”来进行预测…

【PDF技巧】如何编辑忘记密码PDF文件?

PDF文件打开之后&#xff0c;发现编辑功能都是灰色的&#xff0c;无法使用&#xff0c;无法编辑PDF文件&#xff0c;遇到这种情况&#xff0c;因为PDF文件设置了限制编辑导致的。一般情况下&#xff0c;我们只需要输入PDF密码&#xff0c;将限制编辑取消就可以正常编辑文件了&a…