QT 串口发送接收(带发送缓冲区)
串口代码更改,这里记录一下。接收因为是类似于中断的方式,接收一次处理一次,就没做接收缓冲区。与主板通讯模式为主从模式,串口发送函数用时钟轮询该函数。
变量定义
unsigned char serial_main::Send_Buf[30000][300];//发送缓冲区
unsigned char serial_main::recv_buf[150];//查询接收数据数组
串口初始化
/*********通讯串口初始化*******/
void serial_main::serial_port_init()
{
qDebug()<<"serial port init.";
serial_port_1 = new QSerialPort(this);
//open_serial(m_com4,"/dev/ttyS1");
open_serial(serial_port_1,"/dev/ttySAC1");
}
打开串口
/********打开串口***********/
void serial_main::open_serial(QSerialPort *serial, QString name)
{
qDebug()<<"serial port open.";
serial->setPortName(name);
serial->setBaudRate(QSerialPort::Baud115200);//设置波特率和读写方向
// serial->setBaudRate(QSerialPort::Baud57600);//设置波特率和读写方向
serial->setDataBits(QSerialPort::Data8); //数据位为8位
serial->setParity(QSerialPort::EvenParity); //偶验位
serial->setFlowControl(QSerialPort::NoFlowControl);//无流控制
serial->setStopBits(QSerialPort::OneStop); //一位停止位
if(serial->open(QIODevice::ReadWrite))
{
//连接串口接收
connect(serial, &QSerialPort::readyRead,this,&serial_main::receiveData);
//连接接收分析函数
connect(this,SIGNAL(receiveData_analysis_switch_1(QByteArray ,QString )),receive_data_main,SLOT(receiveData_analysis_switch_1(QByteArray ,QString )));
qDebug()<<"open com" << name << "success!";
//发送缓冲区初始化
connect(this,SIGNAL(txd_rxd_data_init()),send_data_main,SLOT(txd_rxd_data_init()));
emit txd_rxd_data_init();//初始化发送数据缓冲区,发送功能号0x02数据读取主板数据
qDebug()<<"txd rxd data success!";
return ;
}
else
{
qDebug()<<"open com" << name << "failed!";
}
}
串口发送函数
/*******串口发送函数*********/
void serial_main::sendDate()
{
// if(Send_fail==0)
// {
QByteArray data,temp;
if(serial_main::Send_Buf[0][0]==0x00)//查询
{
unsigned char temp_query_buf[15];
unsigned int chk = 0;
temp_query_buf[0] = 0x33;//头
temp_query_buf[1] = 0x43;//主板编号
temp_query_buf[2] = 0x0f;//帧长度
temp_query_buf[3] = 0xff;//随机生成唯一标识符高位
temp_query_buf[4] = 0xff;//随机生成唯一标识符低位
temp_query_buf[5] = 0x2c;//功能号
temp_query_buf[6] = 0x00;//数据地址高位
temp_query_buf[7] = 0x00;//数据地址低位
temp_query_buf[8] = 0x00;//数据包序号,0表示没有分包
temp_query_buf[9] = 0x00;//总数据分成了多少个包,0表示没有分包
temp_query_buf[10] = 0x01;//当前数据包数据长度
temp_query_buf[11] = 0x01;//数据内容
for(int i=0; i <12; ++i)chk = (serial_main::crc16_tab[((chk>>8) ^ temp_query_buf[i]) & 0xFF] ^ (chk << 8));
temp_query_buf[12] = (chk >> 8);//CRC校验高位
temp_query_buf[13] = (chk );//CRC校验低位
temp_query_buf[14] = 0x0d;//尾巴
for(int i=0;i<15;i++)
{
data.clear();
data.append(temp_query_buf[i]);
serial_port_1->write(data);
}
}
else
{
trans_size = Send_Buf[0][2];
for(int i=0;i<trans_size;i++)
{
data.clear();
data.append(serial_main::Send_Buf[0][i]);
temp.append(QString::number(serial_main::Send_Buf[0][i], 16));
temp.append("-");
serial_port_1->write(data);
}
// qDebug()<<temp<<trans_size;
// emit ButtonCommunicationDisplay_Send("SendDate:"+temp+" "+"size:"+QString::number(trans_size));
}
// /***************************************************************************/
// // qDebug()<<"TimeoutCount"<<TimeoutCount;
// if(serial_main::TimeoutCount>=50000)
// emit DictionaryQueryComplete(tr("通讯异常,请检查线路或程序是否匹配!"));
// else
// serial_main::TimeoutCount++;
// /***************************************************************************/
// }
}
发送缓冲区插入
/***********发送缓冲区插入main函数***********/
void serial_send_data::txd_All(int FuntionNumber,unsigned int address,int DateNumber,int DateLength_All,QString txd_date)
{
switch(FuntionNumber)
{
case 0x66://停止命令
{
//遍历缓存区,原始数据下移,此数据插入第一行
txd_All_0x66(FuntionNumber,address,DateNumber,DateLength_All,txd_date);
break;
}
// case 0x16://手动的伺服动作
// {
// //清空缓冲区,此数据插入第一行
// txd_All_0x16(FuntionNumber,address,DateNumber,DateLength_All,txd_date);
// break;
// }
default:
{
//插入缓存区末尾
txd_All_default(FuntionNumber,address,DateNumber,DateLength_All,txd_date);
break;
}
}
// QString temp_SendBug;
// for(int i=0;i<tail_pointer+1;i++)
// {
// for(int j=0;j<trans_size;j++)
// {
// QByteArray temp;
// temp.append(Send_Buf[i][j]);
// temp_SendBug += temp.toHex();
// temp_SendBug += "-";
// }
// qDebug()<<"Send_Buf:"<<temp_SendBug;
// temp_SendBug.clear();
// }
serial_main::long_set_flag = 1;
// stopbz=1;
// tx_count=0;
// commandflag=1;
// myreadstate.manualflag=2;
}
/*********停止命令 遍历缓存区,原始数据下移,此数据插入第一行**********/
void serial_send_data::txd_All_0x66(int FuntionNumber,unsigned int address,int DateNumber,int DateLength_All,QString txd_date)
{
bool ok;
int j=11;
unsigned int chk=0;
QByteArray Data_ByteArray;
/*********************************************************************/
int Tail_Pointer = 0;
for(int i=0;i<30000;i++)
{
if(serial_main::Send_Buf[i][0]==0x00)
{
Tail_Pointer = i;
break;
}
}
for(int i=Tail_Pointer;i>0;i--)
{
for(int j=0;j<300;j++)
{
serial_main::Send_Buf[i][j] = serial_main::Send_Buf[i-1][j];
}
}
/*********************************************************************/
QTime randtime;
randtime = QTime::currentTime();
qsrand(randtime.msec()+randtime.second()*1000); //以当前时间ms为随机种子
serial_main::Send_RandomNumber = qrand() % 6000; //产生0~6000的随机整数
serial_main::Send_Buf[0][0] = SYNC;//0x33
serial_main::Send_Buf[0][1] = SM_ADDR;//0x43
serial_main::Send_Buf[0][2] = (14+(txd_date.length()/2));//帧长度
serial_main::Send_Buf[0][3] = (serial_main::Send_RandomNumber&0xff00)>>8;//以随机数生成唯一标识符
serial_main::Send_Buf[0][4] = (serial_main::Send_RandomNumber&0x00ff);
serial_main::Send_Buf[0][5] = FuntionNumber;//功能号,0~255
serial_main::Send_Buf[0][6] = (address&0xff00)>>8;//数据地址
serial_main::Send_Buf[0][7] = (address&0x00ff);
serial_main::Send_Buf[0][8] = DateNumber;//数据包序号,0表示没有分包
serial_main::Send_Buf[0][9] = DateLength_All;//总数据分成了多少个包,0表示没有分包
serial_main::Send_Buf[0][10] = (txd_date.length()/2);//当前数据包数据长度
for(int i=0;i<txd_date.length()/2;i++)
{
Data_ByteArray.clear();
Data_ByteArray.append(txd_date.mid(2*i, 2));
serial_main::Send_Buf[0][j] = Data_ByteArray.toInt(&ok, 16);//将字符串代表的16进制数转换成10进制
j++;
}
/*********************************************************************/
for(int i=0; i <j; ++i)
chk = serial_main::crc16_tab[((chk>>8) ^ serial_main::Send_Buf[0][i]) & 0xFF] ^ (chk << 8);
serial_main::Send_Buf[0][j] = (chk >> 8);
serial_main::Send_Buf[0][j+1] = (chk );
serial_main::Send_Buf[0][j+2]=FRAME_END;
// sys_txd.combuf[3]=sys_txd.combuf[3]+2;
// memcpy(ser_queue[XMIT_QUEUE].entry[temp].buf,sys_txd.combuf,j+2);
serial_main::trans_size=j+3;
// if (myreadstate.manualflag!=0)
// txerrcount=200;
/*********************************************************************/
}
/********手动的伺服动作 清空缓冲区,此数据插入第一行**********/
void serial_send_data::txd_All_0x16(int FuntionNumber,unsigned int address,int DateNumber,int DateLength_All,QString txd_date)
{
bool ok;
int j=11;
unsigned int chk=0;
QByteArray Data_ByteArray;
/************************************************/
for(int i=0;i<30000;i++)
{
for(int j = 0;j<300;j++)serial_main::Send_Buf[i][j] = 0x00;
}
/************************************************/
QTime randtime;
randtime = QTime::currentTime();
qsrand(randtime.msec()+randtime.second()*1000); //以当前时间ms为随机种子
serial_main::Send_RandomNumber = qrand() % 6000; //产生0~6000的随机整数
serial_main::Send_Buf[0][0] = SYNC;//0x33
serial_main::Send_Buf[0][1] = SM_ADDR;//0x43
serial_main::Send_Buf[0][2] = (14+(txd_date.length()/2));//帧长度
serial_main::Send_Buf[0][3] = (serial_main::Send_RandomNumber&0xff00)>>8;//以随机数生成唯一标识符
serial_main::Send_Buf[0][4] = (serial_main::Send_RandomNumber&0x00ff);
serial_main::Send_Buf[0][5] = FuntionNumber;//功能号,0~255
serial_main::Send_Buf[0][6] = (address&0xff00)>>8;//数据地址
serial_main::Send_Buf[0][7] = (address&0x00ff);
serial_main::Send_Buf[0][8] = DateNumber;//数据包序号,0表示没有分包
serial_main::Send_Buf[0][9] = DateLength_All;//总数据分成了多少个包,0表示没有分包
serial_main::Send_Buf[0][10] = (txd_date.length()/2);//当前数据包数据长度
for(int i=0;i<txd_date.length()/2;i++)
{
Data_ByteArray.clear();
Data_ByteArray.append(txd_date.mid(2*i, 2));
serial_main::Send_Buf[0][j] = Data_ByteArray.toInt(&ok, 16);//将字符串代表的16进制数转换成10进制
j++;
}
/*********************************************************************/
for(int i=0; i <j; ++i)
chk = serial_main::crc16_tab[((chk>>8) ^ serial_main::Send_Buf[0][i]) & 0xFF] ^ (chk << 8);
serial_main::Send_Buf[0][j] = (chk >> 8);
serial_main::Send_Buf[0][j+1] = (chk );
serial_main::Send_Buf[0][j+2]=FRAME_END;
// sys_txd.combuf[3]=sys_txd.combuf[3]+2;
// memcpy(ser_queue[XMIT_QUEUE].entry[temp].buf,sys_txd.combuf,j+2);
serial_main::trans_size=j+3;
// if (myreadstate.manualflag!=0)
// txerrcount=200;
/*********************************************************************/
}
/*******插入缓冲区末尾***********/
void serial_send_data::txd_All_default(int FuntionNumber,unsigned int address,int DateNumber,int DateLength_All,QString txd_date)
{
bool ok;
int j=11;
unsigned int chk=0;
QByteArray Data_ByteArray;
int tail_pointer = 0;
for(int i=0;i<30000;i++)
{
if(serial_main::Send_Buf[i][0]==0x00)
{
tail_pointer = i;
break;
}
}
serial_main::Send_RandomNumber = qrand() % 6000; //产生0~6000的随机整数
serial_main::Send_Buf[tail_pointer][0] = SYNC;//0x33
serial_main::Send_Buf[tail_pointer][1] = SM_ADDR;//0x43
serial_main::Send_Buf[tail_pointer][2] = (14+(txd_date.length()/2));//帧长度
serial_main::Send_Buf[tail_pointer][3] = (serial_main::Send_RandomNumber&0xff00)>>8;//以随机数生成唯一标识符
serial_main::Send_Buf[tail_pointer][4] = (serial_main::Send_RandomNumber&0x00ff);
serial_main::Send_Buf[tail_pointer][5] = FuntionNumber;//功能号,0~255
serial_main::Send_Buf[tail_pointer][6] = (address&0xff00)>>8;//数据地址
serial_main::Send_Buf[tail_pointer][7] = (address&0x00ff);
serial_main::Send_Buf[tail_pointer][8] = DateNumber;//数据包序号,0表示没有分包
serial_main::Send_Buf[tail_pointer][9] = DateLength_All;//总数据分成了多少个包,0表示没有分包
serial_main::Send_Buf[tail_pointer][10] = (txd_date.length()/2);//当前数据包数据长度
for(int i=0;i<txd_date.length()/2;i++)
{
Data_ByteArray.clear();
Data_ByteArray.append(txd_date.mid(2*i, 2));
serial_main::Send_Buf[tail_pointer][j] = Data_ByteArray.toInt(&ok, 16);//将字符串代表的16进制数转换成10进制
j++;
}
/*********************************************************************/
for(int i=0; i <j; ++i)
chk = serial_main::crc16_tab[((chk>>8) ^ serial_main::Send_Buf[tail_pointer][i]) & 0xFF] ^ (chk << 8);
serial_main::Send_Buf[tail_pointer][j] = (chk >> 8);
serial_main::Send_Buf[tail_pointer][j+1] = (chk );
serial_main::Send_Buf[tail_pointer][j+2]=FRAME_END;
// sys_txd.combuf[3]=sys_txd.combuf[3]+2;
// memcpy(ser_queue[XMIT_QUEUE].entry[temp].buf,sys_txd.combuf,j+2);
serial_main::trans_size=j+3;
// if (myreadstate.manualflag!=0)
// txerrcount=200;
/*********************************************************************/
}
使用例子
QString temp_string = NULL;
int temp_int = ui->speed_lineedit->text().toInt();
int temp_position_plus = (ui->position_plus_lineedit->text().toFloat())*100;
int temp_position_re = (ui->position_reduce_lineedit->text().toFloat())*100;
temp_string += "70";//按钮命令值
temp_string += "00";//轴选择命令值
temp_string += serial_send_data_1->txd_All_QStringAnalysis(temp_int);//速度
temp_string += serial_send_data_1->txd_All_QStringAnalysis(((temp_position_plus&0xff0000)>>16));//位置+高位
temp_string += serial_send_data_1->txd_All_QStringAnalysis((temp_position_plus&0xff00)>>8);//位置+中位
temp_string += serial_send_data_1->txd_All_QStringAnalysis(temp_position_plus&0x00ff);//位置+低位
temp_string += serial_send_data_1->txd_All_QStringAnalysis(((temp_position_re&0xff0000)>>16));//位置-高位
temp_string += serial_send_data_1->txd_All_QStringAnalysis((temp_position_re&0xff00)>>8);//位置-中位
temp_string += serial_send_data_1->txd_All_QStringAnalysis(temp_position_re&0x00ff);//位置-低位
serial_send_data_1->txd_All(0x03,0x0070,0x00,0x00,temp_string);
QString serial_send_data::txd_All_QStringAnalysis(unsigned char analysis_string)
{
serial_main::long_set_flag = 1;
QString temp = NULL;
if(QString::number(analysis_string,16).length()==1)
{
temp = "0"+QString::number(analysis_string,16);
}
else
{
temp = QString::number(analysis_string,16);
}
return temp;
}
总结
有些功能还没做完,这里记录一下。