通过串口通信实现AT指令发送短信以及拨打电话

  • Post author:
  • Post category:其他



目录


简单说明


注意事项


1. 加载串口模块


2. 引入头文件


3. 设置变量


4. 初始化串口的参数以及发送短信和打电话


实例


其他说明


简单说明

对于其他的编程语言,实现的思路其实是大同小异的,不一样的地方可能在于定义串口变量以及属性的时候会有差异,因此读者可以举一反三。本文章使用的是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 的时候,才继续发送下一条指令。



版权声明:本文为weixin_47844533原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。