IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> qt做串口调试助手——通信收发篇 -> 正文阅读

[嵌入式]qt做串口调试助手——通信收发篇

qt实现串口调试助手

串口初始化

串口调试助手的初始化,一般包括波特率、端口号、奇偶校验、数据位和停止位。如果最终需要将串口商业化,一般这些参数都会交给用户自定义,但我们写了自己用,且上位机和下位机同时开发,则除了端口号,其余参数都会在代码里面定义好。
端口号一般采用自动扫描更新可用串口的方式,比直接列举COM1、COM2等要好很多。

	//参数初始化
 	global_port.setBaudRate(QSerialPort::Baud115200);  //波特率
    global_port.setParity(QSerialPort::NoParity)  ;   //无奇偶校验
    global_port.setDataBits(QSerialPort::Data8);    //8位数据位
    global_port.setStopBits(QSerialPort::OneStop);  // 1位停止位
    //定时扫描和更新串口
    timer = new QTimer;
    connect(timer,&QTimer::timeout,this,&MainWindow::showValidPort);//实时更新端口号
    timer->start(1000); //每1000ms定时检测串口状态
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) //扫描可用串口
    portStringList += info.portName();
    ui->comboVolt1->addItems(portStringList);//将扫描的端口号添加到下拉框

自定义通信协议

为了避免数据传输过程中丢失,我们不会直接接收并使用下位机发送的数据,而是拟定通信协议,包括设置帧头、数据位长度、数据、校验位、帧尾等。这样可以通过对帧头、帧尾的检验,防止数据在传输过程中有丢失。
下图是我根据自己的需求拟定的通信协议,一般如果能通过校验位的校验和帧头帧尾的检测,就说明数据在传输过程中没有丢失。
通信协议

上位机的接收

通信协议拟定好了,上位机的接收也是有讲究的,因为上位机不可能一次性正好接收以上的全部内容,而且我们传输的数据也有可能包含帧头帧尾等对应的ASCII码,为了防止误接收,一般我们设置一个缓冲区去接收数据,接收完一帧之后在处理
这下面的代码其实还有点问题,就是出现校验失败等问题之后,没有清除缓冲区重新接收,后面会再改进

 if((!array.contains("{"))&&buffer.isNull())//异常:头部丢失
        {
            return ;
        }
        //第一种,有头无尾,附加
        if(array.contains("{")&&(!array.contains("}")))
        {
           // buffer.clear();
            buffer.append(array);
        }
        //第二种:无头无尾且变量已有内容,数据中段部分,继续附加即可
        if((!array.contains("{"))&&(!array.contains("}"))&&(!buffer.isNull()))
        {
            buffer.append(array);
        }
        //第三种:无头有尾且变量已有内容,已完整读取,附加后可做处理
        if((!array.contains("{"))&&(array.contains("}"))&&(!buffer.isNull()))
        {
             buffer.append(array);
             is_readall = true;
        }
        //第四种:有头有尾(一段完整的内容),已完整读取
        if((array.contains("{"))&&(array.contains("}")))
        {
             buffer.append(array);
             is_readall = true;
        }
        if(is_readall)//缓存区有头有尾,已完整读取
        {
            qDebug() <<"buffer_size:";
            qDebug() <<buffer.size();//输出长度


            for(int i = 0;i<buffer.size();i++)
            {
                if((uint(uint(buffer.at(i))&0xff))==123)//定位帧头
                {
                    start = i+1;
                    qDebug() <<"start:";
                    break;
                }
            }
            DATA_LEN = ((uint)(buffer.at(start)))&0xff ;//帧头后接通道数
            qDebug() <<DATA_LEN;
            start++;
            if (index < BUFFERSIZE) index++;
            for(int i = 0;i<DATA_LEN;i++)//接收通道数后跟的数据
            {
                if (index >= BUFFERSIZE)  array_signal.at(i).pop_back();
                uint buf_0 = ((uint)buffer.at(4 * i+start)<< 24)& 0xff000000;
                uint buf_1 = ((uint)(buffer.at(4 * i + 1+start)) << 16)& 0x00ff0000;
                uint buf_2 = ((uint)(buffer.at(4 * i + 2+start)) << 8)  & 0x0000ff00;
                uint buf_3 = ((uint)(buffer.at(4 * i + 3+start)) )&0x000000ff ;
                uint buf = buf_0 + buf_1 + buf_2 + buf_3;
                sum+=buf_3;//校验和

                orginal_signal.at(i).insert(orginal_signal.at(i).begin(),
                    (float)(buf));//

                    buf = buf/1000;
                array_signal.at(i).insert(array_signal.at(i).begin(),
                    (float)(buf));//
                if(max_range[i]<buf) max_range[i] = buf;
                if(min_range[i]>buf) min_range[i] = buf;
            }

            is_readall = false;
            sum = sum&0xff;
            checksum = (uint)(buffer.at(buffer.size()-2))&0xff;//检查校验位
            if(checksum == sum)
            {
                qDebug() <<"checkcum successful!";
            }
            else
            {
                qDebug() <<"checkcum failed!";
            }
            if((uint)(buffer.at(buffer.size()-1))== 125)//帧尾
            {
                qDebug() <<"end!";
            }
            buffer.clear();

下位机的发送

串口助手肯定是需要下位机通过串口将数据发给上位机,不管是上位机的发送还是下位机的接收,都要跟通信协议对应上,相比之下,下位机的发送就很简单了,如果想要定时发送,就开个定时器,否则直接while(1)里面发送就行了。
以下是对应的下位机发送格式,使用的是STM32F1的板子

void send_resistance_value(u32 *value,int len)
{
	u8 temp1;
	u32 temp,sum = 0;
	int i = 0;
	USART_SendData(USART1, '{');//帧头1
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
	
	USART_SendData(USART1, len&0xff);//帧头1
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
	for(;i<len;i++)
	{
		temp = value[i];
		
		temp1 = (temp&0xff000000)>>24;
		USART_SendData(USART1, temp1);//向串口1发送最高位
		while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
		
		temp1 = (temp&0xff0000)>>16;
		USART_SendData(USART1, temp1);//向串口1发送次高位
		while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
		
		temp1 = (temp&0xff00)>>8;
		USART_SendData(USART1, temp1);//向串口1发送次低位
		while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
		
		temp1 = (temp&0xff);
		USART_SendData(USART1, temp1);//向串口1发送最低位
		while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
		
		sum+=temp1;//校验和		
	}
	
	temp1 = sum&0xff;
	USART_SendData(USART1, temp1);//发送校验和
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
	
	USART_SendData(USART1, '}');//帧尾
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
}
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-11-17 12:54:59  更:2021-11-17 12:56:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:56:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码