1 简介
1、多线程是什么?为什么要用多线程?
进程 :是一个正在执行中的程序,每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元。
线程:就是进程中的一个独立控制单元,线程在控制着进程的执行。一个进程中至少有一个线程。
多线程:一个进程中不只有一个线程。多线程是指从软件或者硬件上实现多个线程并发执行的技术。
2、为什么要用多线程?
- 为了更好的利用cpu的资源,如果只有一个线程,则第二个任务必须等到第一个任务结束后才能进行,如果使用多线程则在主线程执行任务的同时可以执行其他任务,而不需要等待;
- 进程之间不能共享数据,线程可以;
- 系统创建进程需要为该进程重新分配系统资源,创建线程代价比较小;
在Arduino实际开发中,我们可能会遇到多任务处理的问题,Arduino需要不断的读取外部管脚所输入的传感器数值;同时,要产生PWM方波来控制步进电机;如果有上位机,则还需要完成数据的收发工作。
针对此类多任务同时处理的工作场景,解决方法有多种,第一:使用计时器或外部中断机制,完成多任务处理;第二:使用Arduino 多线程技术,本质上也是中断机制。
Arduino开发板借助SCoop即可轻松实现多线程。
2 使用方法
GitHub链接下载此文件,Arduino IDE 中选择 项目 → 加载库 → 添加一个 .ZIP库
,然后找到刚才压缩的SCoop.zip文件,添加完成之后就可以使用了。GitHub下载地址:https://github.com/fabriceo/SCoop
第一步,引用库文件
#include "SCoop.h"
第二步,setup函数里,调用 mySCoop.start()
命令
void setup(){
mySCoop.start();
}
第三步,loop函数里,调用 yield()
命令
void loop(){
yield();
}
第四步,定义线程并实现具体的功能,有两种定义方式
(1)完整定义
定义一个名字为“TaskOne”的任务
defineTask(TaskOne);
void TaskOne::setup(){
// 初始化
}
void TaskOne::loop(){
// 执行的任务
}
(2)快速定义
如果线程中执行的动作不需要setup的话,还可以使用defineTaskLoop快速定义的方式,如下:
defineTaskLoop(TaskTwo){
// 实现具体的功能
}
注意: 使用此库之后,如果只是想在某个线程中暂停,请使用sleep(ms)
作为延时,因为 sleep(ms)
只针对当前线程,而 delay(ms)
是针对全局的。
3 测试代码
/*********************************************************************
——————1.开发环境:Arduino IDE————————————————————————————————————————
——————2.使用开发板型号:Arduino UNO——————————————————————————————————
——————3.功能:2个LED分别以0.5秒和1秒的速度闪烁,2和3引脚分别接LED——————
*********************************************************************/
#include <SCoop.h>
# define LED1 2 // 初始化引脚
#define LED2 3
defineTask(TaskOne); // 创建子线程1
defineTask(TaskTwo); // 创建子线程2
void TaskOne::setup(){ // 线程1设定
pinMode(LED1,OUTPUT)
}
void TaskOne::loop(){ //线程1循环
digitalWrite(LED1,HIGH);
sleep(500);
digitalWrite(LED1,LOW);
sleep(500);
}
void TaskTwo::setup(){ //线程2设定
pinMode(LED2,OUTPUT)
}
void TaskTwo::loop(){ //线程2循环
digitalWrite(LED2,HIGH);
sleep(1000);
digitalWrite(LED2,LOW);
sleep(1000);
}
void setup(){
mySCoop.start();
}
void loop(){
yield();
}
Arduino虽然可以实现并发处理,但最多只能支持两三个并发任务,再多就可能报错了,如果还想处理更多并发任务,推荐用 stm32。