#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QSerialPort> //QSerialPort:提供访问串口的功能
#include <QSerialPortInfo> //QSerialPortInfo:提供系统中存在的串口的信息
#include "crc16.h"
#include <QTimer>
#include <qdatetime.h>
#include "config.h"
#include <QTcpServer> //TCP网口
#include <QTcpSocket>
#include <QNetworkInterface> //获取ip地址必须要包含的
unsigned char recv_data[128]; //接受数据
int count=0;
/*
串口有三种打开模式,即ReadOnly,WriteOnly,以及ReadWrite
串口数据的写入是通过writeData(const char * data, qint64 maxSize)以及write(const char * data, qint64 maxSize),前者是protected属性,只能在子类中访问,而后者则是public属性。在串口打开并且具有可写属性,即可通过write函数写入数据。
串口数据的读入是通过readData(char * data, qint64 maxSize) ,read(qint64 maxSize)实现的,如果需要一次性读完所有的数据,则可以通过readAll()全部读取串口缓冲区中的数据。
串口内部的缓冲区大小可以通过:setReadBufferSize(qint64 size)实现。当设定缓冲区大小时,串口只能接收size大小的数据流,因此存在数据丢书的可能。当设置为0的时候,并不是指的缓冲区大小为0,而是无穷大,这样就可以保存数据的全部接收完整。这是缓冲区大小的默认属性。
是否有新的数据读入缓冲区是通过readReady()信号来来确定的。这是通过时间驱动的方式来确定是否有数据可以读入。此外还有waitForReadyRead()来等待轮询是否有数据到达串口,但是这是一种阻塞性读入,个人觉得不是太好,所以写串口的时候采用的是事件驱动的方式来确定是够有数据可以读入。
*/
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//查找可用的串口
foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
{
QSerialPort serial; //接下来需要创建一个QSerialPort的对象,
serial.setPort(info);
if(serial.open(QIODevice::ReadWrite)) //如果端口打开 myCom ->open(QIODevice::ReadWrite); //打开模式 表示以可读可写的方式打开串口
{
ui->PortBox->addItem(serial.portName()); //端口号添加进去 //addItem(tr("Circle"))
serial.close();
}
}
QStringList baudList;
baudList << "4800" << "9600" << "14400" << "19200" << "38400"
<< "56000" << "57600" << "76800" << "115200" ;
ui->BaudBox->addItems(baudList); //添加波特率
//设置波特率下拉菜单默认显示第1项
ui->BaudBox->setCurrentIndex(1); //默认TCP服务器
//关闭发送按钮的使能
qDebug() << tr("界面设定成功!"); //相当于c里面的 printf
QTimer *timer = new QTimer(this); //定时器
connect(timer,SIGNAL(timeout()),this,SLOT(timerUpdate()));//超时
timer->start(1000); //1000ms
/* tcp服务器建立 */
ui->ServerPort->setText("8080"); //端口号
// ui->ConnectButton->setEnabled(false); //连接按钮
server = new QTcpServer();
QStringList ProtypeList;
ProtypeList << "TCP服务器" << "TCP客户端" << "UDP协议" ;
ui->ProtypeBox->addItems(ProtypeList); //添加协议类型
//设置协议类型下拉菜单默认显示第0项
ui->ProtypeBox->setCurrentIndex(0); //
QString ip=getHostIp();
ui->ServerIP->setText(ip); //ip自动显示192.168.1.123
//连接信号槽
connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);
}
MainWindow::~MainWindow() //----原始就有
{
delete ui;
}
/*
*/
void MainWindow::timerUpdate(void) //显示时间
{
QDateTime time = QDateTime::currentDateTime();
QString str = time.toString("yyyy-MM-dd hh:mm:ss dddd");//
//ui->label_Time->setText(str);
ui->label_time->setText(str);
}
QString MainWindow::getHostIp() //获取本机IP地址
{
QList<QHostAddress> list = QNetworkInterface::allAddresses();
foreach (QHostAddress address, list)
{
if(address.protocol() == QAbstractSocket::IPv4Protocol)
//我们使用IPv4地址
return address.toString();
}
return 0;
}
void MainWindow::on_ConnectButton_clicked() //tcp连接按钮
{
if(ui->ConnectButton->text() == tr("连接")) //点击连接
{
//关闭设置菜单使能
ui->ServerPort->setEnabled(false);
ui->ServerIP->setEnabled(false); //ProtypeBox
ui->ProtypeBox->setEnabled(false);
int port = ui->ServerPort->text().toInt(); //从输入框获取端口号
ui->label_netState->setStyleSheet("background-color: rgb(0, 255, 0)");//设置成绿色
//监听指定的端口
if(!server->listen(QHostAddress::Any, port))
{
//若出错,则输出错误信息
qDebug()<<server->errorString();
return;
}
//修改按键文字
ui->ConnectButton->setText("断开");
qDebug()<< "Listen succeessfully!";
netisopen=true;
}
else
{
//取消侦听
server->close();
netisopen=false;
//打开设置菜单使能
ui->ServerPort->setEnabled(true);
ui->ServerIP->setEnabled(true);
ui->ProtypeBox->setEnabled(true);
//修改按键文字
ui->ConnectButton->setText("连接");
ui->label_netState->setStyleSheet("background-color: rgb(255, 0, 0)");//红色
//发送按键失能
// ui->pushButton_Send->setEnabled(false);
}
}
void MainWindow::server_New_Connect() //客户端连接
{
//获取客户端连接
socket = server->nextPendingConnection();
//连接QTcpSocket的信号槽,以读取新数据
QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);
//发送按键使能
ui->SendButton->setEnabled(true);
qDebug() << "A Client connect!";
}
void MainWindow::socket_Read_Data() //网口接受数据 只能一个客户端
{
count++;
qDebug() << "进入次数count=" << count;
Delay_ms(20); //延时必须要加
memset(recv_data,0,128);
int len=socket->read((char*)recv_data,128); //char转 QByteArray
/*这里可以开始解析数据*/
QString buf; //char转 QString 16进制数据转字符串 将16进制值传入buff中
for ( unsigned char i = 0; i < len; i++)
{
unsigned char outChar = recv_data[i];
QString str1 = QString("%1").arg(outChar&0xFF, 2, 16, QLatin1Char('0'));
buf += str1;
}
if(!buf.isEmpty())
{
QString str = ui->textEdit_R->toPlainText(); //获取文本内容 此时无显示
buf = buf.toUpper ();//把小字符串转化为大写字符串
for(int j = 0;j<buf.length ();j+=2) //这段是接受数据显示时,两个数据之间有空格 01 02 03 04
{
QString st = buf.mid (j,2); //从i这个位置开始,返回2个字符串
str += st;
str += " ";
}
ui->textEdit_R->clear(); //
ui->textEdit_R->append(str); //追加显示
}
}
void MainWindow::socket_Disconnected()
{
//发送按键失能
ui->SendButton->setEnabled(false);
qDebug() << "Disconnected!";
}
void MainWindow::on_OpenSerialButton_clicked(