结合QT与STM32的串口通讯之跑马游戏设计与实现

通讯界面

在这里插入图片描述

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>

#include <QTimer>
#include <QString>
#include <QByteArray>

#include <QMessageBox>

#include "childwidget.h"

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:

    //连接信号槽
    void ConnectSignal();

    //界面初始化显示设置
    void WidgetInitial();

    //针对串口的操作
    void SerialPortOnorOFF();
    void SerialPortSetBaud();
    void SerialPortSetDataBit();
    void SerialPortSetFlowContronl();
    void SerialPortSetParity();
    void SerialPortSetStopBit();

    //针对定时器的操作
     void UpdateSerialPortNumber();
     void UpdateSendAutomaic();
     void UpdateReceive();

     //启动发送定时器
     void Send_automatic_Start();

     //子窗口退出到父窗口
     void ChildtoParent();

     //关闭
     void closeApp();

     //十六进制选择
     void checkChange();

     //下位机数据解析开启
     void dataAnalysis();

     //显示胜利界面
     void showVictroy();

private:
    Ui::Widget *ui;

private:
    QSerialPort *my_serial_port = new QSerialPort(this);

    QSerialPortInfo *my_serial_port_info = new QSerialPortInfo();

    QTimer *timer_serial_port_number = new QTimer();
    QTimer *timer_send_automatic = new QTimer();
    QTimer *timer_receive_data = new QTimer();
    QTimer *timer_exitGameKey4 = new QTimer();

    QString serial_port_name = "";
public:
    ChildWidget childW;
    bool is_hex = false;
    bool is_Startgame = false;
    bool is_ExitFromVictroy = false;//胜利界面跳出时候,是否按下key4
};

#endif // WIDGET_H

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    setWindowTitle("通讯连接");
    //连接信号槽
    ConnectSignal();

    WidgetInitial();

}

Widget::~Widget()
{
    qDebug()<<"exit UI";
    delete ui;
}

void Widget::ConnectSignal()
{
    //通讯连接
    connect(ui->pushButton_openport,SIGNAL(clicked(bool)),this, SLOT(SerialPortOnorOFF()));

    //通讯参数选择
    connect(ui->comboBox_baudrate, SIGNAL(currentIndexChanged(int)), this, SLOT(SerialPortSetBaud()));
    connect(ui->comboBox_databit,SIGNAL(currentIndexChanged(int)),this,SLOT(SerialPortSetDataBit()));
    connect(ui->comboBox_flowcontrol,SIGNAL(currentIndexChanged(int)),this,SLOT(SerialPortSetFlowContronl()));
    connect(ui->comboBox_checkbit,SIGNAL(currentIndexChanged(int)),this,SLOT(SerialPortSetParity()));
    connect(ui->comboBox_stopbit,SIGNAL(currentIndexChanged(int)),this,SLOT(SerialPortSetStopBit()));


    //串口号
    connect(timer_serial_port_number, SIGNAL(timeout()), this, SLOT(UpdateSerialPortNumber()));
    //发送数据给下位机
    connect(timer_send_automatic,SIGNAL(timeout()),this,SLOT(UpdateSendAutomaic()));
   //接收下位机数据
    connect(timer_receive_data,SIGNAL(timeout()),this,SLOT(UpdateReceive()));

    //进入游戏界面
    connect(ui->pushButton_gamein,SIGNAL(clicked(bool)),this,SLOT(Send_automatic_Start()));

    //子窗口退出信号触发槽函数
    connect(&childW,&ChildWidget::exitsignal,this,&Widget::ChildtoParent);

    //开发板按键4退出
    connect(timer_exitGameKey4,&QTimer::timeout,this,&Widget::ChildtoParent);

    //主窗口按键退出

    connect(ui->pushButton_exit,&QPushButton::clicked,this,&Widget::closeApp);

    //十六进制选择
    connect(ui->checkBoxHex,&QCheckBox::stateChanged,this,&Widget::checkChange);

    //游戏开始信号触发
    connect(&childW,&ChildWidget::startsignal,this,&Widget::dataAnalysis);

    //游戏胜利触发信号,开启发送定时器,给下位机发送胜利信息
    connect(&childW,&ChildWidget::showVicsignal,this,&Widget::showVictroy);


}

void Widget::WidgetInitial()//界面初始化显示设置
{

    timer_serial_port_number->start(10);//10ms刷新一次串口信息

    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()){

        qDebug() << "serial_port_name :"<<serial_port_name;
        qDebug()<<"info.portName():"<<info.portName();
        if(serial_port_name.compare(info.portName())){
            ui->comboBox_IO->clear();
            ui->comboBox_IO->addItem(info.portName());
            my_serial_port->setPortName(info.portName());
        }else{

            serial_port_name = info.portName();
        }
    }

    qDebug()<<"界面初始化完成";
}

void Widget::SerialPortOnorOFF()
{
    QString str = ui->pushButton_openport->text();

    if(str.compare("通讯连接")==0)
    {


        // 以 读写模式 打开串口
        bool is_open = my_serial_port->open(QIODevice::ReadWrite);

        if(is_open){
            ui->pushButton_openport->setText("连接成功");
            // 当串口成功打开后 配置基本传输设置
            SerialPortSetBaud();
            SerialPortSetDataBit();
            SerialPortSetFlowContronl();
            SerialPortSetParity();
            SerialPortSetStopBit();
            timer_receive_data->start(50);  // 50 ms 接收一次数据
        }


    }
    else
    {
        ui->pushButton_openport->setText("通讯连接");
        my_serial_port->close();   // 关闭串口
        timer_receive_data->stop();

        qDebug()<<"通讯断开";

    }
}


void Widget::SerialPortSetBaud()//波特率
{
    qDebug()<<"进入波特率设置";

    int index = ui->comboBox_baudrate->currentIndex();

    switch (index) {
    case 0:
        my_serial_port->setBaudRate(QSerialPort::Baud1200);
        break;
    case 1:
        my_serial_port->setBaudRate(QSerialPort::Baud2400);
        break;
    case 2:
        my_serial_port->setBaudRate(QSerialPort::Baud4800);
        break;
    case 3:
        my_serial_port->setBaudRate(QSerialPort::Baud9600);
        break;
    case 4:
        my_serial_port->setBaudRate(QSerialPort::Baud19200);
        break;
    case 5:
        my_serial_port->setBaudRate(QSerialPort::Baud38400);
        break;
    case 6:
        my_serial_port->setBaudRate(QSerialPort::Baud57600);
        break;
    case 7:
        my_serial_port->setBaudRate(QSerialPort::Baud115200);
        break;
    case 8:
        my_serial_port->setBaudRate(QSerialPort::UnknownBaud);
        break;
    }
}

void Widget::SerialPortSetDataBit()//数据位
{
    qDebug()<<"数据位设置";
    int index = ui->comboBox_databit->currentIndex();
    switch (index) {
    case 0:
        my_serial_port->setDataBits(QSerialPort::Data8);
        break;
    case 1:
        my_serial_port->setDataBits(QSerialPort::Data7);
        break;
    case 2:
        my_serial_port->setDataBits(QSerialPort::Data6);
        break;
    case 3:
        my_serial_port->setDataBits(QSerialPort::Data5);
        break;
    case 4:
        my_serial_port->setDataBits(QSerialPort::UnknownDataBits);
        break;
    }
}

void Widget::SerialPortSetFlowContronl()//流控制
{
    int index = ui->comboBox_flowcontrol->currentIndex();
    switch(index)
    {
    case 0:
        my_serial_port->setFlowControl(QSerialPort::NoFlowControl);
        break;
    case 1:
        my_serial_port->setFlowControl(QSerialPort::HardwareControl);
        break;
    case 2:
        my_serial_port->setFlowControl(QSerialPort::SoftwareControl);
        break;
    case 3:
        my_serial_port->setFlowControl(QSerialPort::UnknownFlowControl);
        break;
    }
}

void Widget::SerialPortSetParity()//校验位
{
    int index = ui->comboBox_checkbit->currentIndex();

    switch (index) {
    case 0:
        my_serial_port->setParity(QSerialPort::NoParity);
        break;
    case 1:
        my_serial_port->setParity(QSerialPort::EvenParity);
        break;
    case 2:
        my_serial_port->setParity(QSerialPort::OddParity);
        break;
    case 3:
        my_serial_port->setParity(QSerialPort::SpaceParity);
        break;
    case 4:
        my_serial_port->setParity(QSerialPort::MarkParity);
        break;
    case 5:
        my_serial_port->setParity(QSerialPort::UnknownParity);
        break;
    }
}

void Widget::SerialPortSetStopBit()//停止位
{
    int index = ui->comboBox_stopbit->currentIndex();

    switch (index) {
    case 0:
        my_serial_port->setStopBits(QSerialPort::OneStop);
        break;
    case 1:
        my_serial_port->setStopBits(QSerialPort::OneAndHalfStop);
        break;
    case 2:
        my_serial_port->setStopBits(QSerialPort::TwoStop);
        break;
    case 3:
        my_serial_port->setStopBits(QSerialPort::UnknownStopBits);
        break;
    }
}

//更新串口号
void Widget::UpdateSerialPortNumber(){

   // qDebug() <<"进入更新串口号函数";

    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()){

        if(serial_port_name.compare(info.portName())){
            ui->comboBox_IO->clear();
            ui->comboBox_IO->addItem(info.portName());
            my_serial_port->setPortName(info.portName());
            return;
        }else{

            serial_port_name = info.portName();
            return;
        }
    }

    ui->comboBox_IO->clear();
    ui->comboBox_IO->addItem("无");



}

//发送数据给下位机
void Widget::UpdateSendAutomaic()
{
    //qDebug()<<"发送数据给下位机";
    QByteArray data;
    data.resize(11);
    data[0] = 0xaa;
    data[1] = 0xf9;

    for(int i = 0; i < 8; i++)
    {
        data[i+2] = 0x00;
    }
    data[10] = 0xdd;
    if(childW.VictroyShow.isOpenVictroy && !is_ExitFromVictroy)
    {
        //victory界面开启,发送数据给下位机
        if(1 == childW.horse_win)
        {
            //horse1赢
           data[2] = 0x01;
        }
        else if(2 == childW.horse_win)
        {
            //horse2赢
            data[3] = 0x02;

        }
        else if(3 == childW.horse_win)
        {
            //horse3赢
            data[4] = 0x03;

        }
    }


    my_serial_port->write(data);//16进制发送给下位机
    qDebug()<<data.toHex();
    timer_send_automatic->stop();
}

void Widget::Send_automatic_Start()
{
    qDebug()<<"进入游戏界面";
    childW.isExit = false;
    childW.show();
    this->hide();
    is_hex = true;
}

//更新接收数据
void Widget::UpdateReceive()
{
    //数据解析
    QByteArray data = my_serial_port->readAll();
    QString str(data);

    if(!data.isNull())
    {
        if(is_hex)
        {
            //HEX文件接收
            QByteArray temp;
            data = data.toHex();

            for(int i = 0; i < data.length()/2; ++i)
            {
                temp += data.mid(i*2,2) + "  ";//每两个字节加一个空格
            }
           ui->plainTextEdit__receive->appendPlainText(temp);

           if(is_Startgame && !childW.isExit)
           {
               if(data.mid(2*2,2) == "01")
               {
                 //按键1按下
                 qDebug()<<"key1的值:"<<data.mid(2*2,2);
                 childW.key1Move();

               }
               else if(data.mid(2*3,2) == "02")
               {
                   //按键2按下
                   qDebug()<<"key2的值:"<<data.mid(2*3,2);
                   childW.key2Move();
               }
               else if(data.mid(2*4,2) == "03")
               {
                   //按键3按下
                   qDebug()<<"key3的值:"<<data.mid(2*4,2);
                   childW.key3Move();
               }
           }
           if(data.mid(2*5,2) == "04")
           {
               //按键4按下,退出游戏
               qDebug()<<"key4的值:"<<data.mid(2*5,2);
               if(!timer_exitGameKey4->isActive())
               {
                    timer_exitGameKey4->start(50);
               }

           }
        }
        else
        {
            //文本文件接收
            ui->plainTextEdit__receive->appendPlainText(str);
        }
    }


}

//子窗口退出到父窗口
void Widget::ChildtoParent()
{
    childW.LableShowChange();
    childW.close();
    this->show();
    is_Startgame = false;

    if(!ui->checkBoxHex->isChecked())
    {
        is_hex  = false;
        qDebug()<<"文本形式解析";
    }
    else
    {
        is_hex = true;
        qDebug()<<"十六进制解析";
    }
    if(timer_exitGameKey4->isActive())
    {
        timer_exitGameKey4->stop();
    }
    if(childW.VictroyShow.isOpenVictroy)
    {
        /***/
        //还原下位机各引脚信号
        is_ExitFromVictroy = true;
        this->UpdateSendAutomaic();
        is_ExitFromVictroy = false;
        /***/
        qDebug()<<"胜利界面关闭";
        childW.VictroyShow.close();
    }
}

void Widget::closeApp()
{
    this->close();
}

void Widget::checkChange()
{

    if(!ui->checkBoxHex->isChecked())
    {
        ui->checkBoxHex->setChecked(false);
        is_hex  = false;
        qDebug()<<"文本形式解析";
    }
    else
    {
        ui->checkBoxHex->setChecked(true);
        is_hex = true;
        qDebug()<<"十六进制解析";
    }


}

void Widget::dataAnalysis()
{

    //开始游戏
    qDebug()<<"开始游戏";
    is_Startgame = true;

}

void Widget::showVictroy()
{
     timer_send_automatic->start(50);
}

游戏界面

在这里插入图片描述

#ifndef CHILDWIDGET_H
#define CHILDWIDGET_H

#include <QWidget>
#include <QTimer>
#include "victroy.h"

namespace Ui {
class ChildWidget;
}

class ChildWidget : public QWidget
{
    Q_OBJECT

public:
    explicit ChildWidget(QWidget *parent = 0);
    ~ChildWidget();
signals:
    void exitsignal();
    void startsignal();
    void showVicsignal();
public slots:
    void exitslot();
    void StartorStopGame();
    void key1Move();
    void key2Move();
    void key3Move();
    void victroyHorse();
    void GameReturn();

public:
    int horse1_x;
    int horse2_x;
    int horse3_x;
    int offsetx;
    int offsetx_start;
    int horse1_startx;
    int horse2_startx;
    int horse3_startx;
    int horse1_starty;
    int horse2_starty;
    int horse3_starty;
    bool isStartKey1;
    bool isStartKey2;
    bool isStartKey3;
    bool isExit;
    int horse_win;

    Victroy VictroyShow;

    void LableShowChange();
    void VictroyShowUI();

private:
    Ui::ChildWidget *ui;
    QTimer *timerVictroy = new QTimer();
};

#endif // CHILDWIDGET_H

#include "childwidget.h"
#include "ui_childwidget.h"
#include <QDebug>

ChildWidget::ChildWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ChildWidget)
{
    ui->setupUi(this);
    horse1_x = ui->label_horse1->x();
    horse2_x = ui->label_horse2->x();
    horse3_x = ui->label_horse3->x();
    horse1_startx = horse1_x;
    horse2_startx = horse2_x;
    horse3_startx = horse3_x;
    horse1_starty = ui->label_horse1->y();
    horse2_starty = ui->label_horse2->y();
    horse3_starty = ui->label_horse3->y();
    offsetx = 5;
    offsetx_start = 80;
    isStartKey1 = true;
    isStartKey2 = true;
    isStartKey3 = true;
    isExit = false;
    horse_win = 0;

    ui->pushButton_key1->setEnabled(false);
    ui->pushButton_key2->setEnabled(false);
    ui->pushButton_key3->setEnabled(false);

    connect(ui->pushButton_exit,&QPushButton::clicked,this,&ChildWidget::exitslot);
    connect(ui->pushButton_start,&QPushButton::clicked,this,&ChildWidget::StartorStopGame);

    //模拟按键
     connect(ui->pushButton_key1,&QPushButton::clicked,this,&ChildWidget::key1Move);
     connect(ui->pushButton_key2,&QPushButton::clicked,this,&ChildWidget::key2Move);
     connect(ui->pushButton_key3,&QPushButton::clicked,this,&ChildWidget::key3Move);

    //胜利弹框
     connect(timerVictroy,&QTimer::timeout,this,&ChildWidget::victroyHorse);

     //鼠标事件销毁胜利弹框,返回游戏界面
     connect(&VictroyShow,&Victroy::exitsig,this,&ChildWidget::GameReturn);


    //设置背景图片
    this->setAutoFillBackground(true);
    QPalette pal;
    QPixmap pix(":/new/prefix1/field.png");
    pal.setBrush(QPalette::Window,QBrush(pix));
    this->setPalette(pal);


}

ChildWidget::~ChildWidget()
{

    delete ui;
}


void ChildWidget::exitslot()
{
    emit exitsignal();
}

void ChildWidget::StartorStopGame()
{
    ui->pushButton_key1->setEnabled(true);
    ui->pushButton_key2->setEnabled(true);
    ui->pushButton_key3->setEnabled(true);
    ui->label_horse1->setPixmap(QPixmap(":/new/prefix1/horse.png"));
    ui->label_horse2->setPixmap(QPixmap(":/new/prefix1/horse.png"));
    ui->label_horse3->setPixmap(QPixmap(":/new/prefix1/horse.png"));
    timerVictroy->start(20);
    emit startsignal();
}

void ChildWidget::LableShowChange()
{
    isStartKey1 = true;
    isStartKey2 = true;
    isStartKey3 = true;
    isExit = true;
    if(!timerVictroy->isActive())
    {
        timerVictroy->start(20);
    }
    if(0 == offsetx)
    {
        offsetx = 5;
    }
    ui->pushButton_key1->setEnabled(false);
    ui->pushButton_key2->setEnabled(false);
    ui->pushButton_key3->setEnabled(false);
    ui->label_horse1->move(horse1_startx,horse1_starty);
    ui->label_horse2->move(horse2_startx,horse2_starty);
    ui->label_horse3->move(horse3_startx,horse3_starty);
    ui->label_horse1->setPixmap(QPixmap(":/new/prefix1/Num1.png"));
    ui->label_horse2->setPixmap(QPixmap(":/new/prefix1/Num2.png"));
    ui->label_horse3->setPixmap(QPixmap(":/new/prefix1/Num3.png"));
}

void ChildWidget::key1Move()
{
    horse1_x = ui->label_horse1->x();
    if(isStartKey1)
    {
        ui->label_horse1->move(horse1_x - offsetx_start,horse1_starty);
        isStartKey1 = false;
    }
    else
    {
        ui->label_horse1->move(horse1_x - offsetx,ui->label_horse1->y());
    }
}

void ChildWidget::key2Move()
{
    horse2_x = ui->label_horse2->x();
    if(isStartKey2)
    {
        ui->label_horse2->move(horse2_x - offsetx_start,horse2_starty);
        isStartKey2 = false;
    }
    else
    {
        ui->label_horse2->move(horse2_x - offsetx,ui->label_horse2->y());
    }
}

void ChildWidget::key3Move()
{
    horse3_x = ui->label_horse3->x();
    if(isStartKey3)
    {
        ui->label_horse3->move(horse3_x - offsetx_start,horse3_starty);
        isStartKey3 = false;
    }
    else
    {
        ui->label_horse3->move(horse3_x - offsetx,horse3_starty);
    }
}

void ChildWidget::victroyHorse()
{
    int tempPosition1 = ui->label_horse1->x();
    int tempPosition2 = ui->label_horse2->x();
    int tempPosition3 = ui->label_horse3->x();

    if(!(isStartKey1 && isStartKey2 && isStartKey3))
    {
        if(tempPosition1 <= 80 || tempPosition2 <= 80 || tempPosition3 <= 80)
        {
            timerVictroy->stop();
            if(tempPosition1 <= 80 && tempPosition1 < tempPosition2 && tempPosition1 < tempPosition3)
            {
                //horse1胜利
                qDebug() <<"horse1胜利";
                VictroyShow.victoryHorse1Show();
                horse_win = 1;
            }
            else if(tempPosition2 <= 80 && tempPosition2 < tempPosition1 && tempPosition2 < tempPosition3)
            {
                qDebug() <<"horse2胜利";
                VictroyShow.victoryHorse2Show();
                horse_win = 2;
            }
            else if(tempPosition3 <= 80 && tempPosition3 < tempPosition1 && tempPosition3 < tempPosition1)
            {
                qDebug() <<"horse3胜利";
                VictroyShow.victoryHorse3Show();
                horse_win = 3;
            }
            else
            {
                qDebug()<<"horse有并列第一";
            }
            offsetx = 0;
            VictroyShowUI();
        }

    }

}

void ChildWidget::VictroyShowUI()
{
    VictroyShow.show();
    this->hide();
    emit showVicsignal();
}

void ChildWidget::GameReturn()
{
    VictroyShow.close();
    LableShowChange();
    this->show();
    horse_win = 0;
}

游戏中
在这里插入图片描述

胜利界面

#ifndef VICTROY_H
#define VICTROY_H

#include <QWidget>
#include <QMouseEvent>
namespace Ui {
class Victroy;
}

class Victroy : public QWidget
{
    Q_OBJECT

public:
    explicit Victroy(QWidget *parent = 0);
    ~Victroy();

private:
    Ui::Victroy *ui;
public:
    void victoryHorse1Show();
    void victoryHorse2Show();
    void victoryHorse3Show();
    bool isOpenVictroy;
signals:
    void exitsig();
protected:
    void mousePressEvent(QMouseEvent *event);
};

#endif // VICTROY_H

#include "victroy.h"
#include "ui_victroy.h"
#include "QDebug"

Victroy::Victroy(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Victroy)
{
    ui->setupUi(this);
    isOpenVictroy = false;
    setAttribute(Qt::WA_DeleteOnClose);
}

Victroy::~Victroy()
{
    isOpenVictroy = false;
    qDebug()<<"胜利界面析构";
    delete ui;
}

void Victroy::victoryHorse1Show()
{
    //设置背景图片
    isOpenVictroy = true;
    this->setAutoFillBackground(true);
    QPalette pal;
    QPixmap pix(":/new/prefix1/victory1.jpg");
    pal.setBrush(QPalette::Window,QBrush(pix));
    this->setPalette(pal);

}

void Victroy::victoryHorse2Show()
{
    //设置背景图片
    isOpenVictroy = true;
    this->setAutoFillBackground(true);
    QPalette pal;
    QPixmap pix(":/new/prefix1/victory 2.jpg");
    pal.setBrush(QPalette::Window,QBrush(pix));
    this->setPalette(pal);

}

void Victroy::victoryHorse3Show()
{
    //设置背景图片
    isOpenVictroy = true;
    this->setAutoFillBackground(true);
    QPalette pal;
    QPixmap pix(":/new/prefix1/victory3.jpg");
    pal.setBrush(QPalette::Window,QBrush(pix));
    this->setPalette(pal);

}

void Victroy::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        emit exitsig();
    }
}

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值