Arduino的多线程

前言

     本章节是如何使用Arduino 的多线程技术。截止目前,Arduino 的性能很棒,但是如果我们想在不同的时间间隔中,完成两件、多件的任务呢? 此时,我们就需要使用一种类多线程技术来处理项目。

Arduino 的多线程 \ 类多线程?

    为了正确理解多线程技术和Arduino 之间的关系,我们需要理解为什么它不是真正的多线程。

    在计算机CPU上,多线程应用程序是两个独立的进程,它们在CPU的不同核心上彼此​​并行工作。这些过程相互作用以共同完成工作,但不一定按照你的假设均匀地分割工作。通常有一个主进程/“线程”,它充当其他线程的管理器,然后是它管理的一个或多个工作线程,每个线程可以执行特定的任务。一个很好的例子是Chrome浏览器。Chrome是所有网页标签(线程)的管理者,但由于chrome是多线程的,因此每个标签都是其自己的小程序。这意味着,如果你有多个核心来分配每个选项卡,它不仅可以更快地运行,还有其他好处,例如当一个选项卡崩溃时不会崩溃整个浏览器。

     我们经常使用的Arduino UNO 的微处理器芯片Atmel ATMega328p ,运行速度为16Mhz 。它能够达到20Mhz ,但是会被拨回来,所以他不会搞乱像将数据写入内存(或者Boom,烧掉)。16Mhz 意味着每一秒, 你的Arduino正在处理16 000 000 个周期,也就是做1600万件工作。这些不是代码行(速度非常快),Arduino相对较慢。例如将数据移入和移出寄存器,这些是处理器指令。

     严格意义上,Arduino 虽然可以实现多线程的效果,但是它只是类多线程技术。

可实现 类多线程的库

     以下笔者总结了3 种常见的库,并提供了下载链接 \ 文档地址 \ 使用示例。

Metro

GitHub地址: https://github.com/thomasfredericks/Metro-Arduino-Wiring

示例:

/*
       Metro 库, 可作为类多线程来使用
*/
#include <Metro.h>
const int blinkPin1 = 13; //定义 LED 引脚13
const int blinkPin2 = 12; //定义 LED 引脚12
boolean blink1State = false;   //定义 blink1State 为false状态
boolean blink2State = false;   //定义 blink2State 为false状态  
Metro blink1Metro = Metro(100);   //把 blink1Metro 实例化 Metro 对象 ,并设置间隔时间
Metro blink2Metro = Metro(1000);     //把 blink2Metro 实例化 Metro 对象 ,并设置间隔时间
void setup()
{
       pinMode(blinkPin1, OUTPUT);   //设置blinkPin1 为输出模式
       pinMode(blinkPin2, OUTPUT);   //设置blinkPin2 为输出模式
}
void loop()
{
       if (blink1Metro.check()) {  //检查blink1Metro间隔(我的理解是计时器每隔100毫秒就会返回true,就执行以下程序)
              blink1State = !blink1State;   //反转blink1State的逻辑真或假(false or  true)
              digitalWrite(blinkPin1, blink1State); //数字引脚,设置为blink1State的状态
       }
       if (blink2Metro.check()) {
              blink2State = !blink2State;
              digitalWrite(blinkPin2, blink2State);
       }
}

参考函数:

void reset() 重新启动/重置。

Metro(unsigned long interval)  实例化一个 Metro 对象,设置间隔时间(单位为毫秒)。

 

Chrono 库 

GitHub地址:  https://github.com/SofaPirate/Chrono

注: 此为Metro库的更新版本。

示例:

#include <Chrono.h>
int ledPinA =  13;
int ledPinB =  9;
int ledStateA = HIGH;
int ledStateB = HIGH;
Chrono chronoA;
Chrono chronoB;
bool isStop = false;

void setup()
{
  Serial.begin(9600);
  pinMode(ledPinA,OUTPUT);
  digitalWrite(ledPinA,ledStateA);
  pinMode(ledPinB,OUTPUT);
  digitalWrite(ledPinB,ledStateB);
}

void loop()
{
  // 使用Chrono作为节拍器,间隔为250毫秒:
  if ( chronoA.hasPassed(250) )
  {
    // 如果自启动以来已通过250ms,则返回true
    chronoA.restart(); // 重新启动crono,以便稍后再次触发
    ledStateA = !ledStateA; // 将状态从0切换到1或从1切换到0
    digitalWrite(ledPinA,ledStateA);
  }
  
  // 使用Chrono作为节拍器,间隔为125毫秒:
   if ( chronoB.hasPassed(125) )
   { 
   // 如果自启动以来已经超过125毫秒,则返回true
    chronoB.restart(); // 重新启动crono,以便稍后再次触发
    ledStateB = !ledStateB;
    digitalWrite(ledPinB,ledStateB);
   }

  // 向串口发送指令'o', \ 'k', 可以查看相应的输出
  if(Serial.read() == 'o')
  {
    Serial.println("Pin_9 is stop... ...");
    chronoB.stop();
  }
  if(Serial.read() == 'k')
  {
    Serial.println("Pin_9 is start... ...");
    chronoB.restart();
  }
}

 

SCoop 库

使用请在GitHub搜索:  SCoop arduino

 修改版: https://github.com/Varsion/SCoop-Arduino

 官方版: https://github.com/fabriceo/SCoop

示例:

格式一
#include <SCoop.h>//引入头文件
defineTask(Task1);//定义线程一
void Task1::setup()
{
pinMode(13, OUTPUT);
//多线程的setup
}
void Task1::loop()
{
digitalWrite(13, HIGH);
sleep(1000);
digitalWrite(13, LOW);
sleep(1000);
//多线程的loop
}

void setup() {
mySCoop.start();

}//形式setup
void loop()
{
yield();
}//形式loop


格式二
#include <SCoop.h>//引入头文件
defineTaskLoop(Task2)//快速定义 省去setup
{
digitalWrite(12, HIGH);
sleep(100);
digitalWrite(12, LOW);
sleep(100);}

void setup() {
mySCoop.start();
pinMode(12, OUTPUT);
}
void loop()
{
yield();
}

更多示例 可参考笔者博客里关于遥控风扇的使用案例。点此转到(遥控风扇)

  • 26
    点赞
  • 239
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值