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

保姆级教程:在GD32F103上用Keil MDK5和FreeRTOS 202411.00创建你的第一个多任务LED闪烁项目

保姆级教程在GD32F103上用Keil MDK5和FreeRTOS 202411.00创建你的第一个多任务LED闪烁项目嵌入式开发的世界里实时操作系统RTOS正变得越来越重要。对于刚接触GD32系列芯片或FreeRTOS的开发者来说如何快速搭建一个可靠的多任务环境往往是第一个需要跨越的门槛。本文将带你从零开始在Keil MDK5环境下为GD32F103芯片配置FreeRTOS 202411.00并实现一个直观的多任务LED闪烁项目。不同于单纯的移植教程我们将通过一个完整的项目实践让你在动手过程中掌握关键知识点。1. 环境准备与工程创建在开始之前确保你已经准备好以下工具和环境Keil MDK5建议使用5.30或更高版本GD32F10x系列芯片支持包从官网下载并安装FreeRTOS 202411.00源码从FreeRTOS官网获取最新稳定版本首先在Keil中创建一个新的工程打开Keil MDK5选择Project → New μVision Project为项目命名如GD32F103_FreeRTOS_LED并选择保存路径在弹出的设备选择窗口中搜索并选择GD32F103C8T6根据你的具体芯片型号选择在Manage Run-Time Environment窗口中勾选以下组件CMSIS → COREDevice → StartupDevice → StdPeriph Drivers → GPIO提示如果你使用的是其他型号的GD32F103芯片记得在工程选项中修改对应的设备型号和启动文件。2. FreeRTOS源码的组织与导入获取FreeRTOS源码后我们需要有策略地组织文件结构。推荐采用以下目录结构Project/ ├── FreeRTOS/ │ ├── include/ # FreeRTOS头文件 │ ├── portable/ # 移植相关文件 │ │ ├── Keil/ # Keil专用文件 │ │ ├── MemMang/ # 内存管理方案 │ │ └── RVDS/ # ARM Cortex-M相关移植文件 │ └── *.c # FreeRTOS核心源文件 ├── User/ │ ├── FreeRTOSConfig.h # FreeRTOS配置文件 │ └── main.c # 用户应用程序 └── GD32F10x_Lib/ # GD32标准外设库将FreeRTOS源码中的关键文件复制到对应位置# 从FreeRTOS源码包中复制核心文件 cp FreeRTOS/Source/include/* Project/FreeRTOS/include/ cp FreeRTOS/Source/*.c Project/FreeRTOS/ # 复制移植相关文件 cp FreeRTOS/Source/portable/RVDS/ARM_CM3/* Project/FreeRTOS/portable/RVDS/ cp FreeRTOS/Source/portable/MemMang/heap_4.c Project/FreeRTOS/portable/MemMang/在Keil工程中添加这些文件右键点击Target 1选择Add Group创建FreeRTOS_CORE和FreeRTOS_PORTABLE两个组将FreeRTOS/*.c添加到FreeRTOS_CORE组将FreeRTOS/portable/MemMang/heap_4.c和FreeRTOS/portable/RVDS/port.c添加到FreeRTOS_PORTABLE组3. 配置FreeRTOS与GD32F103的适配FreeRTOSConfig.h是FreeRTOS的核心配置文件我们需要根据GD32F103的特性进行定制。以下是最关键的配置项#define configCPU_CLOCK_HZ (SystemCoreClock) #define configTOTAL_HEAP_SIZE ((size_t)(10 * 1024)) // 根据实际芯片RAM大小调整 #define configMINIMAL_STACK_SIZE ((unsigned short)128) #define configMAX_PRIORITIES (5) // 中断优先级配置Cortex-M3使用4位优先级 #define configKERNEL_INTERRUPT_PRIORITY 255 #define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 // 包含必要的头文件 #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) #include stdint.h extern uint32_t SystemCoreClock; #endif对于GD32F103与FreeRTOS的中断处理需要特别注意以下几点在gd32f10x_it.c中注释掉以下函数避免与FreeRTOS的实现冲突// void SVC_Handler(void) {} // void PendSV_Handler(void) {} // void SysTick_Handler(void) {}在main.c中重新实现SysTick中断处理函数#include FreeRTOS.h #include task.h extern void xPortSysTickHandler(void); void SysTick_Handler(void) { if(xTaskGetSchedulerState() ! taskSCHEDULER_NOT_STARTED) { xPortSysTickHandler(); } }确保在FreeRTOSConfig.h中启用相关功能#define INCLUDE_xTaskGetSchedulerState 1 #define configUSE_IDLE_HOOK 0 #define configUSE_TICK_HOOK 0 #define configUSE_MALLOC_FAILED_HOOK 04. 创建多任务LED闪烁应用现在我们可以开始编写多任务LED闪烁的应用代码了。我们将创建两个独立的任务分别控制两个LED以不同的频率闪烁。首先配置硬件假设我们使用PB4和PB5控制两个LEDstatic void hardware_init(void) { // 使能GPIOB时钟 rcu_periph_clock_enable(RCU_GPIOB); // 配置PB4和PB5为推挽输出 gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4 | GPIO_PIN_5); // 初始化SysTick定时器1ms中断 systick_config(); }接下来定义任务函数和创建任务// 任务优先级定义 #define TASK_LED1_PRIORITY (tskIDLE_PRIORITY 1) #define TASK_LED2_PRIORITY (tskIDLE_PRIORITY 2) // 任务堆栈大小 #define TASK_LED1_STACK_SIZE (configMINIMAL_STACK_SIZE * 2) #define TASK_LED2_STACK_SIZE (configMINIMAL_STACK_SIZE * 2) // 任务句柄 TaskHandle_t xTaskLed1Handle NULL; TaskHandle_t xTaskLed2Handle NULL; // LED1任务函数500ms间隔 static void task_led1(void *pvParameters) { const TickType_t xDelay pdMS_TO_TICKS(500); for(;;) { gpio_bit_write(GPIOB, GPIO_PIN_4, SET); vTaskDelay(xDelay); gpio_bit_write(GPIOB, GPIO_PIN_4, RESET); vTaskDelay(xDelay); } } // LED2任务函数300ms间隔 static void task_led2(void *pvParameters) { const TickType_t xDelay pdMS_TO_TICKS(300); for(;;) { gpio_bit_write(GPIOB, GPIO_PIN_5, SET); vTaskDelay(xDelay); gpio_bit_write(GPIOB, GPIO_PIN_5, RESET); vTaskDelay(xDelay); } }在main()函数中初始化硬件并创建任务int main(void) { // 硬件初始化 hardware_init(); // 创建LED1任务 xTaskCreate(task_led1, LED1, TASK_LED1_STACK_SIZE, NULL, TASK_LED1_PRIORITY, xTaskLed1Handle); // 创建LED2任务 xTaskCreate(task_led2, LED2, TASK_LED2_STACK_SIZE, NULL, TASK_LED2_PRIORITY, xTaskLed2Handle); // 启动调度器 vTaskStartScheduler(); // 正常情况下不会执行到这里 for(;;); }5. 调试与常见问题解决在开发过程中你可能会遇到以下常见问题问题1编译时报undefined reference to vApplication...现象链接时出现关于vApplicationIdleHook等函数的未定义引用错误。原因FreeRTOS默认启用了某些钩子函数但没有提供实现。解决方案在FreeRTOSConfig.h中禁用这些钩子函数#define configUSE_IDLE_HOOK 0 #define configUSE_TICK_HOOK 0 #define configUSE_MALLOC_FAILED_HOOK 0问题2程序运行后LED不闪烁可能原因SysTick中断配置不正确任务优先级设置不当堆栈空间不足排查步骤确认SysTick_Handler是否正确实现并调用了xPortSysTickHandler使用调试器检查任务是否被正确创建增加任务堆栈大小并重新测试问题3程序运行一段时间后死机可能原因堆空间不足导致内存分配失败任务堆栈溢出解决方案增加configTOTAL_HEAP_SIZE的值使用FreeRTOS提供的堆栈检查功能#define configCHECK_FOR_STACK_OVERFLOW 2并实现vApplicationStackOverflowHook函数用于调试6. 进阶优化与扩展完成基础功能后我们可以考虑以下优化使用静态内存分配对于资源受限的嵌入式系统静态内存分配更可靠// 定义任务控制块和堆栈 StaticTask_t xTaskLed1TCB; StackType_t xTaskLed1Stack[TASK_LED1_STACK_SIZE]; // 创建任务时使用静态分配 xTaskCreateStatic(task_led1, LED1, TASK_LED1_STACK_SIZE, NULL, TASK_LED1_PRIORITY, xTaskLed1Stack, xTaskLed1TCB);添加任务间通信例如使用队列实现任务同步// 创建队列 QueueHandle_t xLedQueue xQueueCreate(5, sizeof(uint8_t)); // 在任务中发送消息 uint8_t led_state 1; xQueueSend(xLedQueue, led_state, portMAX_DELAY); // 在另一个任务中接收消息 uint8_t received_state; if(xQueueReceive(xLedQueue, received_state, pdMS_TO_TICKS(100)) pdPASS) { // 处理接收到的消息 }使用事件组事件组是另一种高效的任务同步机制// 创建事件组 EventGroupHandle_t xLedEvents xEventGroupCreate(); // 设置事件位 xEventGroupSetBits(xLedEvents, 0x01); // 等待事件 EventBits_t uxBits xEventGroupWaitBits(xLedEvents, 0x03, pdTRUE, pdFALSE, portMAX_DELAY);通过这个完整的项目实践你不仅学会了如何在GD32F103上移植FreeRTOS还掌握了多任务编程的基本方法。在实际项目中可以根据需求进一步探索FreeRTOS提供的各种功能如软件定时器、任务通知等高级特性。

相关文章:

保姆级教程:在GD32F103上用Keil MDK5和FreeRTOS 202411.00创建你的第一个多任务LED闪烁项目

保姆级教程:在GD32F103上用Keil MDK5和FreeRTOS 202411.00创建你的第一个多任务LED闪烁项目 嵌入式开发的世界里,实时操作系统(RTOS)正变得越来越重要。对于刚接触GD32系列芯片或FreeRTOS的开发者来说,如何快速搭建一个…...

从GRACE gfc到可用数据:一个MATLAB脚本搞定CSR/GFZ/JPL三大机构数据预处理

GRACE数据处理实战:MATLAB自动化流水线构建指南 在气候变化和水文循环研究中,GRACE卫星数据已成为不可或缺的重要资源。面对CSR、GFZ和JPL三大机构发布的多样化数据格式,研究人员常常需要花费大量时间在数据预处理环节。本文将分享一套完整的…...

FPGA开发板吃灰?用Quartus II和你的旧板子复活一个硬件乘法器(4位乘数/拨码开关输入/LED显示)

让闲置FPGA开发板重获新生:手把手实现4位硬件乘法器 翻箱倒柜找出尘封已久的FPGA开发板,是不是总想着能做点有趣的东西?这次我们不用复杂的IP核,就用最基础的拨码开关和LED灯,配合Quartus II打造一个看得见摸得着的4位…...

保姆级教程:手把手教你用VCSA 8.0.3接管Windows AD域,实现统一登录

企业级虚拟化身份管理:VCSA 8.0.3与Windows AD域深度集成实战 在数字化转型浪潮中,企业IT基础设施的集中化管理已成为刚需。当虚拟化平台规模扩大至数百台主机时,如何确保管理员和开发人员既能高效访问资源,又能遵循最小权限原则&…...

SecGPT-14B模型量化:降低OpenClaw长期运行的Token消耗

SecGPT-14B模型量化:降低OpenClaw长期运行的Token消耗 1. 为什么需要量化SecGPT-14B模型 当我第一次在OpenClaw项目中接入SecGPT-14B模型时,就被它的安全分析能力惊艳到了。这个模型能精准识别代码漏洞、异常网络请求和各种安全威胁,让我的…...

3种简单方法实现Windows与Linux双系统文件无缝共享的终极方案

3种简单方法实现Windows与Linux双系统文件无缝共享的终极方案 【免费下载链接】btrfs WinBtrfs - an open-source btrfs driver for Windows 项目地址: https://gitcode.com/gh_mirrors/bt/btrfs 跨平台文件共享一直是Windows与Linux双系统用户面临的核心痛点。你是否曾…...

实战驱动:基于快马平台生成集成openclaw的ubuntu自动化测试项目实例

在自动化测试和数据抓取领域,openclaw凭借其强大的浏览器控制能力成为开发者的得力助手。最近我在一个电商价格监控项目中需要快速搭建环境,发现通过InsCode(快马)平台可以轻松生成包含完整环境配置和实战示例的项目模板,这里分享下我的实践过…...

Windows右键菜单瘦身秘籍:3个技巧让你的文件操作快如闪电

Windows右键菜单瘦身秘籍:3个技巧让你的文件操作快如闪电 【免费下载链接】ContextMenuManager 🖱️ 纯粹的Windows右键菜单管理程序 项目地址: https://gitcode.com/gh_mirrors/co/ContextMenuManager 你是否经历过这样的尴尬时刻?在…...

新手必看:用Wireshark分析CTF流量题,手把手教你从抓包到找到Flag

从零玩转Wireshark:CTF流量分析实战指南 第一次打开Wireshark时,满屏跳动的数据包就像天书一样让人头晕目眩。但别担心,每个网络安全高手都曾经历过这个阶段。本文将带你走进CTF流量分析的世界,从最基础的Wireshark操作开始&#…...

博士论文的“破茧”时刻:好写作AI如何陪你走完最后一公里

一个论文科普博主眼中的“学术极限运动辅助器” 亲爱的博士生朋友们,今天我们聊点“不轻松”的话题。 当你的同学在朋友圈晒工作、晒娃、晒旅游时,你在晒什么?晒图书馆的凌晨三点,晒被导师批注得“血肉模糊”的草稿,晒…...

毫米波雷达数据处理避坑指南:AWR2243的complex1x与complex2x格式到底怎么选?

毫米波雷达数据格式深度解析:AWR2243的complex1x与complex2x实战选择策略 在毫米波雷达信号处理的实际工程中,ADC数据格式的选择往往被当作一个简单的配置参数,直到工程师们在后期信号处理阶段遇到难以解释的噪声问题或成像质量下降时&#x…...

Ubuntu 24.04 主机名修改全攻略:从基础到自动化脚本

1. 主机名修改基础:为什么需要关注这个小细节? 刚接触Ubuntu系统的朋友可能会好奇:主机名不就是个名字吗?为什么需要专门写篇文章来讲修改方法?我刚开始用Linux时也这么想过,直到有次在局域网里找了半小时的…...

新手福音:用快马平台零代码基础生成产区标准对比网页

新手福音:用快马平台零代码基础生成产区标准对比网页 作为一个刚接触编程的新手,我一直想学习如何用网页展示地理数据的差异。最近在研究农产品产区划分时,发现一线产区和二线产区的标准对比是个很好的学习案例。通过InsCode(快马)平台&…...

告别网络调试焦虑:用STM32CubeMX+FreeRTOS,给LAN8720A和LWIP做个“健康检查”与性能小优化

STM32网络子系统深度优化:从连通性测试到工业级稳定性实战 当你熬夜调试的嵌入式设备终于能Ping通时,那种喜悦感堪比程序员第一次写出"Hello World"。但很快你会发现,真正的挑战才刚刚开始——那些在演示视频里永远不会出现的诡异断…...

动手学深度学习|LeNet 超详细讲解:第一个经典卷积神经网络是怎么工作的?

前言在学习完卷积层、池化层之后,我们终于来到了卷积神经网络发展史上一个非常经典的模型——LeNet。它虽然结构不深,放到今天看甚至有点“朴素”,但它的意义非常大:LeNet 是深度学习历史上最早一批成功应用的卷积神经网络之一。很…...

Naive UI 主题色定制实战:从组件覆盖到全局配置

1. 为什么需要定制Naive UI主题色? 当你使用Naive UI开发项目时,默认的绿色主题可能并不符合你的品牌风格。比如我们团队最近接手的一个金融类项目,客户要求整体UI采用深蓝色调,这时候就需要对Naive UI的主题色进行深度定制。主题…...

通讯协议(四)——SPI通信:从时序图到模式配置的实战解析

1. SPI通信基础:从四线制到主从架构 第一次接触SPI通信时,我被它简洁的物理连接方式惊艳到了。相比其他通信协议,SPI只需要四根线就能实现全双工通信,这让电路设计变得异常清爽。MISO(主入从出)、MOSI&…...

如何用STM32CubeMX快速配置Simulink硬件在环项目?STM32G4xx实战演示

STM32CubeMX与Simulink硬件在环开发实战:从零构建电机控制验证平台 当工程师需要验证一个新型电机控制算法时,传统方式往往需要经历PCB设计、焊接调试、反复烧录的漫长周期。而现在,通过STM32CubeMX与Simulink的硬件在环(HIL&…...

在Jetson Orin NX上为PyTorch 2.0编译TorchVision 0.15:一份完整的避坑与问题解决记录

在Jetson Orin NX上为PyTorch 2.0编译TorchVision 0.15:一份完整的避坑与问题解决记录 Jetson Orin NX作为英伟达新一代边缘计算设备,凭借其强大的AI算力和紧凑的尺寸,成为众多开发者的首选。然而,当我们需要在ARM架构上为特定版本…...

告别手动填表!用n8n+企业微信,5分钟搞定每日销售报表自动推送

告别手动填表!用n8n企业微信,5分钟搞定每日销售报表自动推送 每天早晨9点,销售团队的工作群准时弹出昨日业绩报表——这不是IT部门的功劳,而是一个由n8n驱动的全自动化流程。当传统企业还在用Excel手工汇总数据时,前沿…...

如何用Dify API和GPT-4o高效识别图片?附避坑指南

如何用Dify API和GPT-4o高效识别图片?附避坑指南 在当今数字化时代,图片识别技术已成为众多应用场景中的核心需求。从电商平台的商品自动分类到社交媒体内容审核,再到医疗影像分析,高效准确的图片识别能力正变得越来越重要。Dify作…...

项目经理面试必备:5 大核心问题拆解与高通过率回答策略

1. 项目经理面试的核心问题解析 面试官抛出"请描述你负责过的一个典型项目"时,往往不是想听流水账。我当年第一次面试时就犯过这个错误,花了10分钟详细描述项目背景,结果面试官直接打断:"所以你到底做了什么&#…...

WandEnhancer终极指南:WeMod本地增强与功能解锁的完整实践

WandEnhancer终极指南:WeMod本地增强与功能解锁的完整实践 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/gh_mirrors/we/Wand-Enhancer WandEnhancer是一款专为WeMod客户…...

新手福音:跳过jdk安装,在快马平台开启你的java编程第一课

作为一个Java新手,最让人头疼的往往不是学习语法本身,而是那些繁琐的环境配置。记得我刚开始学Java时,光是安装JDK就折腾了大半天,还要配置环境变量、测试安装是否成功...这些准备工作简直能把学习的热情消磨殆尽。 不过现在有了I…...

边缘设备福音:在树莓派上部署CosyVoice-300M Lite语音合成服务

边缘设备福音:在树莓派上部署CosyVoice-300M Lite语音合成服务 1. 为什么选择CosyVoice-300M Lite 1.1 专为边缘计算优化的语音合成方案 在物联网和边缘计算场景中,我们经常需要在资源受限的设备上运行AI模型。传统语音合成方案要么体积庞大&#xff…...

昇腾310B4 NPU实战:用MindX SDK给Unet模型推理加速,并与CPU/ONNX Runtime性能全面对比

昇腾310B4 NPU实战:Unet模型推理加速与多平台性能深度评测 边缘计算设备的选择往往需要在性能、功耗和成本之间寻找平衡点。当我们手头有一块搭载昇腾310B4 NPU的香橙派AIpro开发板时,如何充分发挥其8TOPS算力优势?本文将以医学图像分割中广泛…...

【实用技巧】-Mac系列设备自定义鼠标指针颜色与动态效果指南

1. 为什么需要自定义鼠标指针? 作为一个用了十年Mac的老用户,我深知默认的白色指针在复杂界面中经常"消失"的烦恼。特别是做设计时,盯着色彩斑斓的PS画布,那个小箭头简直像在玩捉迷藏。更糟的是在演示场景,观…...

TX12 + ExpressLRS 915MHz RC链路优化与EdgeTX固件升级实战

1. 为什么选择TX12搭配ExpressLRS 915MHz系统 玩无人机的朋友都知道,遥控链路就像风筝线,距离和稳定性直接决定飞行体验。我之前用2.4GHz的RadioLink套装,飞到500米就开始心跳加速——信号时断时续,每次返航都像在赌运气。换成TX1…...

第2篇:嵌入式芯片发展历程与全球主流厂商产品线全梳理

引言:嵌入式技术的诞生与电子产业智能化的发展关联 嵌入式技术的诞生与电子产业的智能化升级同频共振,是科技进步与产业需求深度融合的产物。自20世纪70年代第一块单片机问世以来,嵌入式芯片从最初简单的控制单元,逐步进化为支撑…...

遥感小白看过来!无需编程5分钟搞定Landsat8数据下载(2023最新版)

零代码获取Landsat8遥感数据的完整指南(2023实战版) 当第一次接触遥感数据时,许多非技术背景的研究者常被复杂的下载流程吓退。其实,获取Landsat8卫星影像完全可以像网购一样简单——不需要编写任何代码,甚至不需要理解…...