IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> QT连载3:基于QT和STM32H750的LORA试验平台(2) -> 正文阅读

[嵌入式]QT连载3:基于QT和STM32H750的LORA试验平台(2)

前言

? ? ? LORA平台已经可以使用了,可以正常的收发数据,当然这些东西都是基于1个H750的,没有试验两个750上相互传输是个什么情况,下一步准备做一下两个H750互传是否能完成同样的功能。先将试验平台的东西贴上来,看看小伙伴还有什么需求,如果有需求或者不明白的地方欢迎留言或者关注订阅号,在订阅号上留言,届时将积极回答。

平台硬件结构

? ? ?一个一个的连载吧,先说下QT上位软件吧。然后再介绍H750的LORA配置。

第一节:QT界面

? ? ? 整体界面是这样的。一部分一部分的按照思路说。

? ? (1)界面的标题肯定得修改下,LORA调试,这个东西应该挺好弄。直接在main.c里面,加入title的标题,代码如下:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.setWindowTitle("LORA调试");
    w.show();
    return a.exec();
}

? ? (2)整体分为发送和接收两个部分,所以建立个一tab选项卡,1分为2,里面内容一致,直接复制粘贴就可以了。但是tab的字体和栏的大小必须改变下,具体代码如下:

    ui->MYTAB->move(0,0);
    ui->MYTAB->setTabText(0,"LORA发送端");
    ui->MYTAB->setTabText(1,"LORA接收端");

    ui->MYTAB->setCurrentIndex(0);
    QFont ft;
    ft.setPointSize(12);
    ui->MYTAB->setFont(ft);

? ? 其中:设置0和1两个标签的名称,并且运行后第一个显示0标签。改变标签字体的大小,这个都是固定格式,直接复制粘贴就好。

? ? (3)串口设置。由于自己试验的话,波特率,停止位什么的都是固定的,所以这部分可以不要,仅仅添加一个串口号选项就好。代码如下:

    serialPortinfo1 = QSerialPortInfo::availablePorts();
    int count1 = serialPortinfo1.count();
    for(int i = 0; i<count1; i++)
    {
        ui->SPUPORT1->addItem(serialPortinfo1.at(i).portName());
    }

? ? 首先,扫描可用串口,然后放入设计好的串口号下拉菜单就好。

? ? 注:这部分只有打开软件的时候运行一次,所以串口转usb接口必须先接上,才能显示用的串口,如果先运行软件,后插入串口,这部分会检测不到可用的串口号。曾经试验过利用按钮来触发槽函数检索这部分。可以出现这个效果,但是会出现一个bug,就是点一次按钮,就会出现串口号的序列比如com1,再点一次,会再重复出现com1,串口号选项里出现两个com1。试验过怎么消除多余的那个,结果失败了,所以暂时没有用按钮扫描串口号。仅仅在打开软件的时候扫描下串口号。

? ? (4)按钮槽函数:这部分包含读取、保存还有其他按钮,直接设置槽函数就行。槽函数里面的内容下面再一一叙述。

? ? (5)发送窗口。

? ? 问题:发送窗口,

? ? 1. 输入只能从0到9,或者A到F,所以必须限定输入字符;

? ? 2. 输入部分取值仅仅为字符,但是发送的时候需要16进制,所以需要将字符转化。

? ? 解决办法:

? ? 第一个:代码如下:

    QRegExp regx("[A-Fa-f0-9]{40}");
    QValidator *validator1 = new QRegExpValidator(regx, ui->LORA1SENDDATA);
    ui->LORA1SENDDATA->setValidator(validator1);
    QValidator *validator2 = new QRegExpValidator(regx, ui->LORA2SENDDATA);
    ui->LORA2SENDDATA->setValidator(validator2);

? ? 至于为啥这样写,不知道,试验了,加入这个函数后,其他数据就不能输入了。如果需要其他字符,可以修改第一行里的内容。

? ? 第二个:代码如下:

void MainWindow::on_LORA1SEND_clicked()
{
    uint8_t gngetdatalength = ui->LORA1SENDDATA->text().length();
    QByteArray  gsgetsenddata = ui->LORA1SENDDATA->text().toUtf8();

    uint8_t LORA1senddata[gngetdatalength];

    for(int i=0; i<gngetdatalength; i++)
    {
        LORA1senddata[i] = int(gsgetsenddata.at(i));

        if((LORA1senddata[i]>=48)&&(LORA1senddata[i]<=57))
            LORA1senddata[i] = LORA1senddata[i] - 48;
        if((LORA1senddata[i]>=65)&&(LORA1senddata[i]<=70))
            LORA1senddata[i] = LORA1senddata[i] - 55;
    }

    uint8_t LORA1sendDataBuffer[qCeil(gngetdatalength*0.5)];

    if(gngetdatalength%2 == 0)
    {

        for(int i=0; i<gngetdatalength*0.5; i++)
        {
            LORA1sendDataBuffer[i] = LORA1senddata[2*i+1]+16*LORA1senddata[2*i];
        }

    }
    else
    {
        for(int j=0; j<(gngetdatalength+1)*0.5-1; j++)
        {
            LORA1sendDataBuffer[j] = LORA1senddata[2*j+1]+16*LORA1senddata[2*j];
        }
        LORA1sendDataBuffer[int((gngetdatalength+1)*0.5-1)] = LORA1senddata[gngetdatalength-1];
    }
}

? ? 一部分一部分的介绍:

? ? 1. 取输入字符的长度和字符内容;

? ? 2. for循环里:将字符赋值给另一个数组变量(变换一次需要定义一个数组,原因在前面文章里有详细介绍),并且将字符ASC码转化为16进制编码,这个可以看看ASCII的表,也就是减几个数,加几个数的逻辑。

? ? 3.if和else语句:输入为单个的字符:AA,需要将AA字符转化为AA16进制,这是长度为2,需要除以2,才能组成一个byte,也就是一个0xFF,这样才能发送。

? ? 所以当字符为AA(长度偶数)时,一种情况;当字符AAB(长度奇数)时,另一种情况。

? ? 当为AA时,转化为16进制,并将第一个A乘以16,加第二个A,就能得到需要的16进制0xAA了;

? ? 当为AAB时,AA处理方法和前面一样,后面的B,不作处理,直接按照0x0B处理。

? ? 这样就将任意长度的字符串转为可以发送的16进制数据了。

? (6)接收窗口

        nRxAllLength = m1Serial.bytesAvailable();
        recvData.resize(50);
        recvData = m1Serial.readAll();

        for(int i=0; i<nRxAllLength; i++)
        {
            gnReceiveData[i] = recvData[i];
        }
        nRxHeadCheck_H    = gnReceiveData[0];
        nRxHeadCheck_L    = gnReceiveData[1];
        nRxDataLength     = gnReceiveData[2];
        uint8_t gnShowData[50];
        QString hexbigshow;
        for(int i=0; i<nRxDataLength; i++)
        {
            gnShowData[i] = gnReceiveData[i+3];
            QString hexsmall = QString("%1").arg(gnShowData[i], 2, 16, QLatin1Char('0')).toUpper();

            hexbigshow=hexbigshow+" "+hexsmall;
        }
        if(nRxHeadCheck_H == 3)ui->LORA2RECEIVEDATA->setText(hexbigshow);
        if(nRxHeadCheck_H == 4)ui->LORA1RECEIVEDATA->setText(hexbigshow);

? ? 一部分一部分的解释:

? ? 1. 取接收数据长度;

? ? 2. 取接收数据;

? ? 3. 放入另一个数组里;

? ? 4. 根据接收协议,除去报头,将数据位放入字符串中,变为16进制显示,并且加入空格,然后加以显示。

? ? 5.报头3和4对应接收和发送LORA的对话框。具体协议可以看看上篇文章。https://blog.csdn.net/weixin_45426095/article/details/119248641?《QT连载2:基于QT和STM32H750的LORA试验平台(1)》

? ? (7)其他函数

? ? 这部分包含按钮下的槽函数,具体举例:

void MainWindow::on_LORA1TANS_clicked()
{
    ui->LORA1SEND->setEnabled(true);

    ui->LORA1ADDRSAVE->setEnabled(false);
    ui->LORA1BAUDSAVE->setEnabled(false);
    ui->LORA1SPEEDSAVE->setEnabled(false);
    ui->LORA1WORKMODESAVE->setEnabled(false);
    ui->LORA1TRANSMODESAVE->setEnabled(false);
    ui->LORA1CHANNELSAVE->setEnabled(false);
    ui->LORA1READINIT->setEnabled(false);

    ui->LORA1ADDRREAD->setEnabled(false);
    ui->LORA1BAUDREAD->setEnabled(false);
    ui->LORA1SPEEDREAD->setEnabled(false);
    ui->LORA1WORKMODEREAD->setEnabled(false);
    ui->LORA1TRANSMODEREAD->setEnabled(false);
    ui->LORA1CHANNELREAD->setEnabled(false);

    SLAVEADRESS_1 = 0x03;
    FUCTION_1     = 0x06;
    REGADRESS_1   = 0x00A5;
    REGNUM_1      = 0x0001;
    ModbusRTUSend_1(SLAVEADRESS_1,FUCTION_1,REGADRESS_1,REGNUM_1);
}

? ? 这个是传输模式按钮点击的槽函数,先是禁用和使能按钮,不至于发生点击错误。然后根据通讯协议发送数值,最好是搞几个形参的函数,这样每次发送都可以调用这个函数,好看,意义清晰。具体发送函数:

int MainWindow::ModbusRTUSend_1(uint8_t SlaAdrtemp,uint8_t Fuctemp,uint16_t RegAdrtemp,uint16_t RegNumtemp)
{
    sendData_1.resize(8);
    sendData_1[0] = SlaAdrtemp;
    sendData_1[1] = Fuctemp;
    sendData_1[2] =(RegAdrtemp&0XFF00)>>8;
    sendData_1[3] = RegAdrtemp;
    sendData_1[4] =(RegNumtemp&0XFF00)>>8;
    sendData_1[5] = RegNumtemp;
    nTxVerify_1 = 0xFFFF;
    for(int i=0;i<6;i++)
    {
       nTxVerify_1 = GetCRC16_1(sendData_1[i], nTxVerify_1);
    }
    sendData_1[6] = nTxVerify_1;
    sendData_1[7] =(nTxVerify_1&0XFF00)>>8;

    m1Serial.write(sendData_1);
    return 0;
}

? ? 解释:先将数据放入发送buffer,CRC校验,这个函数前述文章有介绍,然后执行write函数,这样数据就通过串口发送到H750了。

第二节:工具

? ? 这样QT界面和QT下面的程序都已经编写完毕。点击相应按钮,串口发送写入的数据,达到发送和接收的目的。当然这里仅仅是QT的接口部分,剩下的是H750的处理和LORA的发送部分,这节将下面再连载叙述。

? ? 使用虚拟串口工具和串口助手,就可以模拟具体串口发送和接收的数据了。当然都需要按照通讯协议去发和收。

? ? 经过验证,点击某个按钮,串口助手接收到的数据符合自己的预期,就证明QT部分编写正确了。

总结

? ? 这部分差不多和前面的一样,仅仅是在原有的基础上进行修改,大体框架都一致。有需要源代码的小伙伴可以关注订阅号,里面留言将发送源代码。

?

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-12 16:46:05  更:2021-08-12 16:47:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:45:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码