STM32+Clion多线程开发

这篇具有很好参考价值的文章主要介绍了STM32+Clion多线程开发。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

创建多线程

freertos.c

main.cpp

main_app.h

二值信号量

相关API介绍

(1) osSemaphoreCreate

(2)osSemaphoreDelete

(3)osSemaphoreRelease

(4)osSemaphoreWait

实际使用

创建信号量(freertos.c)

在头文件中外部引用(freertos_inc.h)

main.c

关于clion使用printf,参考【教程】手把手教你用Clion进行STM32开发【如何优雅の进行嵌入式开发】 - 知乎 (zhihu.com)


创建多线程

本文的程序通过STM32CubeMX+Clion完成,使用单片机为Stm32f411CEU6

为了让自己的程序和生成的程序分开,方便后续的管理,我我们可以新建一个Src目录或者User目录,然后在目录里新建main_app.cpp/main_app.h,如果有其他传感器功能的实现或者算法的实现可以再新建一个目录放到里面,新加的目录记得在CMakelist里添加路径。

STM32+Clion多线程开发,stm32,嵌入式硬件,单片机,c++,c语言

在include和file里都要添加,尤其是file,不添加也不会报错容易漏。

STM32+Clion多线程开发,stm32,嵌入式硬件,单片机,c++,c语言

然后要知道程序是在哪里运行的,不在main.c中而是在下面这个文件里core/src/freertos.c,在这里写上自己的主程序函数就可以成功进入

freertos.c
void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */

    main_app();
    vTaskDelete(defaultTaskHandle);


  /* USER CODE END StartDefaultTask */
}

接下来创建第一个线程,这里使用cmsis_os.h,记得包含到头文件里,然后按照以下格式创建即可,要注意的就是设置的栈大小和优先级,还有这个任务main_app执行完后就结束了,所以后续需要使用的变量或者类,不要放到函数中而是要放在前面,创建全局变量并初始化。

main.cpp
SensorManager sensorManager;//全局变量,记得初始化,在这里直接初始化也可以

osThreadId_t SensorTaskHandle;
void SensorTask(void *pvParameters) {
    for(;;) {
        LED_B_TogglePin;
        osDelay(1000);
    }
}

osThreadId_t LCDTaskHandle;
void LCDTask(void *pvParameters) {
    for(;;) {
        LED_R_TogglePin;
        osDelay(1000);
    }
}

void main_app()
{

    const osThreadAttr_t SensorTask_attributes = {
            .name = "SensorTask",
            .stack_size = 128 * 8,//栈空间
            .priority = (osPriority_t) osPriorityNormal,
    };
    SensorTaskHandle = osThreadNew(SensorTask, nullptr, &SensorTask_attributes);

    const osThreadAttr_t LCDTask_attributes = {
            .name = "LCDTask",
            .stack_size = 128 * 8,
            .priority = (osPriority_t) osPriorityNormal,
    };
    LCDTaskHandle = osThreadNew(LCDTask, nullptr, &LCDTask_attributes);


    // 启动调度器
    printf("end\n");
}
main_app.h
#ifndef STM32_DEMO2_F4_MAIN_APP_H
#define STM32_DEMO2_F4_MAIN_APP_H

#ifdef __cplusplus
extern "C" {
#endif

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

#include "cmsis_os.h"
#include "main.h"
#include "gpio.h"
#include "usart.h"


void main_app(void);

#ifdef __cplusplus
}

#endif

#endif //STM32_DEMO2_F4_MAIN_APP_H

二值信号量

在多线程时当多个线程同时访问一个变量时,可能会造成冲突,比如当两个线程同时使用printf时,出现冲突,结果就是打印乱码,因此需要使用信号量来避免这种情况,在使用串口的问题中,我使用二值信号量。

相关API介绍

(1) osSemaphoreCreate

用于创建一个二值信号量,并返回一个ID。

函数 osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count)

参数 semaphore_def: 引用由osSemaphoreDef定义的信号量 count: 信号量数量

返回值 成功返回信号量ID,失败返回0

(2)osSemaphoreDelete

用于删除一个信号量,包括二值信号量,计数信号量,互斥量和递归互斥量。如果有任务阻塞在该信号量上,那么不要删除该信号量。

函数 osStatus osSemaphoreDelete (osSemaphoreId semaphore_id)

参数 semaphore_id: 信号量ID

返回值 错误码文章来源地址https://www.toymoban.com/news/detail-840351.html

(3)osSemaphoreRelease

用于释放信号量的宏。释放的信号量对象必须是已经被创建的,可以用于二值信号量、计数信号量、互斥量的释放,但不能释放由函数 xSemaphoreCreateRecursiveMutex() 创建的递归互斥量。可用在中断服务程序中。

函数 osStatus osSemaphoreRelease (osSemaphoreId semaphore_id)

参数 semaphore_id: 信号量ID

返回值 错误码

(4)osSemaphoreWait

用于获取信号量,不带中断保护。获取的信号量对象可以是二值信号量、计数信号量和互斥量,但是递归互斥量并不能使用这个 API 函数获取。可用在中断服务程序中。

函数 int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec)

参数 semaphore_id: 信号量ID millisec:等待信号量可用的最大超时时间,单位为 tick(即系统节拍周期)。 如果宏 INCLUDE_vTaskSuspend 定义为 1 且形参 xTicksToWait 设置为 portMAX_DELAY ,则任务将一直阻塞在该信号量上(即没有超时时间)

返回值 错误码

实际使用

创建信号量(freertos.c)
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
osSemaphoreId sem_uart6_rx;
osSemaphoreId sem_uart6_tx;
/* USER CODE END PD */

void MX_FREERTOS_Init(void) {
    // Create a semaphore for USB RX, and start with no tokens by removing the starting one.
    osSemaphoreDef(sem_usb_rx);
    sem_uart6_rx = osSemaphoreNew(1, 0, osSemaphore(sem_usb_rx));

    // Create a semaphore for USB TX
    osSemaphoreDef(sem_usb_tx);
    sem_uart6_tx = osSemaphoreNew(1, 1, osSemaphore(sem_usb_tx));
  /* USER CODE END RTOS_SEMAPHORES */

  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

}
在头文件中外部引用(freertos_inc.h)
#ifndef STM32_DEMO2_F4_FREERTOS_INC_H
#define STM32_DEMO2_F4_FREERTOS_INC_H

#ifdef __cplusplus
extern "C" {
#endif
// List of semaphores
extern osSemaphoreId sem_uart6_rx;
extern osSemaphoreId sem_uart6_tx;

// List of Tasks
/*--------------------------------- System Tasks -------------------------------------*/
extern osThreadId_t defaultTaskHandle;      // Usage: 4000 Bytes stack

/*---------------------------------- User Tasks --------------------------------------*/
extern osThreadId_t SensorTaskHandle;         // Usage: 4000 Bytes stack
extern osThreadId_t LCDTaskHandle;  // Usage: 4000 Bytes stack

/*---------------- 24.1K (used) / 64K (for FreeRTOS) / 128K (total) ------------------*/

#ifdef __cplusplus
}
#endif

#endif //STM32_DEMO2_F4_FREERTOS_INC_H
main.c
osThreadId_t SensorTaskHandle;
void SensorTask(void *pvParameters) {
    osSemaphoreAcquire(sem_uart6_tx,osWaitForever);
    printf("enter SensorTask\n");
    osSemaphoreRelease(sem_uart6_tx);
    for(;;) {
        LED_B_TogglePin;
        osDelay(1000);
    }
}

osThreadId_t LCDTaskHandle;
void LCDTask(void *pvParameters) {
    osSemaphoreAcquire(sem_uart6_tx,osWaitForever);
    printf("enter LCDTask\n");
    osSemaphoreRelease(sem_uart6_tx);
    for(;;) {
        LED_R_TogglePin;
        osDelay(1000);
    }
}

void main_app()
{

    const osThreadAttr_t SensorTask_attributes = {
            .name = "SensorTask",
            .stack_size = 128 * 8,//栈空间
            .priority = (osPriority_t) osPriorityNormal,
    };
    SensorTaskHandle = osThreadNew(SensorTask, nullptr, &SensorTask_attributes);

    const osThreadAttr_t LCDTask_attributes = {
            .name = "LCDTask",
            .stack_size = 128 * 8,
            .priority = (osPriority_t) osPriorityNormal,
    };
    LCDTaskHandle = osThreadNew(LCDTask, nullptr, &LCDTask_attributes);


    // 启动调度器
    printf("end\n");
}

关于clion使用printf,参考【教程】手把手教你用Clion进行STM32开发【如何优雅の进行嵌入式开发】 - 知乎 (zhihu.com)

到了这里,关于STM32+Clion多线程开发的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 嵌入式毕设分享 stm32人脸识别快递柜系统(源码+硬件+论文)

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年04月10日
    浏览(48)
  • 嵌入式毕设分享 stm32智能鱼缸监控投喂系统(源码+硬件+论文)

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年03月17日
    浏览(58)
  • 嵌入式毕设分享 stm32 RFID智能仓库管理系统(源码+硬件+论文)

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月20日
    浏览(50)
  • STM32开发环境搭建&工程创建(嵌入式学习)

    简介 STM32CubeMX是STMicroelectronics公司提供的一款集成开发环境(IDE)工具,用于快速配置和初始化STM32微控制器系列的软件工程。它提供了图形化界面和交互式工具,使开发者能够轻松地生成STM32微控制器的初始化代码和配置文件。 STM32CubeMX具有以下主要功能和特点: 微控制器

    2024年02月11日
    浏览(47)
  • 嵌入式物联网STM32实战开发代码例程库

    几百个例程清单,CSDN下载地址: https://download.csdn.net/download/weixin_39804904/88671879 开发例程清单(持续新增中,欢迎点赞关注): 0001基于STM32F103单片机GPIO实现控制LED灯闪烁的程序代码0001.rar 0002基于STM32F103单片机GPIO实现按键KEY的检测程序代码0002.rar 0003基于STM32F103单片机GPIO实现

    2024年02月02日
    浏览(30)
  • 嵌入式系统开发13——STM32输出PWM实现呼吸灯

    本文主要介绍在STM32F103C8T6上,利用定时器输出PWM波形,进而驱动LED实现呼吸灯。 使用TIM3和TIM4,分别输出一个PWM波形,PWM的占空比随时间变化,去驱动你外接的一个LED以及最小开发板上已焊接的LED(固定接在 PC13 GPIO端口),实现2个 LED呼吸灯的效果。 脉冲宽度调制(PWM) ,是

    2023年04月08日
    浏览(67)
  • 【STM32嵌入式系统设计与开发】——7有源蜂鸣器应用

    STM32资料包: 百度网盘下载链接:链接:https://pan.baidu.com/s/1mWx9Asaipk-2z9HY17wYXQ?pwd=8888 提取码:8888 观察电路图,核心板PD14连接底板中的P2外接排针,将正负极接上直流电压即可持续发声,频率固定。LED的PA0连接底板的D1灯。 步骤1:复制工程模板“1_Template”重命名为“4_Active

    2024年03月21日
    浏览(50)
  • 嵌入式系统开发笔记104:在STM32CubeIDE中导入工程

      本文讲述如何在STM32CubeIDE中导入现有工程。

    2024年02月16日
    浏览(37)
  • 嵌入式开发--STM32G4系列片上FLASH的读写

    这个玩意吧,说起来很简单,就是几行代码的事,但楞是折腾了我大半天时间才搞定。原因后面说,先看代码吧: 读操作很简单,以32位方式读取的时候是这样的: 需要注意的是,当以32位方式读取时,地址需要是4的整数倍,即32位。 8位或16位方式类似操作即可 需要注意的

    2024年01月18日
    浏览(49)
  • STM32F4+FreeRTOS+LVGL实现嵌入式快速开发(缝合怪)

    极速进行项目开发,只需要懂一款芯片架构+一个操作系统+一个GUI。各种部件程序全靠抄 ,成为究极缝合怪。本文用stm32f407+FreeRTOS+lvgl演示一些demo。 原文链接:STM32F4+FreeRTOS+LVGL实现快速开发(缝合怪) lvgl官方的音乐播放器demo: 百问网的2048小游戏: STM32F407这款芯片就不多介绍

    2024年02月08日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包