1、说明
从大一入门接触到Arduino后来进阶到PlatformIO,如今继续考研,放下Arduino系列。
有相关心得体会和相关内容分享出来。
1.1、建议
从做题家出身的初学者们,不要轻视Arduino,不论先学后学51 32或者Arduino,都是有很好的辅助作用。
先学arduino,会对32 51等功能更理解容易深入;先学习51 32会更容易通过Arduino得到体验感,作为保底的工具。
总之,不能轻易看扁任何的技术,技术是自我实现的工具之一,但起码也是你保底措施!
2、自造的设计模式
因本人省创项目用到ESP32系列单片机,但并不想再去学IDF(手册不习惯),故继续Arduino开发,涉及到相关内容会在其他博客补充,这里抽象出个人认为最重要的几个设计思路。
2.1、非阻塞任务循环
顾名思义,就是不阻塞的delay,但是在裸机开发中很常用,代码如下:
解释很详细,看注释即可
#include <iostream>
using namespace std;
#define TIME_INTERVAL 100 // 随机间隔时间:单位毫秒
#define INTERVAL_T1 2100 // 任务一,预期间隔时间
#define TASK1 random(INTERVAL_T1 - TIME_INTERVAL, INTERVAL_T1 + TIME_INTERVAL) // 任务一,随机间隔时间
int main(int argc, char *argv[])
{
while (1)
{
static uint32_t t_task1 = 0; // 任务一计时
// 获取上电后的运行时间,millis单位为ms;约等于PC下自程序启动后的占用CPU时间
if (millis() - t_task1 > TASK1)
{
t_task1 = millis();//更新时间戳;约47天后t_task1溢出.
// Todo...
}
// 任务二:可复制逻辑...
}
}
2.2、假任务循环队列,分次执行
比如任务量大,但内存有限,可通过分批次循环执行任务来完成,代码如下:
#include <iostream>
#include <unistd.h>
using namespace std;
// 自己总结的设计模式:假任务循环队列,分次执行
// 个人更多用在wifi发送阶段,因内存不够,只能分段
void roundQueue()
{
// 分为几次,就有几个任务数
#define TaskNumAll 3 //以3为例子
static unsigned char Tcount = 0; //自定义初始值,匹配case,推荐用0
switch (Tcount)
{
case 0:
{
cout << "run Task1" << endl;
break;
}
case 1:
{
cout << "run Task2" << endl;
break;
}
case 2:
{
cout << "run Task3" << endl;
break;
}
// 不会出现意外
// default:
// break;
}
++Tcount %= TaskNumAll;
/* 这种错误,在末尾case会溢出;
可用default设置Tcount为初始值重新开始,
但少执行一次有效任务执行,效率低
Tcount++ %= TaskNumAll;
*/
}
int main(int argc, char *argv[])
{
while (1)
{
roundQueue();
sleep(1);
}
}
2.3、搭配使用
混合在一起使用,才是常见思路,分为两个文件(清晰看着),可拷贝使用:
#include "Arduino.h"
// 1.逻辑功能
#define TaskNumAll 3 //循环任务数
void roundQueue()
{
static unsigned char TaskCount = 0;
switch (TaskCount)
{
case 0:
{
cout << "run Task1" << endl;
break;
}
case 1:
{
cout << "run Task2" << endl;
break;
}
case 2:
{
cout << "run Task3" << endl;
break;
}
}
++TaskCount %= TaskNumAll;
}
// 2.宏配置
#define TIME_INTERVAL 100 // 随机间隔时间:单位毫秒
#define INTERVAL_T1 2100 // 任务一,预期间隔时间
#define TASK1 random(INTERVAL_T1 - TIME_INTERVAL, INTERVAL_T1 + TIME_INTERVAL) // 任务一,随机间隔时间
#define INTERVAL_T2 2100 // 任务一,预期间隔时间
#define TASK2 random(INTERVAL_T2 - TIME_INTERVAL, INTERVAL_T2 + TIME_INTERVAL) // 任务一,随机间隔时间
#include "3.3.NonBlockPollingLoopQueuePattern.hpp"
/*
用法:结合上述两种写法,常见于arduino单片机 非阻塞任务循环队列
场景:比如esp32的mqtt要发送很多内容,若一次性发出,会内存爆炸,所以分批次发送
时间:记录于大三下,对Arduino入门进行想法设计,不知不觉和Arduino就有了默契
补充:配合使用定时器和freertos任务并不对轮循造成冲突
*/
void setup(){};
void loop()
{
// 任务一计时:获取数据
static uint32_t t_task1 = 0;
if (millis() - t_task1 > TASK1)
{
t_task1 = millis(); //更新时间戳;约47天后t_task1溢出.
roundQueue(); // Todo...
}
// 任务二计时:发送数据,可复制逻辑...
static uint32_t t_task2 = 0;
if (millis() - t_task2 > TASK2)
{
t_task2 = millis();
// Todo...
}
}
3、总结
水平有限,不对之处,希望指正!诸位三无量!