arduino使用FreeRTOS实时操作系统

news2024/11/18 17:48:34

How to use FreeRTOS with Arduino – Real time operating system

如何让Arduino运行FreeRTOS实时操作系统

在本文中,您将学习如何使用带Arduino的Freertos操作系统来执行特定的任务。实时操作系统又称RTOS,是一种旨在满足实时应用要求的操作系统。它能够处理输入的数据,通常不需要缓冲延迟。RTOS是调用预定义函数的组合。实时操作系统中的关键因素是最小的中断延迟和最小的线程切换延迟。实时操作系统的价值更多地体现在它对给定时间段内完成任务的响应速度和可预测性。

FreeRTOS with Arduino

有三种 RTOS 实时操作系统:

  • Hard RTOS; 必须在规定的期限内完成任务;
  • Firm RTOS; 任务有时间限制,不过如果错过也能接受;
  • Soft RTOS; 任务无时间限制

Examples of RTOS:

  • LynxOS
  • RTLinux
  • VxWorks
  • FreeRTOS
  • OSE
  • QNX
  • Windows CE

Why RTOS are required:

当我们编写好的嵌入式软件时,我们不需要RTOS,但是当它的复杂性和大小增加时,RTOS总是有益的,原因如下:

  • 摘要时间信息
  • 可维护性/可扩展性
  • 模块化
  • 清洁界面
  • 更容易测试(在某些情况下)
  • 代码重用
  • 提高效率
  • 空闲时间
  • 灵活的中断处理
  • 混合加工要求
  • 更轻松地控制外围设备

这些是RTOS的优点,但也有一些缺点,如下所示;

  • 低优先级任务
  • 代码精度
  • 有限的任务
  • 复杂算法
  • 设备驱动程序和中断信号
  • 线程优先级
  • 不容易编程

该项目中使用的操作系统是FreeRTOS。 FreeRTOS由Real Time Engineers Ltd.开发.FreeRTOS是一种流行的实时操作系统内核。 FreeRTOS是开源的。 它用于嵌入在所述35微控制器中的嵌入式设备。 它主要用C语言编写,但有些函数是用汇编语言编写的。 还有在线提供的SafeRTOS和OpenRTOS,与FreeRTOS类似。

使用Arduino进行任务切换:

在这个项目中,3 Led表示三个任务,一个Led表示空闲状态。 三个任务分别是Task1,Task2和Task3。

安装FreeRTOS库:

https://github.com/feilipu/Arduino_FreeRTOS_Library

代码:

#include <Arduino_FreeRTOS.h>

void setup()
{
// 初始化串口波特率
Serial.begin(9600);

Serial.println(F("In Setup function"));

// 3个led灯 任务,1个led空闲任务
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
  
  //   任务执行函数名 任务名字  栈大小 NULL 优先权 NULL
  xTaskCreate(MyTask1, "Task1", 100, NULL, 1, NULL); // 三个任务,标签为"Task1"~"Task3" ,优先权分别为1~3
  xTaskCreate(MyTask2, "Task2", 100, NULL, 2, NULL);
  xTaskCreate(MyTask3, "Task3", 100, NULL, 3, NULL);

  xTaskCreate(MyIdleTask, "IdleTask", 100, NULL, 0, NULL);}// 第四个,空闲任务,最低优先级0级


void loop()
{
// 无
}

// 任务1 Task1====
static void MyTask1(void* pvParameters)
{
  while(1) // for (;;) //这个更好
  { 
    digitalWrite(8,HIGH); // 8号管脚灯亮
    digitalWrite(9,LOW); 
    digitalWrite(10,LOW);
    digitalWrite(11,LOW); 
    Serial.println(F("Task1"));
    vTaskDelay(100/portTICK_PERIOD_MS);// 延时 0.1秒
  }
 }

// 任务2====
static void MyTask2(void* pvParameters)

{ 
 while(1)
  { 
    digitalWrite(8,LOW);
    digitalWrite(9,HIGH);  // 9号管脚灯亮
    digitalWrite(10,LOW);
    digitalWrite(11,LOW);   
    Serial.println(F("Task2"));
    vTaskDelay(110/portTICK_PERIOD_MS);// 延时
    }
 }
 
 
// 任务3=====
static void MyTask3(void* pvParameters)
{ 
 while(1)
  { 
    digitalWrite(8,LOW);
    digitalWrite(9,LOW); 
    digitalWrite(10,HIGH);// 10号管脚灯亮
    digitalWrite(11,LOW);
    Serial.println(F("Task3"));
    vTaskDelay(120/portTICK_PERIOD_MS);// 延时
  }
}

// 空闲任务,无任务时,就执行该空闲时期任务

static void MyIdleTask(void* pvParameters)
{
 while(1)
  { 
    digitalWrite(8,LOW);
    digitalWrite(9,LOW); 
    digitalWrite(10,LOW);
    digitalWrite(11,HIGH); // 11号管脚灯亮
    Serial.println(F("Idle state"));
    delay(50);// 延时
    }
}

每个任务有不同的优先级以及延时时间

Implementation:

Serial Monitor:FreeRTOS tasks with Arduino

link: http://microcontrollerslab.com/use-freertos-arduino/

// 实验中包含五个实时任务:
#include <Arduino_FreeRTOS.h>
#include <semphr.h>  //  Semaphores 信号量

#define Button 8
#define LED_Extern 9
#define Buzzer 12
#define LED_Buildin 13
#define Light_Sensor A0
#define TH_Sensor A3
#define Rotation A5

// 用来确保串口互斥访问的信号量及其使用:
// Declare a mutex Semaphore Handle which we will use to manage the Serial Port.
// It will be used to ensure only one Task is accessing this resource at any time.
SemaphoreHandle_t xSerialSemaphore;// 确保同一时间仅有一个任务获取相同的资源

// 定义5个任务函数
void TaskBuzzerAlarm( void *pvParameters ); //按钮控制蜂鸣器
void TaskLEDControl( void *pvParameters );  //旋位器控制LED灯
void TaskLEDBlink( void *pvParameters );    //板载LED灯闪烁
void TaskLightMonitor( void *pvParameters );//监控亮度
void TaskTHMonitor( void *pvParameters );   //温湿度传感器监控温湿度

void setup() {
  // put your setup code here, to run once:
  pinMode(Button,INPUT);// 按键
  pinMode(LED_Extern,OUTPUT);// 板外LED
  pinMode(Buzzer,OUTPUT);// 蜂鸣器
  pinMode(LED_Buildin,OUTPUT);// 板载LED
  pinMode(Light_Sensor,INPUT);// 光线传感器
  pinMode(TH_Sensor,INPUT);   // 温湿度传感器
  pinMode(Rotation,INPUT);    // 旋位器

  // 串口
  Serial.begin(9600);
  
  while (!Serial) {
    ; // 等待串口连接
  }

  // 创建串口信号量
  if ( xSerialSemaphore == NULL )  // Check to confirm that the Serial Semaphore has not already been created.
  {
    xSerialSemaphore = xSemaphoreCreateMutex();  // Create a mutex semaphore we will use to manage the Serial Port
    if ( ( xSerialSemaphore ) != NULL )
      xSemaphoreGive( ( xSerialSemaphore ) );  // Make the Serial Port available for use, by "Giving" the Semaphore.
  }

  // 创建 5 个任务
  xTaskCreate(
    TaskBuzzerAlarm                      // 任务执行函数
    ,  (const portCHAR *)"BuzzerAlarm"   // 任务名
    ,  128                               // 栈大小
    ,  NULL
    ,  3                  // 优先级,越大优先级越高
    ,  NULL );

  xTaskCreate(
    TaskLEDControl
    ,  (const portCHAR *) "LEDControl"
    ,  128  // Stack size
    ,  NULL
    ,  2  // Priority
    ,  NULL );

  xTaskCreate(
    TaskLEDBlink
    ,  (const portCHAR *) "LEDBlink"
    ,  128  // Stack size
    ,  NULL
    ,  0  // Priority
    ,  NULL );

  xTaskCreate(
    TaskLightMonitor
    ,  (const portCHAR *) "LightMonitor"
    ,  128  // Stack size
    ,  NULL
    ,  1  // Priority
    ,  NULL );

  xTaskCreate(
    TaskTHMonitor
    ,  (const portCHAR *) "THMonitor"
    ,  128  // Stack size
    ,  NULL
    ,  1  // Priority
    ,  NULL );
  // Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started.
}

void loop() {
  // put your main code here, to run repeatedly:

  // Empty. Things are done in Tasks.
  
}

//  5个任务函数====================

void TaskBuzzerAlarm( void *pvParameters __attribute__((unused)) )  // This is a Task.
{
  /*
    DigitalRead
    Reads a digital input on pin 8 that has a pushbutton attached to it, prints the result to the serial monitor
  */

  for (;;) // A Task shall never return or exit.
  {
    // read the input pin:
    int buttonState = digitalRead(Button);

    if(buttonState==LOW){
    digitalWrite(Buzzer,LOW);
    }
    else{
     digitalWrite(Buzzer,HIGH);
    }

    vTaskDelay( 500 / portTICK_PERIOD_MS );  // half second delay in between reads for stability
  }
}

void TaskLEDControl(void *pvParameters)  // This is a task.
{
  (void) pvParameters;

/*
  LED Controlled By Rotation Sensor
*/
  for (;;) // A Task shall never return or exit.
  {
    int rota=analogRead(Rotation);
    analogWrite(LED_Extern,map(rota,0,1023,0,255));
    vTaskDelay( 500 / portTICK_PERIOD_MS ); // wait for half second
  }
}

void TaskLEDBlink(void *pvParameters)  // This is a task.
{
  (void) pvParameters;

/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.
*/
  for (;;) // A Task shall never return or exit.
  {
    digitalWrite(LED_Buildin, HIGH);   // turn the LED on (HIGH is the voltage level)
    vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
    digitalWrite(LED_Buildin, LOW);    // turn the LED off by making the voltage LOW
    vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
  }
}

void TaskLightMonitor( void *pvParameters __attribute__((unused)) )  // This is a Task.
{
  /*
    AnalogRead
    Reads a analog input on pin A0 that has a Light Sensor attached to it, prints the result to the serial monitor
  */

  for (;;) // A Task shall never return or exit.
  {
    // read the input pin:
    int LightValue = analogRead(Light_Sensor);

    // See if we can obtain or "Take" the Serial Semaphore.
    // If the semaphore is not available, wait 5 ticks of the Scheduler to see if it becomes free.
    if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 5 ) == pdTRUE )
    {
      // We were able to obtain or "Take" the semaphore and can now access the shared resource.
      // We want to have the Serial Port for us alone, as it takes some time to print,
      // so we don't want it getting stolen during the middle of a conversion.
      // print out the value of the light sensor:
      Serial.print("Light Sensor(0~1023):");
      Serial.println(LightValue);

      xSemaphoreGive( xSerialSemaphore ); // Now free or "Give" the Serial Port for others.
    }

    vTaskDelay( 5000 / portTICK_PERIOD_MS );  // 5 second delay in between reads for stability
  }
}

void TaskTHMonitor( void *pvParameters __attribute__((unused)) )  // This is a Task.
{
  /*
    AnalogRead
    Reads a analog input on pin A0 that has a Temporature&Humidity Sensor attached to it, prints the result to the serial monitor
  */

  for (;;) // A Task shall never return or exit.
  {
    // read the input pin:
    int THValue = analogRead(TH_Sensor);

    // See if we can obtain or "Take" the Serial Semaphore.
    // If the semaphore is not available, wait 5 ticks of the Scheduler to see if it becomes free.
    if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 5 ) == pdTRUE )
    {
      // We were able to obtain or "Take" the semaphore and can now access the shared resource.
      // We want to have the Serial Port for us alone, as it takes some time to print,
      // so we don't want it getting stolen during the middle of a conversion.
      // print out the value of the THlk liyhb kmyhh kmmi sensor:
      Serial.print("Temporature&Humidity Sensor(0~1023):");
      Serial.println(THValue);

      xSemaphoreGive( xSerialSemaphore ); // Now free or "Give" the Serial Port for others.
    }

    vTaskDelay( 5000 / portTICK_PERIOD_MS );  // 5 second delay in between reads for stability
  }
}


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

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

相关文章

将字符串的大小写字母进行转换大写字母转换为小写字母小写字母转换为大写字母str.swapcase()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将字符串的大小写字母进行转换 大写字母转换为小写字母 小写字母转换为大写字母 str.swapcase() 选择题 以下程序的运行结果是? str"I Like Python!" print("【显示】str:&quo…

可自定义实时监控系统HertzBeat

什么是 HertzBeat &#xff1f; HertzBeat是一个拥有强大自定义监控能力&#xff0c;无需 Agent 的开源实时监控告警系统。集 监控告警通知 为一体&#xff0c;支持对应用服务&#xff0c;数据库&#xff0c;操作系统&#xff0c;中间件&#xff0c;云原生&#xff0c;网络等监…

算法:双指针解决数组划分和数组分块问题

文章目录 实现原理实现思路典型例题移动0复写0快乐数盛最多水的容器有效三角形的个数三数之和四数之和 总结 在快速排序或者是其他和数组有关的题目中&#xff0c;有很经典的一类题目是关于数组划分的&#xff0c;数组划分就是把数组按照一定的规则划分为不同的区间&#xff0c…

jupyter notebook出现ERR_SSL_VERSION_OR_CIPHER_MISMATCH解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

SQL阶段性优化

&#x1f61c;作 者&#xff1a;是江迪呀✒️本文关键词&#xff1a;微信小程序、页面跳转、移动端、前端☀️每日 一言&#xff1a;我们要把懦弱扼杀在摇篮中。 一、前言 我们在做系统的过程中&#xff0c;难免会遇到页面查询速度慢&#xff0c;性能差的问题&…

敏感信息泄露

由于后台人员的疏忽或者不当的设计&#xff0c;导致不应该被前端用户看到的数据被轻易的访问到。 比如&#xff1a; —通过访问url下的目录&#xff0c;可以直接列出目录下的文件列表; —输入错误的url参数后报错信息里面包含操作系统、中间件、开发语言的版本或其他信息; —前…

STM32编程Printf函数语法

Printf函数语法 函数声明 printf 函数的声明如下&#xff1a; // C99 前 int printf( const char *format, ... ); // C99 起 int printf( const char *restrict format, ... );参数列表 format – 是格式控制字符串&#xff0c;包含了两种类型的对象&#xff1a;普通字符和…

C语言小白急救 指针初级讲解(四千字教程)

系列文章目录 C语言小白急救 表达式求值&#xff08;两千字教程&#xff09; C语言小白急救 操作符详解(8千字保姆级教程) C语言小白急救 扫雷游戏&#xff08;万字保姆级教程&#xff09; C语言小白急救 使用C语言编写‘三子棋‘ 文章目录 系列文章目录[C语言小白急救 表达式…

YOLOv5、YOLOv8改进:SOCA注意力机制

目录 简介 2.YOLOv5使用SOCA注意力机制 2.1增加以下SOCA.yaml文件 2.2common.py配置 2.3yolo.py配置 简介 注意力机制&#xff08;Attention Mechanism&#xff09;源于对人类视觉的研究。在认知科学中&#xff0c;由于信息处理的瓶颈&#xff0c;人类会选择性地关注所有…

五款拿来就能用的炫酷表白代码

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;小白零基础《Python入门到精通》 五款炫酷表白代码 1、无限弹窗表白2、做我女朋友好吗&#xff0c;不同意就关机3、…

增长黑武器|LTD营销SaaS荣获“2023亚太杰出营销数字化供应商”

LTD受邀与全球五百强企业数字化创新决策人&#xff0c;共同交流探讨信息化管理与数字化变革。 盛夏未央&#xff0c;八月笙箫已起&#xff0c;初秋登场。 在这烂漫的金秋时节&#xff0c;杭州乐通达网络有限公司&#xff08;简称&#xff1a;LTD&#xff09;受邀参加了“重建信…

【VS Code插件开发】Webview面板(三)

&#x1f431; 个人主页&#xff1a;不叫猫先生&#xff0c;公众号&#xff1a;前端舵手 &#x1f64b;‍♂️ 作者简介&#xff1a;前端领域优质作者、阿里云专家博主&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01; &#x1f4e2; 资料领取&#xff1a;前端…

嵌入式设备应用开发(其他第三方库)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 前面我们介绍的qt、boost这些都是通用库。也就是说,不管什么样的场景,这些库都可以拿过来使用。然而在实际开发中还有一些第三方库,它是需要和实际场景联系在一起的。也就是说,…

百度千帆大模型初体验,接入30+大模型、100+提示词模版、插件最丰富,国内最强

大家好&#xff0c;我是二哥呀。 作为国内的头部大厂&#xff0c;百度在大模型这块的投入力度可以说非常大&#xff0c;3 月 16 号发布的大模型——文心一言可以说在业界激起了巨浪。 有支持的&#xff0c;当然也有怀疑的&#xff0c;但无论如何&#xff0c;百度勇敢的迈出去…

致敬,“编辑器之神”Vim的开发者Bram Moolenaar去世

编辑器之神Vim之父Bram Moolenaar逝世&#xff0c;享年62岁。其家人称&#xff0c;因过去几周里病情迅速恶化&#xff0c;Bram Moolenaar于8月3日去世。Bram的一生将大部分时间都奉献给了Vim&#xff0c;甚至在一个月前&#xff0c;他还在对Vim做着更新、修改工作。 Vim 是一个…

数据在内存中的储存·大小端(文字+画图详解)(c语言·超详细入门必看)

前言&#xff1a;Hello&#xff0c;大家好&#xff0c;我是心跳sy&#x1f618;&#xff0c;本节我们介绍c语言的两种基本的内置数据类型&#xff1a;数值类型和字符类型在内存中的储存方法&#xff0c;并对大小端进行详细介绍&#xff08;附两种大小端判断方法&#xff09;&am…

操作系统——进程和线程

文章目录 1.进程和线程的区别2.进程有哪几种状态?3.进程间的通信方式4.线程间的同步的方式5.进程的调度算法 1.进程和线程的区别 从上图可以看出&#xff1a;一个进程中可以有多个线程&#xff0c;多个线程共享进程的堆和方法区 (JDK1.8 之后的元空间)资源&#xff0c;但是每个…

块/ if else/ switch /for for each

1、块作用域&#xff0c; 定义在{}中的变量&#xff0c;只能在{}内生效 import java.util.*; public class Test{ public static void main(String[] xxx){int a10;if(a>9){int k 2;//k只在if{}内有效}//这个括号之后再对k进行操作&#xff0c;违法} } import java.util.…

Java之优雅处理 NullPointerException空指针异常

前言 NPE问题就是&#xff0c;我们在开发中经常碰到的NullPointerException。假设我们有两个类&#xff0c;他们的UML类图如下图所示 在这种情况下&#xff0c;有如下代码 user.getAddress().getProvince(); 这种写法&#xff0c;在user为null时&#xff0c;是有可能报Nul…

AI引擎助力,CamScanner智能高清滤镜开启扫描新纪元!

文章目录 ⭐ 写在前面⭐ 突破图像处理难点&#xff1a;扫描全能王的独特优势⭐ 耳听为虚&#xff0c;眼见为实⭐ 产品背后的主要核心&#xff1a;AI-Scan助力⭐ 深度学习助力智能文档处理的国际化进程⭐ 品味智能文档处理的轻松与精准 ⭐ 写在前面 在数字化快速发展的今天&…