这是我第一次使用CSDN来写博客,写这篇博客也是对自己入门以来的一个总结和该项目的记录。如图所示:
大家可以看到,基本的功能跟串口助手是类似的,在此基础上我加入了表格导入数据的方式,把表格数据转换为16进制数据的过程,软件数据发送显示及下位机接收显示,来确保我们的程序是否正常工作。
本文讲述的 QSerialPort 是在qt5 + 版本以上才有
与下位机,单片机通信少不了使用串口进行通信,Qt 也提供了串口通信的类
使用的时候在 pro 添加这句导入模块 QT += serialport
QT += serialport
QT下读取excel文件使用的预处理的文件
QT +=axcontainer
那么Pro文件内就不多做介绍了,直接进入核心部落。
首先是对UI界面的设计,我把我的贴出来供大家参考。
excelengine.h
#ifndef EXCELENGINE_H
#define EXCELENGINE_H
#include
#include
#include
#include
#include
#include "qt_windows.h"
#include
class ExcelEngine
{
public:
ExcelEngine();
ExcelEngine(QString xlsFile);
~ExcelEngine();
bool Open(UINT nSheet, bool visible);
bool Open(QString xlsFile, UINT nSheet, bool visible);
void Save();
void Close();
void Clear();
bool SaveDataFrTable(QTableWidget *tableWidget);
bool ReadDataToTable(QTableWidget *tableWidget);
QVariant GetCellData(UINT row, UINT column);
bool SetCellData(UINT row, UINT column, QVariant data);
bool IsOpen();
bool IsValid();
UINT GetRowCount()const;
UINT GetColumnCount()const;
private:
QAxObject* pExcel;
QAxObject* pWorkbooks;
QAxObject* pWorkbook;
QAxObject* pWorksheet;
QString sXlsFile;
int nRowCount;
int nColumnCount;
int nStartRow;
int nStartColumn;
int nCurrSheet;
bool bIsOpen;
bool bIsValid;
bool bIsANewFile;
bool bIsSaveAlready;
bool bIsVisible;
};
#endif // EXCELENGINE_H
excelengine.cpp
#include "excelengine.h"
ExcelEngine::ExcelEngine()
{
pExcel = NULL;
pWorkbooks = NULL;
pWorkbook = NULL;
pWorksheet = NULL;
sXlsFile = "";
nRowCount = 0;
nColumnCount = 0;
nStartRow = 0;
nStartColumn = 0;
bIsOpen = false;
bIsValid = false;
bIsANewFile = false;
bIsSaveAlready = false;
HRESULT r = OleInitialize(0);
if (r != S_OK && r != S_FALSE)
{
qDebug("Qt: Could not initialize OLE (error %x)", (unsigned int)r);
}
}
ExcelEngine::ExcelEngine(QString xlsFile)
{
pExcel = NULL;
pWorkbooks = NULL;
pWorkbook = NULL;
pWorksheet = NULL;
sXlsFile = xlsFile;
nRowCount = 0;
nColumnCount = 0;
nStartRow = 0;
nStartColumn = 0;
bIsOpen = false;
bIsValid = false;
bIsANewFile = false;
bIsSaveAlready = false;
HRESULT r = OleInitialize(0);
if (r != S_OK && r != S_FALSE)
{
qDebug("Qt: Could not initialize OLE (error %x)", (unsigned int)r);
}
}
ExcelEngine::~ExcelEngine()
{
if ( bIsOpen )
{
//析构前,先保存数据,然后关闭workbook
Close();
}
OleUninitialize();
}
/**
*@brief 打开sXlsFile指定的excel报表
*@return true : 打开成功
* false: 打开失败
*/
bool ExcelEngine::Open(UINT nSheet, bool visible)
{
if ( bIsOpen )
{
//return bIsOpen;
Close();
}
nCurrSheet = nSheet;
bIsVisible = visible;
if ( NULL == pExcel )
{
pExcel = new QAxObject("Excel.Application");
if ( pExcel )
{
bIsValid = true;
}
else
{
bIsValid = false;
bIsOpen = false;
return bIsOpen;
}
pExcel->dynamicCall("SetVisible(bool)", bIsVisible);
}
if ( !bIsValid )
{
bIsOpen = false;
return bIsOpen;
}
if ( sXlsFile.isEmpty() )
{
bIsOpen = false;
return bIsOpen;
}
/*如果指向的文件不存在,则需要新建一个*/
QFile f(sXlsFile);
if (!f.exists())
{
bIsANewFile = true;
}
else
{
bIsANewFile = false;
}
if (!bIsANewFile)
{
pWorkbooks = pExcel->querySubObject("WorkBooks"); //获取工作簿
pWorkbook = pWorkbooks->querySubObject("Open(QString, QVariant)",sXlsFile,QVariant(0)); //打开xls对应的工作簿
}
else
{
pWorkbooks = pExcel->querySubObject("WorkBooks"); //获取工作簿
pWorkbooks->dynamicCall("Add"); //添加一个新的工作薄
pWorkbook = pExcel->querySubObject("ActiveWorkBook"); //新建一个xls
}
pWorksheet = pWorkbook->querySubObject("WorkSheets(int)", nCurrSheet);//打开sheet
//至此已打开,开始获取相应属性
QAxObject *usedrange = pWorksheet->querySubObject("UsedRange");//获取该sheet的使用范围对象
QAxObject *rows = usedrange->querySubObject("Rows");
QAxObject *columns = usedrange->querySubObject("Columns");
//因为excel可以从任意行列填数据而不一定是从0,0开始,因此要获取首行列下标
nStartRow = usedrange->property("Row").toInt(); //第一行的起始位置
nStartColumn = usedrange->property("Column").toInt(); //第一列的起始位置
nRowCount = rows->property("Count").toInt(); //获取行数
nColumnCount = columns->property("Count").toInt(); //获取列数
// qDebug()<
// qDebug()<
// qDebug()<
// qDebug()<
bIsOpen = true;
return bIsOpen;
}
/**
*@brief Open()的重载函数
*/
bool ExcelEngine::Open(QString xlsFile, UINT nSheet, bool visible)
{
sXlsFile = xlsFile;
nCurrSheet = nSheet;
bIsVisible = visible;
return Open(nCurrSheet,bIsVisible);
}
/**
*@brief 保存表格数据,把数据写入文件
*/
void ExcelEngine::Save()
{
if ( pWorkbook )
{
if (bIsSaveAlready)
{
return ;
}
if (!bIsANewFile)
{
pWorkbook->dynamicCall("Save()");
}
else /*如果该文档是新建出来的,则使用另存为COM接口*/
{
pWorkbook->dynamicCall("SaveAs (const QString&,int,const QString&,const QString&,bool,bool)",
sXlsFile,56,QString(""),QString(""),false,false);
}
bIsSaveAlready = true;
}
}
/**
*@brief 关闭前先保存数据,然后关闭当前Excel COM对象,并释放内存
*/
void ExcelEngine::Close()
{
//关闭前先保存数据
Save();
if ( pExcel && pWorkbook )
{
pWorkbook->dynamicCall("Close(bool)", true);
pExcel->dynamicCall("Quit()");
delete pExcel;
pExcel = NULL;
bIsOpen = false;
bIsValid = false;
bIsANewFile = false;
bIsSaveAlready = true;
}
}
/**
*@brief 把tableWidget中的数据保存到excel中
*@param tableWidget : 指向GUI中的tablewidget指针
*@return 保存成功与否 true : 成功
* false: 失败
*/
bool ExcelEngine::SaveDataFrTable(QTableWidget *tableWidget)
{
if ( NULL == tableWidget )
{
return false;
}
if ( !bIsOpen )
{
return false;
}
int tableR = tableWidget->rowCount();
int tableC = tableWidget->columnCount();
//获取表头写做第一行
for (int i=0; i<tableC; i++)
{
if ( tableWidget->horizontalHeaderItem(i) != NULL )
{
this->SetCellData(1,i+1,tableWidget->horizontalHeaderItem(i)->text());
}
}
//写数据
for (int i=0; i<tableR; i++)
{
for (int j=0; j<tableC; j++)
{
if ( tableWidget->item(i,j) != NULL )
{
this->SetCellData(i+2,j+1,tableWidget->item(i,j)->text());
}
}
}
//保存
Save();
return true;
}
/**
*@brief 从指定的xls文件中把数据导入到tableWidget中
*@param tableWidget : 执行要导入到的tablewidget指针
*@return 导入成功与否 true : 成功
* false: 失败
*/
bool ExcelEngine::ReadDataToTable(QTableWidget *tableWidget)
{
if ( NULL == tableWidget )
{
return false;
}
//先把table的内容清空
int tableColumn = tableWidget->columnCount();
tableWidget->clear();
for (int n=0; n<tableColumn; n++)
{
tableWidget->removeColumn(0);
}
int rowcnt = nStartRow + nRowCount;
int columncnt = nStartColumn + nColumnCount;
//获取excel中的第一行数据作为表头
QStringList headerList;
for (int n = nStartColumn; n<columncnt; n++ )
{
QAxObject * cell = pWorksheet->querySubObject("Cells(int,int)",nStartRow, n);
if ( cell )
{
headerList<<cell->dynamicCall("Value2()").toString();
}
}
//重新创建表头
tableWidget->setColumnCount(nColumnCount);
tableWidget->setHorizontalHeaderLabels(headerList);
//插入新数据
for (int i = nStartRow+1, r = 0; i < rowcnt; i++, r++ ) //行
{
tableWidget->insertRow(r); //插入新行
for (int j = nStartColumn, c = 0; j < columncnt; j++, c++ ) //列
{
QAxObject * cell = pWorksheet->querySubObject("Cells(int,int)", i, j );//获取单元格
//在r新行中添加子项数据
if ( cell )
{
tableWidget->setItem(r,c,new QTableWidgetItem(cell->dynamicCall("Value2()").toString()));
}
}
}
return true;
}
/**
*@brief 获取指定单元格的数据
*@param row : 单元格的行号
*@param column : 单元格的列号
*@return [row,column]单元格对应的数据
*/
QVariant ExcelEngine::GetCellData(UINT row, UINT column)
{
QVariant data;
QAxObject *cell = pWorksheet->querySubObject("Cells(int,int)",row,column);//获取单元格对象
if ( cell )
{
data = cell->dynamicCall("Value2()");
}
return data;
}
/**
*@brief 修改指定单元格的数据
*@param row : 单元格的行号
*@param column : 单元格指定的列号
*@param data : 单元格要修改为的新数据
*@return 修改是否成功 true : 成功
* false: 失败
*/
bool ExcelEngine::SetCellData(UINT row, UINT column, QVariant data)
{
bool op = false;
QAxObject *cell = pWorksheet->querySubObject("Cells(int,int)",row,column);//获取单元格对象
if ( cell )
{
QString strData = data.toString(); //excel 居然只能插入字符串和整型,浮点型无法插入
cell->dynamicCall("SetValue(const QVariant&)",strData); //修改单元格的数据
op = true;
}
else
{
op = false;
}
return op;
}
/**
*@brief 清空除报表之外的数据
*/
void ExcelEngine::Clear()
{
sXlsFile = "";
nRowCount = 0;
nColumnCount = 0;
nStartRow = 0;
nStartColumn = 0;
}
/**
*@brief 判断excel是否已被打开
*@return true : 已打开
* false: 未打开
*/
bool ExcelEngine::IsOpen()
{
return bIsOpen;
}
/**
*@brief 判断excel COM对象是否调用成功,excel是否可用
*@return true : 可用
* false: 不可用
*/
bool ExcelEngine::IsValid()
{
return bIsValid;
}
/**
*@brief 获取excel的行数
*/
UINT ExcelEngine::GetRowCount()const
{
return nRowCount;
}
/**
*@brief 获取excel的列数
*/
UINT ExcelEngine::GetColumnCount()const
{
return nColumnCount;
}
以上是对excel表格的导入程序描述,控件实现如下源码中查找。
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#include
#include
// CRC16码表
#define UCHAR unsigned char
static const UCHAR aucCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40};
static const UCHAR aucCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
0x41, 0x81, 0x80, 0x40};
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
ExcelEngine eetest;
void McMBCRC16(unsigned char *pDataIn, int iLenIn, unsigned int *pCRCOut);
public slots:
// void readallexcel();//读取串口
void sleep(unsigned int msec);
private slots:
void on_cin_Button_clicked();
void on_save_Button_clicked();
void Serial_read();//读取串口
void on_send_Button_clicked();
void on_open_Button_clicked();
void on_search_Button_clicked();
void on_clear_r_Button_clicked();
void on_up_Button_clicked();
void on_receiveEdit_textChanged();
public:
QSerialPort Serial;
};
#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.setWindowTitle("多功能串口开发软件 作者:Cola.Liu");
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
//#define cunction - like macro
#include
#include
#include
#include
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setWindowTitle("TEST窗口 作者:cola.liu"); //设置子窗口标题
Serial.setPortName("/dev/ttyUSB4");
connect(&Serial, &QSerialPort::readyRead , this , &MainWindow::Serial_read);
ui->bandRateBox->setCurrentIndex(0); //波特率默认9600
Serial.setPortName("/dev/ttyUSB4"); //设置端口号
Serial.setBaudRate(9600); //设置波特率
Serial.setDataBits(QSerialPort::Data8); //设置数据位
Serial.setStopBits(QSerialPort::OneStop); //设置停止位
Serial.setParity(QSerialPort::NoParity); //设置奇偶校验
Serial.setFlowControl(QSerialPort::NoFlowControl);//设置流控制模式
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_cin_Button_clicked()
{
QString FilePath = QFileDialog :: getOpenFileName(this, NULL, NULL, "All File(*.*)");
if(FilePath!=""){
eetest.Open(FilePath,1,false);
eetest.ReadDataToTable(ui->tableWidget);
}
}
void MainWindow::on_save_Button_clicked()
{
// eetest.Open("a.xlsx"11,1,false);
eetest.SaveDataFrTable(ui->tableWidget);
}
void MainWindow::Serial_read()
{
//读取串口收到的数据
QByteArray buffer = Serial.readAll();
//判断是否需要16进制显示
if(ui->show16Box->isChecked()==true)
{
int count = buffer.size();
QString receive;
for ( int i= 0; i< count; i++)
{
receive += QString(" %1").arg( (quint8)buffer.data()[i], 2, 16, QLatin1Char( '0' ) );
}
//buffer = buffer.toHex() ;//转换为16进制 例:"1234" -->“31323334”
//ui->receiveEdit->insertPlainText(receive+"\n");
//设置时间
QDateTime time = QDateTime::currentDateTime();//获取系统现在的时间
QString str = time.toString("yyyy-MM-dd hh:mm:ss ddd"); //设置显示格式
receive = ui->receiveEdit->toPlainText() +"\n"+receive;
ui->receiveEdit->setText( receive );
}
//QString receive = QString(buffer);
//在接受窗口显示收到的数据
// ui->receiveEdit->insertPlainText(receive);
//ui->receiveEdit->setText( ui->receiveEdit->toPlainText() + "\nghjxsdhjsd:\n" + ui->SendEdit->toPlainText() );
}
void MainWindow::on_open_Button_clicked()
{
if(ui->open_Button->text() == QString("打开串口")) //串口未打开
{
//设置端口号
Serial.setPortName(ui->comBox->currentText());
//设置波特率
Serial.setBaudRate(ui->bandRateBox->currentText().toInt());
//设置数据位
switch (ui->dataBitBox->currentText().toInt())
{
case 8: Serial.setDataBits(QSerialPort::Data8); break;
case 7: Serial.setDataBits(QSerialPort::Data7); break;
case 6: Serial.setDataBits(QSerialPort::Data6); break;
case 5: Serial.setDataBits(QSerialPort::Data5); break;
default: break;
}
//设置停止位
switch (ui->stopBitBox->currentText().toInt())
{
case 1: Serial.setStopBits(QSerialPort::OneStop);break;
case 2: Serial.setStopBits(QSerialPort::TwoStop);break;
default:break;
}
//设置校验方式
switch (ui->checkoutBox->currentIndex())
{
case 0: Serial.setParity(QSerialPort::NoParity);break;
default:break;
}
//设置流控制模式
Serial.setFlowControl(QSerialPort::NoFlowControl);
//打开串口
if(Serial.open(QIODevice::ReadWrite)==false)
{
QMessageBox::warning(NULL , "提示", "串口打开失败!");
return;
}
// 失能串口设置控件
ui->comBox->setEnabled(false);
ui->checkoutBox->setEnabled(false);
ui->bandRateBox->setEnabled(false);
ui->dataBitBox->setEnabled(false);
ui->stopBitBox->setEnabled(false);
ui->search_Button->setEnabled(false);
//调整串口控制按钮的文字提示
ui->open_Button->setText(QString("关闭串口"));
}
else //串口已经打开
{
Serial.close();
// 使能串口设置控件
ui->comBox->setEnabled(true);
ui->checkoutBox->setEnabled(true);
ui->bandRateBox->setEnabled(true);
ui->dataBitBox->setEnabled(true);
ui->stopBitBox->setEnabled(true);
ui->search_Button->setEnabled(true);
//调整串口控制按钮的文字提示
ui->open_Button->setText(QString("打开串口"));
}
}
void MainWindow::on_search_Button_clicked()
{
// 清除当前显示的端口号
ui->comBox->clear();
//检索端口号
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
ui->comBox->addItem(info.portName());
}
}
void MainWindow::on_clear_r_Button_clicked()
{
ui->receiveEdit->clear();
}
void MainWindow::on_send_Button_clicked()
{
if(Serial.isOpen()==false) //判断串口是否正常打开
{
QMessageBox::warning(NULL , "提示", "请打开串口!");
return;
}
//toPlainText() 转换为纯文本格式
//toUtf8() 转换为UTF-8 编码
QByteArray senddata = ui->SendEdit->toPlainText().toUtf8();
//判断是否有非16进制字符
if(ui->send16Box->isChecked()==true) //勾选了16进制发送
{
int cnt = senddata.size(); //要发送数据的长度
char *data = senddata.data();
for(int i=0;i<cnt;i++)//判断是否有非16进制字符
{
if(data[i]>='0' && (data[i]<='9'))
continue;
else if(data[i]>='a' && (data[i]<='f'))
continue;
else if(data[i]>='A' && (data[i]<='F'))
continue;
else if(data[i] == ' ') //输入为空格
continue;
else
{
QMessageBox::warning(NULL , "提示", "输入非16进制字符!");
return;
}
}
//字符串转化为16进制数 "1234" --> 0X1234
//转换时会自动除去非16进制字符
senddata = senddata.fromHex(senddata);
}
//勾选了发送新行
if(ui->newlineBox->isChecked()==true)
{
int cnt = senddata.size();
senddata = senddata.insert(cnt,"\r\n"); //插入回车换行符
}
//设置时间
QDateTime time = QDateTime::currentDateTime();//获取系统现在的时间
QString str = time.toString("yyyy-MM-dd hh:mm:ss ddd"); //设置显示格式
ui->receiveEdit->setText( ui->receiveEdit->toPlainText() +"\n"+ str +":\n" + ui->SendEdit->toPlainText() );
Serial.write(senddata); //通过串口发送数据
// ui->receiveEdit->setText( ui->SendEdit-> );
}
void MainWindow::on_up_Button_clicked()
{
quint16 index = ui->tableWidget->currentRow();
quint16 count = ui->tableWidget->columnCount();
for (int i=1;i<count;i++)
{
quint16 abc = ui->tableWidget->item(index,i)->text().toInt();
unsigned char ab[8];
unsigned int CrcTemp;
ab[0]= 0x01;//从机地址
ab[1]= 0x06;
ab[2]= 0x90;
ab[3]=i-1; //指令地址:单元格从0-6,地址分别为0-6
ab[4]= abc >> 8;//单元格的数据
ab[5]=abc; //发送
McMBCRC16(ab,6,&CrcTemp);
ab[6]=CrcTemp&0xFF;
ab[7]=CrcTemp>>8;
Serial.write((const char*)ab,8);
QDateTime time = QDateTime::currentDateTime();//获取系统现在的时间
QString str = time.toString("yyyy-MM-dd hh:mm:ss ddd"); //设置显示格式
QString receive;
for ( int i= 0; i< 8; i++)
{
receive += QString(" %1").arg( (quint8)ab[i], 2, 16, QLatin1Char( '0' ) );
}
ui->receiveEdit->setText( ui->receiveEdit->toPlainText() +"\n"+ str +":\n" +receive );
sleep(1000);
}
}
void MainWindow::on_receiveEdit_textChanged()
{
ui->receiveEdit->moveCursor(QTextCursor::End);
}
void MainWindow::McMBCRC16(unsigned char *pDataIn, int iLenIn, unsigned int *pCRCOut){
UCHAR ucCRCHi = 0xFF;
UCHAR ucCRCLo = 0xFF;
int iIndex;
while(iLenIn-- )
{
iIndex = ucCRCLo ^ *( pDataIn++ );
ucCRCLo = ( UCHAR )( ucCRCHi ^ aucCRCHi[iIndex] );
ucCRCHi = aucCRCLo[iIndex];
}
*pCRCOut = ( ucCRCHi << 8 | ucCRCLo );
}
//延时
void MainWindow::sleep(unsigned int msec)
{
//currentTime返回当前时间,用当前时间加上我们要延时的时间msec得到一个新时刻
QTime reachTime = QTime::currentTime().addMSecs(msec);
while (QTime::currentTime()<reachTime)
QCoreApplication::processEvents(QEventLoop::AllEvents,100);
}
与下位机连接后的功能展示:
如果此文章对你有帮助请点个关注点个赞,这就是我最大的鼓励 谢谢。
让我们一起成长,大家可以把自己的见解在下方留言评论哦!