目录
简单说明
对于其他的编程语言,实现的思路其实是大同小异的,不一样的地方可能在于定义串口变量以及属性的时候会有差异,因此读者可以举一反三。本文章使用的是QT+VS进行实现。
具备的硬件设备为短信猫等传输设备,以及对应的端口驱动。驱动在对应的公司官网均可下载。
注意事项
AT指令的构成:AT指令加上回车。而对于程序来说,回车代表 \r\n 。因此发送AT指令之后,还需要再发送一个\r\n ,否则硬件设备无法识别这是一个AT指令。对于发送短信来说,发送完短信内容之后,还需要发送一个结束符号:以十六进制的方式发送 1A 。则在C语言中 十六进制的转义符为 \x,因此发送完信息之后需要通过AT指令发送一个结束指令:“\x1A\0\r\n”。这时候才代表发送信息这个业务结束。
1. 加载串口模块
右键点击该VS项目,选择QT
点击QT Project Settings,
在General的属性列中找到QT Modules,
点击下拉框找到Select Moudles并点击,然后勾选即可。
2. 引入头文件
#include <qserialport.h>
#include <qserialportinfo.h>
3. 设置变量
QSerialPort* serial;//创建一个串口通信的对象
serial = new QSerialPort();//实例化对象
connect(serial, &QSerialPort::readyRead,this, &RS232::readData);//当该串口对象有信息可以接受的时候,调用 readData 方法
4. 初始化串口的参数以及发送短信和打电话
//初始化参数以及发送短信和打电话
void RS232::init(QString phone, QString messageWarn)
{
//获取可以用的串口
QList <QSerialPortInfo> serialPortInfos = QSerialPortInfo::availablePorts();
//输出当前系统可以使用的串口个数
qDebug() << serialPortInfos.count();
qDebug() << serialPortInfos.first().portName();//输出 COM3
//设置串口名字
serial->setPortName("COM3");// “COM3” 是短信猫硬件对应的串口号,读者可以通过window系统的设备管理器 查看自己硬件的串口号
//设置波特率
serial->setBaudRate(115200);//波特率参考自己通信硬件对应波特率参数
//下面的参数一般都是通用的,读者可以按照自己语言的接口进行设置参数
//设置数据位
serial->setDataBits(QSerialPort::Data8);//设置数据位为8
//设置奇偶校验位
serial->setParity(QSerialPort::NoParity);//设置为无
//设置停止位
serial->setStopBits(QSerialPort::OneStop);//设置为1
//设置流控
serial->setFlowControl(QSerialPort::NoFlowControl);//设置为无
//打开串口
serial->open(QIODevice::ReadWrite);
//开始发送信息
serial->write("AT\r\n");//该AT指令的作用是确保串口是否连接成功
//开始发送短信
Sendstr[0] = "AT+CMGF=1\r\n";//设置为短信模式
Sendstr[1] = "AT+CSCS=\"GSM\"\r\n";
Sendstr[2] = "AT+CMGS=\"" + phone + "\"\r\n";//phone为电话号码
Sendstr[3] = messageWarn + "\r\n";//messageWarn为短信内容
Sendstr[4] = "\x1A\0\r\n";//结束符号
for(int i = 0;i<5;i++)
{
serial->write(Sendstr[i]);
}
//打电话
QString phone = "ATD13528926183;\r\n"; //ATD加上电话号码即可。注意电话号码后面需要加上分号
serial->write(phone);
}
5. 接受硬件设备的回应
void RS232::readData()
{
//每次发送一条AT指令,如果成功,则会返回 \r\nOK\r\n;如果失败,则会返回 \r\nERROR\r\n。
//对于短信来说,当连接工作的指令或者设置参数的指令例如设置为短信模式,设置电话号码等均返回OK之后,则会返回输入内容标识符 > 表示已经成功,可以输入内容。
QByteArray buf;
buf = serial->readAll();
}
实例
.h 头文件
#pragma once
#include <QtWidgets/QWidget>
#include "ui_RS232.h"
#include <qserialport.h>
#include <qserialportinfo.h>
#include <qdebug.h>
#include <Windows.h>
#include <qpushbutton.h>
class RS232 : public QWidget
{
Q_OBJECT
public:
RS232(QWidget *parent = Q_NULLPTR);
int sendIndex;//用来判断发送的次数 主要针对发送短信,因为发送短信需要发送多条铺垫AT指令才可以进行主要的发送内容操作
QByteArray hollgetinfo;//用来收集硬件设备返回的完整信息 即 \r\nOK\r\n。否则在接受的时候信息可能会发生混乱。
QSerialPort* serial;//串口通信对象
QString Sendstr[5];//用来存放AT指令
QByteArray buf;//接受返回值
void readData();
void init(QString phone, QString messageWarn);
private:
Ui::RS232Class ui;
};
.cpp文件
#include "RS232.h"
#define CTRL_Z 0x1a
RS232::RS232(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
serial = new QSerialPort();
connect(serial, &QSerialPort::readyRead,this, &RS232::readData);
init("13528926183","have oil");
}
//初始化参数
void RS232::init(QString phone, QString messageWarn)
{
QString description;
QString manufacturer;
QString serialNumber;
//获取可以用的串口
QList <QSerialPortInfo> serialPortInfos = QSerialPortInfo::availablePorts();
//输出当前系统可以使用的串口个数
qDebug() << serialPortInfos.count();
qDebug() << serialPortInfos.first().portName();//输出 COM3
//设置串口名字
serial->setPortName("COM3");
//设置波特率
serial->setBaudRate(115200);
//设置数据位
serial->setDataBits(QSerialPort::Data8);
//设置奇偶校验位
serial->setParity(QSerialPort::NoParity);
//设置停止位
serial->setStopBits(QSerialPort::OneStop);
//设置流控
serial->setFlowControl(QSerialPort::NoFlowControl);
//打开串口
serial->open(QIODevice::ReadWrite);
sendIndex = 0;//用来判断已经发送了多少条AT指令(针对发送信息来说)
hollgetinfo.clear();//每次发送信息的时候都需要清空该变量。
//开始发送信息
serial->write("AT\r\n"); //先通过发送AT指令,让硬件设备返回一个信息 例如 \r\nOK\r\n 因此通过connect调用readData方法
//发送短信的AT指令存储
Sendstr[0] = "AT+CMGF=1\r\n";
Sendstr[1] = "AT+CSCS=\"GSM\"\r\n";
Sendstr[2] = "AT+CMGS=\"" + phone + "\"\r\n";
Sendstr[3] = messageWarn + "\r\n";
Sendstr[4] = "\x1A\0\r\n";
}
void RS232::readData()
{
buf = serial->readAll();
if (!buf.isEmpty())
{
hollgetinfo.append(buf);//组装硬件设备的信息,确保每一条返回的信息都是 \r\nOK\r\n 等类型
qDebug() <<"sendIndex:" <<sendIndex<< "receive news:" << hollgetinfo;
if (sendIndex<5&&(strstr(hollgetinfo.toStdString().c_str(),"\r\nOK\r\n")!=NULL)|| (strstr(hollgetinfo.toStdString().c_str(), "\r\n>") != NULL)) {
//当发送短信相关的AT指令少于5条(因为发送短信至少需要5条指令),则进入该if
//当硬件设备返回\r\nOK\r\n信息,则进入该if
//当硬件设备返回 \r\n> 则进入该if
QByteArray ba= Sendstr[sendIndex].toLatin1();
serial->write(ba.data());//发送AT指令
sendIndex++;
hollgetinfo.clear();//将返回信息清空,准备接受下一条返回信息
}
}
else
{
qDebug() << "no informations";
}
}
其他说明
AT指令并不只有本文中提到的,本文只是使用了AT指令比较常用的指令。
对于发信息的AT指令,本文使用到的AT指令仅仅可以发送英文短信,而如何发送中文短信,读者可以查阅AT指令大全,该指令与本文发送非中文指令只是大同小异。
使用串口通信的时候,确保信息发送的间隔性。例如你使用AT指令发送123之后,立马接着发送456。则对于硬件设备,可能他接受到的信息是 1234 ,56。因此读者需要注意信息发送的间隔性,本文通过 if 语句进行判断,当完全收到硬件设备的回应消息 也就是 \r\nOK\r\n 的时候,才继续发送下一条指令。