七个项目掌握freertos

news2025/2/22 11:06:47

1、闪烁LED:


最基本的示例项目,涉及到创建一个简单的任务,用于控制LED的闪烁。这个项目会教你如何初始化FreeRTOS并创建任务。

#include "FreeRTOS.h"
#include "task.h"
#define LED_PIN (某个GPIO引脚)

void vBlinkTask(void *pvParameters) {
    while(1) {
        // Toggle LED状态
        gpio_set_level(LED_PIN, !gpio_get_level(LED_PIN));
        
        // 500毫秒延时
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

int main(void) {
    // 初始化硬件
    gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);

    // 创建闪烁LED的任务
    xTaskCreate(vBlinkTask, "BlinkTask", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+1, NULL);
    
    // 启动调度器
    vTaskStartScheduler();

    // 如果执行到这里,那么会有问题
    for( ;; );
}


2、任务通信:

创建两个任务,使用队列来在它们之间传递消息。这个项目可以帮助你理解FreeRTOS中的任务同步和通信机制。

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

QueueHandle_t xQueue;

void vSenderTask(void *pvParameters) {
    int32_t lValueToSend = 0;
    while(1) {
        // 发送一个值到队列中
        xQueueSend(xQueue, &lValueToSend, 0);
        lValueToSend++;
        
        // 间隔一秒
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void vReceiverTask(void *pvParameters) {
    int32_t lReceivedValue;
    while(1) {
        // 从队列中接收数据
        if(xQueueReceive(xQueue, &lReceivedValue, portMAX_DELAY)) {
            // 成功接收到数据,lReceivedValue有新值
        }
    }
}

int main(void) {
    // 创建队列,长度为1,数据大小为int32_t
    xQueue = xQueueCreate(1, sizeof(int32_t));
    
    // 创建两个任务
    xTaskCreate(vSenderTask, "SenderTask", 1000, NULL, 1, NULL);
    xTaskCreate(vReceiverTask, "ReceiverTask", 1000, NULL, 1, NULL);
    
    // 启动调度器
    vTaskStartScheduler();
    
    return 0;
}


3、多任务管理:


创建多个任务,包括周期性任务和响应外部事件(如按钮按下)的任务。这有助于你学习任务优先级和调度。

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

void vTaskFunction(void *pvParameters) {
    for (;;) {
        // 任务具体的代码

        vTaskDelay(一个时间周期);
    }
}

int main(void) {
    xTaskCreate(vTaskFunction, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
    xTaskCreate(vTaskFunction, "Task2", configMINIMAL_STACK_SIZE, NULL, 2, NULL);

    vTaskStartScheduler();

    return 0;
}


4、利用信号量控制资源访问:


用一个或多个任务来模拟资源(如串口)的访问,并使用信号量来同步对该资源的访问。

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

SemaphoreHandle_t xSemaphore;

void vTaskFunction(void *pvParameters) {
    for (;;) {
        // 获取信号量
        if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
            // 访问资源

            // 释放信号量
            xSemaphoreGive(xSemaphore);
        }
    }
}

int main(void) {
    xSemaphore = xSemaphoreCreateMutex();
    xTaskCreate(vTaskFunction, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
    xTaskCreate(vTaskFunction, "Task2", configMINIMAL_STACK_SIZE, NULL, 1, NULL);

    vTaskStartScheduler();

    return 0;
}


5、模拟温度监控系统:

创建任务来模拟温度传感器的读取,并通过队列将数据发送给数据处理任务。

#include "FreeRTOS.h"
#include "queue.h"

QueueHandle_t xQueue;

void vSensorTask(void *pvParameters) {
    float temperature;

    for (;;) {
        // 模拟读取温度传感器数据
        temperature = getTemperature();

        // 将数据放入队列
        xQueueSend(xQueue, &temperature, portMAX_DELAY);
    }
}

int main(void) {
    xQueue = xQueueCreate(10, sizeof(float));

    xTaskCreate(vSensorTask, "SensorTask", configMINIMAL_STACK_SIZE, NULL, 2, NULL);

    vTaskStartScheduler();

    return 0;
}


6、FreeRTOS内存管理:

学习和实践FreeRTOS的内存分配和释放,理解不同内存管理方案的使用。

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

// 声明两个任务的函数原型
void vProducerTask(void *pvParameters);
void vConsumerTask(void *pvParameters);

// 定义全局队列句柄
QueueHandle_t xQueue;

int main(void) {
    // 创建一个队列,能够存储10个int类型的指针
    xQueue = xQueueCreate(10, sizeof(int *));

    if (xQueue != NULL) {
        // 创建任务
        xTaskCreate(vProducerTask, "Producer", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
        xTaskCreate(vConsumerTask, "Consumer", configMINIMAL_STACK_SIZE, NULL, 1, NULL);

        // 启动调度器
        vTaskStartScheduler();
    }

    // 在这里应该永远执行不到
    for (;;);
}

void vProducerTask(void *pvParameters) {
    int *piValue;
    while (1) {
        // 动态分配内存
        piValue = (int *) pvPortMalloc(sizeof(int));
        
        if (piValue != NULL) {
            // 在分配的内存中存储数值
            *piValue = rand() % 100;

            // 将内存指针发送到队列
            if(xQueueSend(xQueue, &piValue, portMAX_DELAY) != pdPASS) {
                // 如果发送失败则释放内存
                vPortFree(piValue);
            }
        }

        // 模拟生产者速率
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void vConsumerTask(void *pvParameters) {
    int *piValue;
    while (1) {
        if (xQueueReceive(xQueue, &piValue, portMAX_DELAY) == pdPASS) {
            // 从队列中接收到内存指针, 处理数据
            processValue(*piValue);
            
            // 释放内存
            vPortFree(piValue);
        }
    }
}

void processValue(int value) {
    // 在这里实现数据处理
}


7、FreeRTOS软件定时器:

配置和使用FreeRTOS的软件定时器,进行周期性任务的调度。

#include "FreeRTOS.h"
#include "timers.h"

// 定时器的回调函数
void vTimerCallback(TimerHandle_t xTimer);

int main(void) {
    // 初始化硬件,根据具体平台进行相应初始化,例如GPIO、中断等。

    // 创建定时器
    TimerHandle_t xExampleTimer;

    // 定时器的ID,没有特殊用途时可以设置为NULL
    const uint32_t timerID = 0;

    // 创建软件定时器,设置定时500毫秒, 自动重载,timerID为定时器ID,vTimerCallback为回调函数
    xExampleTimer = xTimerCreate("Timer", pdMS_TO_TICKS(500), pdTRUE, (void *)timerID, vTimerCallback);

    // 启动定时器,定时器会在启动后的500毫秒后执行回调函数。0表示不等待命令发送到定时器命令队列。
    if (xExampleTimer != NULL) {
        xTimerStart(xExampleTimer, 0);
    }

    // 启动调度器,开始执行任务
    vTaskStartScheduler();

    // 如果程序执行到这里,那么可能是因为内存不足导致调度器无法启动。
    for (;;);

    return 0;
}

// 定义回调函数
void vTimerCallback(TimerHandle_t xTimer) {
    // 这里执行定时器到期时需要执行的代码
    // 比如Toggle一个LED的状态、读取传感器数据、或要发送一个心跳消息等。

    // TimerHandle_t可以用来获取定时器的ID
    uint32_t timerID = (uint32_t) pvTimerGetTimerID(xTimer);

    // 根据timerID进行相应的处理,若timerID没有用到,则可以忽略
}

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

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

相关文章

BUGKU-WEB cookies

题目描述 题目截图如下: 进入场景看看: 解题思路 看源码看F12:看请求链接看提示:cookies欺骗 相关工具 插件:ModHeader或者hackbarbase64解密 解题步骤 看源码 就是rfrgrggggggoaihegfdiofi48ty598whrefeoia…

2000-2023年7月全国各省专利侵权结案案件数量数据

2000-2023年7月全国各省专利侵权结案案件数量数据 1、时间:2000-2023年7月 2、指标:地区、年份、专利侵权纠纷行政案件-结案数目 3、范围:31省 4、来源:国家知识产权局,并由该局每个月公布的数据汇总而成 5、指标…

STM32CubeIDE基础学习-STM32CubeIDE软件代码编写格式问题

STM32CubeIDE基础学习-STM32CubeIDE软件代码编写格式问题 前言 代码编写最好就是规定一个格式,或者建立一个偏好,这样写出来的代码就方便自己管理了,不然代码乱放下次打开工程就很难找到具体位置,如果规定了格式,那么…

LeetCode中的returnSize和returnColumnSize

今天这篇比较水,不过本文要讲的内容是我曾经遇到过的问题,也可能是大部分人在初次接触力扣时的一些疑问。当时遇到这个问题也是上网找了许久没有找到满意的答案,现在自己明白了,也希望能够帮助还抱有疑惑的各位解答。 如果我说的…

认证授权与JWT

认证授权与JWT 1、认证授权概念介绍1.1 什么是认证1.2 什么是授权 2、权限数据模型3、RBAC权限模型3.1 介绍3.2 基于角色访问控制3.3 基于资源访问控制 4、常见认证方式4.1 Cookie-Session4.2 jwt令牌无状态认证 5 常见技术实现6.Jwt介绍6.1 JWT简介6.2.Jwt组成 7、JWT使用7.1 …

2024-3-12尾盘一致转分歧

安彩高科开一字符合预期,昨天风光储锂电大涨,理应给大溢价,超预期是 艾艾精工 高开秒板,立航科技高开分歧反核承接良好回封一致,带动了低空经济板块高潮,低空经济开始往 碳纤维 方向扩散。盘中我说了 三晖…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的火焰检测系统(Python+PySide6界面+训练代码)

摘要:本研究详述了一种采用深度学习技术的火焰检测系统,该系统集成了最新的YOLOv8算法,并与YOLOv7、YOLOv6、YOLOv5等早期算法进行了性能评估对比。该系统能够在各种媒介——包括图像、视频文件、实时视频流及批量文件中——准确地识别火焰目…

蓝桥杯真题讲解:子矩阵(二维滑动窗口)

蓝桥杯真题讲解&#xff1a;子矩阵&#xff08;二维滑动窗口&#xff09; 一、视频讲解二、正解代码 一、视频讲解 蓝桥杯真题讲解&#xff1a;子矩阵&#xff08;二维滑动窗口&#xff09; 二、正解代码 //二维单调队列 #include<bits/stdc.h> #define endl \n #def…

Midjourney绘图欣赏系列(十一)

Midjourney介绍 Midjourney 是生成式人工智能的一个很好的例子&#xff0c;它根据文本提示创建图像。它与 Dall-E 和 Stable Diffusion 一起成为最流行的 AI 艺术创作工具之一。与竞争对手不同&#xff0c;Midjourney 是自筹资金且闭源的&#xff0c;因此确切了解其幕后内容尚不…

(二)运行自己的stable-diffusion

前面的步骤如https://datawhaler.feishu.cn/docx/BwjzdQPJRonFh8xeiSOcRUI3n8b所示 拷贝、解压文件后&#xff0c;进入到stable-diffusion-webui的文件夹中&#xff0c;文件如下&#xff1a; 启动&#xff1a; 运行效果&#xff1a; 由于生成了好几个图&#xff0c;所以…

布隆过滤器(做筛选器索引)

什么是布隆过滤器 布隆过滤器&#xff08;Bloom Filter&#xff09;是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。 它的优点是空间效率和查询时间都比一般的算法要好的多&#xff0c;缺点是…

学习vue3第四节(ref以及ref相关api)

主要记录以下api&#xff1a;ref()、isRef()、unref()、 shallowRef()、triggerRef()、customRef() 1、ref() 定义 接受一个内部值&#xff0c;返回一个响应式的、可更改的 ref 对象&#xff0c;此对象只有一个指向其内部值的属性 .value&#xff0c;.value属性用于追踪并且存…

I2C驱动AT24C02

文章目录 一、硬件电路设备地址 二、使用步骤字节写:页写入:任意写:任意读: 一、硬件电路 设备地址 设备需要一个8位的设备地址字&#xff0c;后面跟着一个启动条件&#xff0c;以使芯片能够进行读或写操作 设备地址字由一个强制的1,0序列的前四个最有效的位&#xff0c;如所示…

简单使用国产数据库—达梦

达梦数据库是一款由中国的达梦软件公司开发的关系数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它在业界以其高性能、可扩展性和安全性而著称。该系统广泛应用于各种应用程序的数据存储和管理&#xff0c;满足用户对于数据处理和管理的多样化需求。 安装好的达梦数…

容联云孙昌勋:聚焦“营销服”数智化转型,构筑金融业增长引擎

在每日经济新闻2024全国两会特别报道中&#xff0c;容联云创始人兼CEO孙昌勋针对“人工智能”在具体行业如何开展时表示&#xff1a;“随着泛金融行业用户渠道与体验发生变化&#xff0c;金融业对营销、销售、服务等场景的数智化改造有巨大的需求&#xff0c;人工智能等科技投入…

Qt/QML编程之路:openglwidget和倒车影像的切换(43)

关于如何实现一个基于OpenGL的3d 图形,这个有很多专门的介绍,我在开发中遇到了这么一个问题: 如何实现一个倒车影像的video显示与一个3D物体显示的切换,因为开窗在同样的一个位置,如果车子倒车启动,则需要将原本显示3D的地方切换为视频图像的显示。 class testOpenGl : …

docker容器镜像管理+compose容器编排(持续更新中)

目录 一、 Docker的基本组成 二、 容器和镜像的关系 2.1 面向对象角度 2.2 从镜像容器角度 三、 容器命令 3.1 使用Ubuntu 3.1.1 下载镜像 3.1.2 新建和启动容器 run 3.1.3交互式 compose编排与部署 1. docker-compose部署 2. docker-compose.yml模板 …

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:PluginComponent)

提供外部应用组件嵌入式显示功能&#xff0c;即外部应用提供的UI可在本应用内显示。 说明&#xff1a; 该组件从API Version 9开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。本组件为系统接口。 子组件 无 接口 PluginComponent(value:…

2.4 关系代数 数据库系统概论

目录 2.4.1 传统的集合运算 &#xff08;二目运算&#xff09; &#xff08;1&#xff09; 并&#xff08;Union&#xff09; &#xff08;2&#xff09;差&#xff08;Except&#xff09; &#xff08;3&#xff09; 交&#xff08;Intersection&#xff09; &#xff08…

wait 和 notify方法

目录 1.1 wait()方法 wait 做的事情: wait 结束等待的条件: 1.2 notify()方法 1.3notifyAll方法 1.4wait()和sleep()对比 由于线程之间是抢占式执行的, 因此线程之间执行的先后顺序难以预知. 但是实际开发中有时候我们希望合理的协调多个线程之间的执行先后顺序. 完成这个协调…