前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于状态机控制 Led(QT实现)

基于状态机控制 Led(QT实现)

作者头像
嵌入式小屋
发布2022-04-27 17:22:23
6970
发布2022-04-27 17:22:23
举报

在现实生活中,我们在不同的状态,对于相同的事,会有不同的反应,就拿天气对上班的影响。可以例举下图:

天气

上班方式

晴朗

走路

下雨

打伞上班

台风

不上班

还有,我们学硬件时的点亮Led,也会有以下操作:

源状态

目标状态

事件

常亮(Light)

熄灭(close)

close

常亮(Light)

闪烁 (Blink)

blink

熄灭(Close )

常亮(Light)

light

熄灭(Close )

闪烁(Blink)

blink

闪烁(Blink)

熄灭(close)

close

闪烁(Blink)

常亮(Light)

light

按照上图,我们可以看出:

当发出 close 事件时,Led 有可能处于不同状态,如常亮,或者闪烁状态,这里面还是省略了,如果目标状态与当前状态一样应该要怎么办。在下面代码中实现了。

这里将演示如何实现上述表格的状态,视频如下:

http://mpvideo.qpic.cn/0bc32iaegaaanuangw6igvqvbuwdipjaaqya.f10002.mp4?

其中主要的代码如下:

1. LedController 控制类 的头文件

以下主要看注释部分:

代码语言:javascript
复制
class LedController : public QObject
{
    Q_OBJECT
public:
    typedef enum {
        LIGHT,
        BLINK,
        CLOSE
    }eLedState,eLedCmd; // Led 的状态枚举

    typedef struct {
        eLedCmd cmd;
        QString msg;
    }eLedEvent;

    explicit LedController(QObject *parent = nullptr);
    explicit LedController(Ui::Widget *ui, QObject *parent = nullptr);

private:
    eLedState m_ledState = CLOSE; // 记录 Led 状态
    QQueue<eLedEvent> m_cmdQueue;
    bool m_handleMessage = false;
    QTimer *timer;
    Ui::Widget *m_ui;
    QPixmap *ledLightPic;
    QPixmap *ledClosePic;

signals:
    void controlLedState(eLedEvent enent);
     ...
     ...
}

2. 根据当前 Led 状态进行转换(在控制类 的源文件中)

代码语言:javascript
复制
void LedController::onHandleLedEvent()
{
    if (!m_cmdQueue.empty()) {
        //说明正在处理信息,获取事件
        m_handleMessage = true;
        eLedEvent ledEvent = m_cmdQueue.dequeue();
        QString  msg = ledEvent.msg;

        //根据 Led 状态散转
        switch(m_ledState)
        {
            case LIGHT:   //当前 Led 已经被点亮
                switch (ledEvent.cmd)
                {
                    case LIGHT:
                        qDebug() << "当前 Led 已经为点亮状态";
                    break;
                    case BLINK:
                        qDebug() << "当前 Led 为点亮状态, 转换为闪烁状态";
                        m_ledState = BLINK;
                        startBlink(1000);
                    break;
                    case CLOSE:
                        qDebug() << "当前 Led 为点亮状态, 转换为关闭状态";
                        m_ledState = CLOSE;
                        closeLed();
                    break;

                    default:
                    break;
                }
            break;
            case BLINK:   //当前 Led 已经是闪烁状态
                switch (ledEvent.cmd)
                {
                    case LIGHT:
                        qDebug() << "当前 Led 为闪烁状态,转换为点亮状态";
                        m_ledState = LIGHT;
                        stopBlink();
                        lightLed();
                    break;
                    case BLINK:
                        qDebug() << "当前 Led 为闪烁状态,修改闪烁间隔为 "+ msg + " ms";
                        startBlink(msg.toInt());
                        m_ledState = BLINK;
                    break;
                    case CLOSE:
                        qDebug() << "当前 Led 为闪烁状态,转换为关闭状态";
                        m_ledState = CLOSE;
                        stopBlink();
                        closeLed();
                    break;

                    default:
                    break;
                }
            break;
            case CLOSE:   //当前 Led 已经是关闭状态
                switch (ledEvent.cmd)
                {
                    case LIGHT:
                        qDebug() << "当前 Led 为关闭状态,转换为点亮状态";
                        m_ledState = LIGHT;
                        lightLed();
                    break;
                    case BLINK:
                        qDebug() << "当前 Led 为关闭状态,转换为闪烁状态,间隔为 " + msg + " ms";
                        m_ledState = BLINK;
                        startBlink(msg.toInt());
                    break;
                    case CLOSE:
                        qDebug() << "当前 Led 已经为关闭状态";
                    break;

                    default:
                    break;
                }
            break;
        }
         m_handleMessage = false;
    }
}

3. 最终结果如开头视频所示

4. 源代码

后台回复:状态机

如果你还是没看懂,建议把代码运行跑跑看。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-12-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 嵌入式小屋 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档