我是靠谱客的博主 沉默舞蹈,最近开发中收集的这篇文章主要介绍Linux驱动实现AT指令,QT Linux实现AT指令处理框架,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

本框架在QT4.8.6版本环境下编写。

一、业务逻辑的诞生

1.1 了解一下什么是AT指令

94bf3eae96826fe42bd406b665492b1a.png

1.2 思考在QT上如何处理AT指令

看了下网上大多数人实现的在Linux下的4G模块AT指令收发控制,以及在QT上实现的,还有某些厂商实现的解析框架,其实就是在处理串口的收发,但未免做得有点糙,问题点也很多,比如很多人压根就没做指令回复的超时处理,万一要是发生了,那将给整个程序带来致命性的伤害。

最近的项目上需要在QT上处理AT指令的发送和回复,基于这样的环境,于是我决定实现两条线程,一条用于处理设备的初始化,一条用于处理在主进程指令的发送,由于AT指令收发存在延时,所以直接在主进程上延时,QT主进程就卡死了,这就是为什么我一定要用线程去处理的结果。

1.3 特别提醒

如果是在Linux操作串口设备,qt也要有相应的权限,使用如下指令即可。

sudo qtcreator &

二、移植通用串口框架到QT上

三、Gobal_Item_flag.h

该文件主要是用于串口通信模块(支持AT指令)、以及一些全局参数的定义。

#ifndef GOBAL_ITEM_FLAG_H

#define GOBAL_ITEM_FLAG_H

#include "posix_qextserialport.h"

#define __NBIOT

#define DEV_NAME "/dev/ttyUSB0"

#define RECV_DATA_LEN 1024

extern char recv_buffer[RECV_DATA_LEN];

//AT_CMD_DEFINE Start

#ifdef __NBIOT

#define AT_TEST_OK "AT"

#define GET_IMSI "AT+CIMI"

#define GET_SIGNAL "AT+CSQ"

#define GET_SUPPORT_NBAND "AT+NBAND=?"

#define GET_CURRENT_NBAND "AT+NBAND?"

#define SET_NBAND "AT+NBAND=5"

#define GET_CGATT "AT+CGATT"

#define CREATE_TCP_SOCKET "AT+NSOCR=STREAM,6,56000,1"

#define CONNECT_TCP_SERVER "AT+NSOCO=1,120.78.136.134,9002"

#define HARDWARE_RESET "AT+NRB"

#elif __ESP8266

#define AT_TEST_OK "AT"

#define AT_SET_MODE "AT+CWMODE=%d"

#define AT_CONNECT_ROUTER "AT+CWJAP="%s","%s""

#define AT_CONNECT_SERVER "AT+CIPSTART="%s","%s",%d"

#define AT_SET_CIP_MODE "AT+CIPMODE=1"

#define AT_ENTER_CIP_MODE "AT+CIPSEND"

#elif __ME3630

#define AT_TEST_OK "AT"

#define CREATE_TCP_SOCKET "AT+ZIPCALL=1"

#define CONNECT_TCP_SERVER "AT+ZIPOPEN=1,0,120.78.136.134,9001"

#define AT_SEND_DATA "AT+ZIPSEND=1,%s";

#endif

//AT_CMD_DEFINE End

#endif // GOBAL_ITEM_FLAG_H

四、网络接口线程定义

头文件network_interface.h

#ifndef NETWORK_INTERFACE_H

#define NETWORK_INTERFACE_H

#include

#include

#include

#include

#include "Gobal_Item_flag.h"

class NetWork_Interface : public QThread

{

Q_OBJECT

public:

explicit NetWork_Interface(QObject *parent = 0);

~NetWork_Interface();

//if Status is True,Thread is stop,else is Runing

void NetWork_Thread_change(bool Status);

int Send_AT_Cmd(QString cmd_buffer,const char *success_ack,const char *error_ack,int timeout);

private:

Posix_QextSerialPort *NetWork_Port ;

volatile bool Stop_flag ;

int Uart_Init(const char *dev_name,BaudRateType BaudRate,DataBitsType DataBits,

ParityType ParityBits,StopBitsType StopBits,FlowType FlowControl,int TimeOut);

protected:

void run();

signals:

public slots:

};

#endif // NETWORK_INTERFACE_H

这里实现了串口的初始化,线程状态的控制,线程函数执行以及AT指令的发送函数。

接口实现network_interface.cpp

#include "network_interface.h"

//全局串口数据接收缓存区

char recv_buffer[RECV_DATA_LEN] = {0};

//串口初始化

int NetWork_Interface::Uart_Init(const char *dev_name,BaudRateType BaudRate,DataBitsType DataBits,

ParityType ParityBits,StopBitsType StopBits,FlowType FlowControl,int TimeOut)

{

this->NetWork_Port = new Posix_QextSerialPort(dev_name,QextSerialBase::Polling);

if(NetWork_Port->open(QIODevice::ReadWrite))

{

this->NetWork_Port->setBaudRate(BaudRate);

this->NetWork_Port->setDataBits(DataBits);

this->NetWork_Port->setParity(ParityBits);

this->NetWork_Port->setStopBits(StopBits);

this->NetWork_Port->setFlowControl(FlowControl);

this->NetWork_Port->setTimeout(TimeOut);

return 0 ;

}

return 1 ;

}

NetWork_Interface::NetWork_Interface(QObject *parent) :

QThread(parent)

{

int ret = Uart_Init(DEV_NAME,BAUD9600,DATA_8,PAR_NONE,STOP_1,FLOW_OFF,200);

if(0 != ret)

{

qDebug() << "Open Device Fail..." ;

this->NetWork_Thread_change(true);

return ;

}

//改变线程的状态为执行

this->NetWork_Thread_change(false);

}

NetWork_Interface::~NetWork_Interface()

{

this->NetWork_Port->close();

delete this->NetWork_Port;

}

//Change Thread Status

void NetWork_Interface::NetWork_Thread_change(bool Status)

{

Stop_flag = Status ;

}

//Runing Init Thread

void NetWork_Interface::run()

{

qDebug() << "Open Device Success....Start Uart_Recv Thread";

//Init Device

while(!Stop_flag)

{

QThread::msleep(200);

}

}

/AT指令收发

/*

cmd_buffer:要发送的AT指令,不需要带rn

success_ack:成功的预言字符串

error_ack:错误的语言字符串

timeout:超时,意思是如果发送超过timeout定义的,即返回超时失败。

return : 0 成功 1失败 -1超时

*/

int NetWork_Interface::Send_AT_Cmd(QString cmd_buffer,const char *success_ack,const char *error_ack,int timeout)

{

char *cmd = NULL;

char *send_cmd = NULL ;

QByteArray Byte_Data,temp;

temp.clear();

memset(recv_buffer,0,1024);

cmd_buffer.append("rn");

Byte_Data = cmd_buffer.toLatin1();

send_cmd = Byte_Data.data();

this->NetWork_Port->write(send_cmd);

while(timeout--)

{

temp.clear();

memset(recv_buffer,0,1024);

temp = this->NetWork_Port->readAll();

cmd = temp.data();

strcpy(recv_buffer,cmd);

if(strstr(recv_buffer,error_ack) != NULL)

{

qDebug() << "ackerror:" << recv_buffer ;

return 1 ;

}

if(strstr(recv_buffer,success_ack) != NULL)

{

qDebug() << "acksuccess:" << recv_buffer ;

return 0 ;

}

QThread::msleep(1);

}

qDebug() << "ackerror:AT cmd recv TimeOut";

return -1 ;

}

五、网络控制线程定义

网络控制线程头文件

#ifndef NETWORK_CONTROL_THREAD_H

#define NETWORK_CONTROL_THREAD_H

#include

#include "network_interface.h"

class NetWork_Control_Thread : public QThread

{

Q_OBJECT

public:

explicit NetWork_Control_Thread(QObject *parent = 0);

~NetWork_Control_Thread();

void NetWork_Thread_change(bool Status);

private:

volatile bool Stop_flag ;

NetWork_Interface *netWork_Ptr ;

protected:

void run();

signals:

public slots:

};

#endif // NETWORK_CONTROL_THREAD_H

网络控制线程接口实现

#include "network_control_thread.h"

NetWork_Control_Thread::NetWork_Control_Thread(QObject *parent) :

QThread(parent)

{

this->NetWork_Thread_change(false);

//在这里实例化网络接口线程

this->netWork_Ptr = new NetWork_Interface ;

//启动网络接口线程

this->netWork_Ptr->start();

}

NetWork_Control_Thread::~NetWork_Control_Thread()

{

this->NetWork_Thread_change(true);

delete this->netWork_Ptr ;

}

//改变线程的状态

void NetWork_Control_Thread::NetWork_Thread_change(bool Status)

{

this->Stop_flag = Status ;

}

//线程执行函数

void NetWork_Control_Thread::run()

{

//发送AT测试指令

this->netWork_Ptr->Send_AT_Cmd(AT_TEST_OK,"OK","ERROR",200);

while(!this->Stop_flag)

{

qDebug() << "NetWork_Control_Thread is Runing....";

QThread::msleep(1000);

}

}

六、AT指令框架测试

mainwindown.h

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include

#include "network_control_thread.h"

namespace Ui {

class MainWindow;

}

class MainWindow : public QMainWindow

{

Q_OBJECT

public:

explicit MainWindow(QWidget *parent = 0);

~MainWindow();

private:

Ui::MainWindow *ui;

NetWork_Control_Thread *network_control_ptr ;

};

#endif // MAINWINDOW_H

mainwindown.cpp

#include "mainwindow.h"

#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :

QMainWindow(parent),

ui(new Ui::MainWindow)

{

ui->setupUi(this);

//实例化网络控制线程

this->network_control_ptr = new NetWork_Control_Thread ;

//启动网络控制线程===>启动后将会自动启动网络接口线程

this->network_control_ptr->start();

}

MainWindow::~MainWindow()

{

delete this->network_control_ptr;

delete ui;

}

运行结果,这里我用的是NBIOT的BC28模块进行测试,本例程只提供测试框架,开发者需自行添加自己的业务逻辑处理。

050399d8fdbfbfad572007650d0da0fd.png

以下是我利用这个框架写的一个类似上位机的软件,可以读取模块的基本信息:

7b4bd95b6994f0d8075f0c1ac57c64d5.png

本文同步分享在 博客“Engineer-Bruce_Yang”(CSDN)。

如有侵权,请联系 support@oschina.cn 删除。

本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

最后

以上就是沉默舞蹈为你收集整理的Linux驱动实现AT指令,QT Linux实现AT指令处理框架的全部内容,希望文章能够帮你解决Linux驱动实现AT指令,QT Linux实现AT指令处理框架所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部