PlatformIO&Arduino之经验总结

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、总结

水平有限,不对之处,希望指正!诸位三无量!

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值