摘要:上位机软件程序通过QT实现,采集输入信息,根据实际需要做出合适的串口通讯协议,实现效果如下图所示:
主要实现的功能:
1.串口基本参数可选,可调
2.显示区域可选择十六进制/asicii码显示,可根据自己的需求调整多少字节对齐,显示的比较工整,有利于解析协议
3.可自己制定协议头,其他子项内容都是以十进制输入,内置checksum自动计算
4.实时显示发送/接收字节数
5.可自己定制时间周期定时发送
6.实时显示时间
代码实现:
实现过程较为简单,主要是协议处理:
串口设备:新建串口对象 -> 寻找可用串口设置 -> 设置串口基本参数 -> 打开串口 ->监听串口
串口协议:LineEdit的内容是大端格式,所以使用的时候要将变量转换成大端,默认是小端
注意:
1 QString("%1").arg(ui>lineEdit_S_num>text().toInt(),8,16,QChar('0'))
2
3 第一个参数 : 将Qstring转换为int型4 第二个参数 : 需要将几个字符串转换成十六进制的,
5 如char型 :需要两个字符
6 short型 : 需要四个字符
7 int/long : 需要八个字符
8 第三个参数: 转换为多少进制
9 第四个参数: 不足位数的用0补齐
1 //QByteArray里面的数据按照对应的通讯协议进行调整
2 void Widget::int_adjust(QByteArray &str,qint8 startcount)
3 {
4 qint8 temp1;
5 qint8 temp2;
6 temp1 = str[startcount];
7 temp2 = str[startcount+1];
8 str[startcount] = str[startcount+3];
9 str[startcount+1] = str[startcount+2];
10 str[startcount+2] =temp2;
11 str[startcount+3] =temp1;
12 }
13 void Widget::short_adjust(QByteArray &str,qint8 startcount)
14 {
15 qint8 temp1;
16 temp1 = str[startcount];
17 str[startcount] = str[startcount+1];
18 str[startcount+1] = temp1;
19 }
1 //字符串转成十六进制实现
2 void Widget::StringToHex(QString str, QByteArray &senddata)
3 {
4
5 int hexdata,lowhexdata;
6
7 int hexdatalen = 0;
8
9 int len = str.length();
10
11 senddata.resize(len/2);
12
13 char lstr,hstr;
14
15 for(int i=0; i<len; )
16 {
17 //char lstr,
18 hstr=str[i].toLatin1();
19 if(hstr == ' ')
20 {
21 i++;
22 continue;
23 }
24 i++;
25 if(i >= len)
26 break;
27 lstr = str[i].toLatin1();
28 hexdata = ConvertHexChar(hstr);
29 lowhexdata = ConvertHexChar(lstr);
30 if((hexdata == 16) || (lowhexdata == 16))
31 break;
32 else
33 hexdata = hexdata*16+lowhexdata;
34 i++;
35 senddata[hexdatalen] = (char)hexdata;
36 hexdatalen++;
37 }
38 senddata.resize(hexdatalen);
39 }
40
41
42 char Widget::ConvertHexChar(char ch)
43 {
44 if((ch >= '0') && (ch <= '9'))
45 return ch-0x30;
46 else if((ch >= 'A') && (ch <= 'F'))
47 return ch-'A'+10;
48 else if((ch >= 'a') && (ch <= 'f'))
49 return ch-'a'+10;
50 else return (-1);
51
52
53 }
要点,易错点基本已经指出,其他的比较简单,这里不再赘叙
1 #include "widget.h"
2 #include "ui_widget.h"
3 #include <QTimer>
4 #include <QDateTime>
5 #include <QMessageBox>
6 static int CountBase = 0;
7 static int SENDNUMSIZE = 20;
8 static int recvCount = 0;
9 Widget::Widget(QWidget *parent) :
10 QWidget(parent),
11 ui(new Ui::Widget)
12 {
13 ui->setupUi(this);
14 serial = new QSerialPort;
15 /* regester software timer*/
16 atimer = new QTimer();
17 atimer->setInterval(1000);
18 atimer->start();
19
20 cycletime = new QTimer();
21 cycletime->setInterval(ui->lineEdit_cycletime->text().toInt());
22
23 QObject::connect(atimer,&QTimer::timeout,this,&Widget::timer_handle);
24
25 //查找可用的串口
26 foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
27 {
28 QSerialPort serial;
29 serial.setPort(info);
30 if(serial.open(QIODevice::ReadWrite))
31 {
32 ui->comBox->addItem(serial.portName());
33 serial.close();
34 }
35 }
36 //设置波特率下拉菜单默认显示第0项
37 ui->baudBox->setCurrentIndex(0);
38 ui->baudBox->setEnabled(false);
39 ui->stopbitBox->setEnabled(false);
40 ui->databitBox->setEnabled(false);
41 ui->checkBox->setEnabled(false);
42 ui->comBox->setEnabled(false);
43 }
44
45 Widget::~Widget()
46 {
47 delete ui;
48 }
49 void Widget::timer_handle(void)
50 {
51
52 QDateTime current_date_time =QDateTime::currentDateTime();
53 QString current_date =current_date_time.toString("yyyy.MM.dd hh:mm:ss ddd");
54 // ui->textBrowser_date
55 ui->label_date->setText(current_date);
56
57 }
58
59 void Widget::on_pushButton_oprea_clicked()
60 {
61 if(ui->pushButton_oprea->text() == tr("串口已关闭"))
62 {
63 serial = new QSerialPort;
64 //设置串口名
65 serial->setPortName(ui->comBox->currentText());
66 //打开串口
67 serial->open(QIODevice::ReadWrite);
68 //设置波特率
69 serial->setBaudRate(QSerialPort::Baud115200);//设置波特率为115200
70 //设置数据位数
71 switch (ui->databitBox->currentIndex())
72 {
73 case 0:
74 serial->setDataBits(QSerialPort::Data8);//设置数据位8
75 break;
76 default:
77 break;
78 }
79 //设置校验位
80 switch (ui->checkBox->currentIndex())
81 {
82 case 0:
83 serial->setParity(QSerialPort::NoParity);
84 break;
85 default:
86 break;
87 }
88 //设置停止位
89 switch (ui->stopbitBox->currentIndex())
90 {
91 case 0:
92 serial->setStopBits(QSerialPort::OneStop);//停止位设置为1
93 break;
94 case 1:
95 serial->setStopBits(QSerialPort::TwoStop);
96 default:
97 break;
98 }
99 //设置流控制
100 serial->setFlowControl(QSerialPort::NoFlowControl);//设置为无流控制
101
102 //关闭设置菜单使能
103 ui->baudBox->setEnabled(true);
104 ui->stopbitBox->setEnabled(true);
105 ui->databitBox->setEnabled(true);
106 ui->checkBox->setEnabled(true);
107 ui->comBox->setEnabled(true);
108 ui->pushButton_oprea->setText(tr("串口已打开"));
109
110 //连接信号槽
111 QObject::connect(serial,&QSerialPort::readyRead,this,&Widget::ReadData);
112 }
113 else
114 {
115 cycletime->stop();
116 //关闭串口
117 serial->clear();
118 serial->close();
119 serial->deleteLater();
120
121 //恢复设置使能
122 ui->baudBox->setEnabled(false);
123 ui->stopbitBox->setEnabled(false);
124 ui->databitBox->setEnabled(false);
125 ui->checkBox->setEnabled(false);
126 ui->comBox->setEnabled(false);
127 ui->pushButton_oprea->setText(tr("串口已关闭"));
128 }
129 }
130 //读取接收到的信息
131 void Widget::ReadData()
132 {
133 QByteArray temp;
134 if(ui->HEX_SHOW->isChecked())
135 {
136 SENDNUMSIZE = ui->lineEdit_duiqi->text().toInt();
137 temp = serial->readAll();
138 QDataStream out(&temp,QIODevice::ReadWrite); //将字节数组读入
139 while(!out.atEnd())
140 {
141 qint8 outChar = 0;
142 static qint8 datacount = 1;
143 recvCount++;
144 out>>outChar; //每字节填充一次,直到结束
145 datacount++;
146 //十六进制的转换
147 QString str = QString(" %1").arg(outChar&0xFF,2,16,QLatin1Char('0'));
148 ui->textBrowser->insertPlainText(str);
149 ui->label_recvvalue->setNum(recvCount);
150 if(SENDNUMSIZE+2 == datacount)
151 {
152 datacount = 1;
153 ui->textBrowser->insertPlainText("\n");
154 ui->textBrowser->moveCursor(QTextCursor::End);
155 }
156 }
157 }
158 else
159 {
160
161 temp += serial->readAll();
162 if(!temp.isEmpty())
163 {
164 ui->textBrowser->append(temp);
165 ui->textBrowser->moveCursor(QTextCursor::End);
166 }
167 temp.clear();
168 }
169
170 }
171 short Widget::checksum(QByteArray ba)
172 {
173 short i = 0,sumValue = 0;
174
175 for(i=2;i<(ba.length());i++)
176 {
177 sumValue+=ba.at(i);
178 }
179 return sumValue;
180 }
181
182 void Widget::on_send_clicked()
183 {
184 short checkValue = 0;
185 QString str;
186 QByteArray senddata;
187 if(ui->pushButton_oprea->text() == tr("串口已关闭"))
188 {
189 QMessageBox::information(this, "warning", "串口没打开", QMessageBox::Yes);
190
191 }
192 if(ui->radio_dash->isChecked())
193 {
194 str = ui->lineEdit_head->text()
195 + QString("%1").arg(ui->lineEdit_infopage->text().toShort(),2,16,QChar('0'))
196 + QString("%1").arg(ui->lineEdit_menu->text().toShort(),2,16,QChar('0'))
197 + QString("%1").arg(ui->lineEdit_speed->text().toShort(),2,16,QChar('0'))
198 + QString("%1").arg(ui->lineEdit_FP->text().toShort(),2,16,QChar('0'))
199 + QString("%1").arg(ui->lineEdit_BP->text().toShort(),2,16,QChar('0'))
200 + QString("%1").arg(ui->lineEdit_gear->text().toShort(),2,16,QChar('0'))
201 + QString("%1").arg(ui->lineEdit_hour->text().toShort(),2,16,QChar('0'))
202 + QString("%1").arg(ui->lineEdit_minute->text().toShort(),2,16,QChar('0'))
203 + QString("%1").arg(ui->lineEdit_TemP->text().toShort(),4,16,QChar('0'))//10
204 + QString("%1").arg(ui->lineEdit_trip->text().toShort(),4,16,QChar('0'))//12
205 + QString("%1").arg(ui->lineEdit_C_Trip->text().toShort(),4,16,QChar('0'))//14
206 + QString("%1").arg(ui->lineEdit_odo->text().toInt(),8,16,QChar('0'))//16
207 + QString("%1").arg(ui->lineEdit_LF_Press->text().toShort(),4,16,QChar('0'))//20
208 + QString("%1").arg(ui->lineEdit_LB_Press->text().toShort(),4,16,QChar('0'))//22
209 + QString("%1").arg(ui->lineEdit_RF_Press->text().toShort(),4,16,QChar('0'))//24
210 + QString("%1").arg(ui->lineEdit_RB_Press->text().toShort(),4,16,QChar('0'))//26
211 + QString("%1").arg(ui->lineEdit_oil_cost->text().toInt(),8,16,QChar('0'))//28
212 + QString("%1").arg(ui->lineEdit_C_oilcost->text().toShort(),2,16,QChar('0'))
213 + QString("%1").arg(ui->lineEdit_AV_oil_cost->text().toShort(),2,16,QChar('0'))
214 + QString("%1").arg(ui->lineEdit_can_warning->text().toShort(),2,16,QChar('0'))
215 + QString("%1").arg(ui->lineEdit_icon->text().toShort(),4,16,QChar('0'))//35
216 + QString("%1").arg(ui->lineEdit_backlight->text().toShort(),2,16,QChar('0'));
217 /*************** 调整short 和 init 数据类型字节发送顺序 ****************/
218 StringToHex(str,senddata);//将str字符串转换为16进制的形式
219 short_adjust(senddata,10);
220 short_adjust(senddata,12);
221 short_adjust(senddata,14);
222 int_adjust(senddata,16);
223 short_adjust(senddata,20);
224 short_adjust(senddata,22);
225 short_adjust(senddata,24);
226 short_adjust(senddata,26);
227 int_adjust(senddata,28);
228 short_adjust(senddata,35);
229 }
230 else{
231 str = ui->lineEdit_head->text()
232 + QString("%1").arg(ui->lineEdit_ST_Page->text().toShort(),2,16,QChar('0'))
233 + QString("%1").arg(ui->lineEdit_menu_level->text().toShort(),2,16,QChar('0'))
234 + QString("%1").arg(ui->lineEdit_cursor->text().toShort(),2,16,QChar('0'))
235 + QString("%1").arg(ui->lineEdit_C_selcet->text().toShort(),2,16,QChar('0'))
236 + QString("%1").arg(ui->lineEdit_num->text().toShort(),2,16,QChar('0'))
237 + QString("%1").arg(ui->lineEdit_S_num->text().toInt(),8,16,QChar('0'))
238 + QString("%1").arg(ui->lineEdit_S_hour->text().toShort(),2,16,QChar('0'))
239 + QString("%1").arg(ui->lineEdit_S_minute->text().toShort(),2,16,QChar('0'))
240 + QString("%1").arg(ui->lineEdit_S_year->text().toShort(),4,16,QChar('0'))
241 + QString("%1").arg(ui->lineEdit_S_month->text().toShort(),2,16,QChar('0'))
242 + QString("%1").arg(ui->lineEdit_S_day->text().toShort(),2,16,QChar('0'))
243 + QString("%1").arg(ui->lineEdit_S_backlight->text().toShort(),2,16,QChar('0'));
244 /*************** 调整short 和 init 数据类型字节发送顺序 ****************/
245 StringToHex(str,senddata);//将str字符串转换为16进制的形式
246 int_adjust(senddata,7);
247 short_adjust(senddata,13);
248 }
249
250
251 checkValue = checksum(senddata);
252 senddata.append((char)(checkValue));
253 serial->write(senddata);//发送到串口
254 CountBase+=senddata.length();
255
256 ui->label_sendvalue->setNum(CountBase);
257 }
258 void Widget::int_adjust(QByteArray &str,qint8 startcount)
259 {
260 qint8 temp1;
261 qint8 temp2;
262 temp1 = str[startcount];
263 temp2 = str[startcount+1];
264 str[startcount] = str[startcount+3];
265 str[startcount+1] = str[startcount+2];
266 str[startcount+2] =temp2;
267 str[startcount+3] =temp1;
268 }
269 void Widget::short_adjust(QByteArray &str,qint8 startcount)
270 {
271 qint8 temp1;
272 temp1 = str[startcount];
273 str[startcount] = str[startcount+1];
274 str[startcount+1] = temp1;
275 }
276
277 void Widget::StringToHex(QString str, QByteArray &senddata)
278 {
279
280 int hexdata,lowhexdata;
281
282 int hexdatalen = 0;
283
284 int len = str.length();
285
286 senddata.resize(len/2);
287
288 char lstr,hstr;
289
290 for(int i=0; i<len; )
291 {
292 //char lstr,
293 hstr=str[i].toLatin1();
294 if(hstr == ' ')
295 {
296 i++;
297 continue;
298 }
299 i++;
300 if(i >= len)
301 break;
302 lstr = str[i].toLatin1();
303 hexdata = ConvertHexChar(hstr);
304 lowhexdata = ConvertHexChar(lstr);
305 if((hexdata == 16) || (lowhexdata == 16))
306 break;
307 else
308 hexdata = hexdata*16+lowhexdata;
309 i++;
310 senddata[hexdatalen] = (char)hexdata;
311 hexdatalen++;
312 }
313 senddata.resize(hexdatalen);
314 }
315
316
317 char Widget::ConvertHexChar(char ch)
318 {
319 if((ch >= '0') && (ch <= '9'))
320 return ch-0x30;
321 else if((ch >= 'A') && (ch <= 'F'))
322 return ch-'A'+10;
323 else if((ch >= 'a') && (ch <= 'f'))
324 return ch-'a'+10;
325 else return (-1);
326
327
328 }
329
330
331 void Widget::on_pushButton_clicked()
332 {
333 ui->textBrowser->clear();
334 CountBase = 0;
335 ui->label_sendvalue->setNum(0);
336 recvCount = 0;
337 ui->label_recvvalue->setNum(0);
338 }
339 void Widget::cycletime_handle(void)
340 {
341 on_send_clicked();
342 }
343 void Widget::on_lineEdit_duiqi_editingFinished()
344 {
345 SENDNUMSIZE = ui->lineEdit_duiqi->text().toInt();
346 }
347
348 void Widget::on_checkBox_TIMER_stateChanged(int arg1)
349 {
350 if(ui->checkBox_TIMER->isChecked())
351 {
352 cycletime->start();
353 QObject::connect(cycletime,&QTimer::timeout,this,&Widget::cycletime_handle);
354 }
355 else
356 {
357 cycletime->stop();
358 }
359
360 }
all code