精华内容
下载资源
问答
  • 我现在要做一个全站仪的数据读取接口,由于不了解全站仪数据的发送方式,缓冲区大小该如何设置,才不会造成数据丢失? 比如我设置缓冲区大小为1024,我一次性发送2048个字节的数据,那么缓冲区只有1024个字节的数据,剩下...
  • 1.串口初始化配置//串口二初始化配置 void usart2_init(u32 bound) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; //开启GPIO时钟和...

    1.串口初始化配置

    //串口二初始化配置
    void usart2_init(u32 bound)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;
    	USART_InitTypeDef USART_InitStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    	
    	//开启GPIO时钟和串口2时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    	
    	//配置串口2参数
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//PA2:发送
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
    	GPIO_Init(GPIOA, &GPIO_InitStructure);
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3:接收
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    	GPIO_Init(GPIOA, &GPIO_InitStructure);
    	
    	//串口参数设置
    	USART_InitStructure.USART_BaudRate = bound;//波特率
    	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    	USART_InitStructure.USART_StopBits = USART_StopBits_1;
      USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
      USART_InitStructure.USART_Parity = USART_Parity_No;
      USART_Init(USART2, &USART_InitStructure);
    	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启中断,中断处理函数用于接收数据
      USART_Cmd(USART2, ENABLE);                    //使能串口 
    	
    	//NVIC内部中断向量管理配置
      NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
    	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化NVIC寄存器
    }
    

    2.利用串口发送数据

    //发送一个字符
    void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t ch)
    {
    	//发送一个字节数据到USART
    	USART_SendData(pUSARTx, ch);
    	
    	//等待发送数据寄存器为空
    	while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
    }
    
    //发送一个字符串
    void Usart_SendString(USART_TypeDef* pUSARTx, char* str)
    {
    	unsigned int k = 0;
    	do
    	{
    		//逐个字节发送
    		Usart_SendByte(pUSARTx, *(str + k));
    		k++;
    	}while(*(str + k) != '\0');
    	
    	//等待发送完成
    	while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET);
    }

    3.串口发送数据重定向到串口调试助手,输出调试信息。

    //重定义fputc函数 
    int fputc(int ch, FILE *f)
    {      
    	while((USART2->SR&0X40)==0);//循环发送,直到发送完毕   
            USART2->DR = (u8) ch;      
    	return ch;
    }

    4.串口接收数据

    u8 USART2_RX_BUF[USART_REC_LEN];   //串口二接收数据缓存
    u16 USART2_RX_STA = 0;//接收到的有效字节数目
    void USART2_IRQHandler(void)                    //串口2中断服务程序
    {
        u8 tmp;
        if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中断
        {
            tmp = USART_ReceiveData(USART2);  //读取接收到的数据
            if(tmp != 0x00)
            {
                USART2_RX_BUF[USART2_RX_STA] = tmp;
                USART2_RX_STA++;
            }
      }
    } 
    

    这里需要定义两个全局变量,第一个是接收数据的缓存,第二个是数据计数器,用来统计接收到的数据的数量。注意,有人可能会想到我可不可以直接在中断处理函数内部做一些处理操作,我的建议是不要,而是通过上诉最简单的方式。原因有两个,第一,这种方式思路清晰,第二,这种方式不会出现数据因为处理延时而丢失的问题,毕竟串口通信还是比较快的过程,如果花费过多的时间在中断处理函数中,可能导致意想不到的后果。另外,调试串口接收数据的时候,可能会出现问题,因为调试的过程中你的程序中途暂停执行了,但是不能保证发送方也暂停执行,所以会漏掉部分信息,常见的就是调试的时候只出现了第一个字节的数据,这是因为前面说的,毕竟串口通信还是比较快的。另外,串口接收的基础是在串口初始化的时候将接收中断打开。

    //主函数中通过串口发送数据,同时检测是否有数据到来,如果有判断是否为OK,如果是,则退出循环,否则再次发送,直到发送成功
    do
    {
    	//发送数据
    	Usart_SendString(USART2, "AT");
    				
    	//等待接收成功后回应的结果
    	delay_ms(3000);
    				
    	printf("send status:");
    	//判断是否发送成功
    	while(j < USART2_RX_STA)
    	{
    		printf("%c", USART2_RX_BUF[j]);
    		if((USART2_RX_BUF[j-1] == 'O' || USART2_RX_BUF[j-1] == 'o') && (USART2_RX_BUF[j] == 'K' || USART2_RX_BUF[j] == 'k'))
    		{
    			flag = 1;//发送成功
    			USART2_RX_STA = 0;
    			j = 0;
    			break;
    		}
    		j++;
    	}
    }while(flag == 0);

    其中flag是一个标志,flag==0代表数据发送失败,flag==1代表数据发送成功,此时将退出循环发送程序。

    最后,硬件平台:stm32f103zet6

    展开全文
  • 最近在软件调试中,发现数据一长就经常丢失数据,所以耐下心了解了一些原理,用较为简单的理解方式记录下来。 题外话: 一般来说,半双工通信需要添加一个超时时间,当超过这个时间后,就判定接收失败了,之前的缓存...

    最近在软件调试中,发现数据一长就经常丢失数据,所以耐下心了解了一些原理,用较为简单的理解方式记录下来。
    题外话
    一般来说,半双工通信需要添加一个超时时间,当超过这个时间后,就判定接收失败了,之前的缓存数据也要清空。
    个人选择定时器的方式,至于如何计算超时,公式如下:
    数据所需时常=总数据长度10/波特率。
    对于我的数据,最长为1237字节,波特率选择9600,则需要耗时1237
    10/9600=1.28854…,基本为1.3秒,所以我设置了串口的超时时间为3秒。发送后如果3秒没接收到数据,就算超时,直接发下一条指令。

    串口数据丢失:

    数据丢失中间部分数据或者尾部数据。
    问题原因:

    未使用好串口的丢弃缓存函数

    serialPort?.DiscardInBuffer();//丢弃接收缓冲区数据
    

    个人习惯在下面的代码后面添加丢弃缓存函数,导致数据丢失

     byte[] buffer = new byte[serialPort.BytesToRead];
     serialPort.Read(buffer, 0, buffer.Length);
    

    原因是我读取serialPort.BytesToRead长度时,用buffer取缓存的时候,长度已经增加了,所以我丢弃缓存会将还没获取的缓存一并清除。
    这里大家用read()方法的时候,其实读出来的数据在缓存中已经被清除了,不需要处理。

    串口数据一包分很多次触发串口事件

    为了串口一次得到完整包,一般我们在进入串口事件后会选择延时(根据完整包所需时长),再从缓存中获取数据。
    但是一旦数据包字节很长的时候,这样的方式就不是很好,因为延时造成界面卡或者漏包,就选择将延时去掉。
    使用9600的波特率接大于32字节的数据时,如果在串口事件中不延时,会发现每次触发触发事件可以接收到32个字节,所以需要拼接字节,得到最后的完整包。
    个人代码如下:

     private void DataReceived(object sender, SerialDataReceivedEventArgs e)
     {
         try
         {
             if (!serialPort.IsOpen)//串口在关闭时不接收数据 为了防止关闭串口时卡死的问题
             {
                 serialPort?.DiscardInBuffer();//丢弃接收缓冲区数据
                 return;
             }
             if (serialPort.BytesToRead < 4 && LineBuffer == null)
             {
                 return;
             }
             byte[] buffer = new byte[serialPort.BytesToRead];
             serialPort.Read(buffer, 0, buffer.Length);
             InquireOutTimeCount = 0;
             if (buffer == null || buffer.Length <= 0)
                 return;
             Show(buffer, "串口接收");
             if (buffer[0] == CommunicationHelper.CmdBagHead1 && buffer[1] == CommunicationHelper.CmdBagHead2)//判断是否是包头
             {
                 LineBuffer = buffer;
             }
             else if (LineBuffer != null)//拼接
             {
                 LineBuffer = CommunicationHelper.AddBytes(LineBuffer, buffer);
             }
             //之后去判断包是否完整,完整解析后清空自己的缓存
             .........
    }
    

    有关串口事件说明

    串口内部有一个缓存,串口数据都会保留在这里,可使用read()去读取。
    经过调试,发现串口事件应该是一个时间触发的机制,例如9600的波特率每次触发串口事件最多能传递32个字节。
    串口内部的缓存是类似队列的先进先出,进入串口事件后,读到的缓存长度serialPort.BytesToRead只是读的时候缓存的长度,可能你下一行代码去取缓存的时候,缓存就增加了,你只能取到之前的缓存数量,若没有选择清空缓存,完成本次串口事件后,剩余的缓存会再次触发串口事件让你继续读取缓存。

    展开全文
  • Qt以前的版本中,没有提供官方的对RS232串口的支持,编写串口程序很不方便。现在好了,在 Qt5.1 中提供了QtSerialPort模块,方便编程人员快速的开发应用串口的应用程序。 Qt5 serialPort存在的问题。

    什么是Qt5 serialPort?

    虽然现在大多数的家用PC机上已经不提供RS232接口了。但是由于RS232串口操作简单、通讯可靠,在工业领域中仍然有大量的应用。Qt以前的版本中,没有提供官方的对RS232串口的支持,编写串口程序很不方便。现在好了,在 Qt5.1 中提供了QtSerialPort模块,方便编程人员快速的开发应用串口的应用程序。

    Qt5 serialPort存在的问题。

    在项目中需要编写一个上位机串口接受数据,结果发现接受数据时,使用Qt5serialport会丢失数据。编写程序时参考文章。
    http://blog.csdn.net/u014695839/article/details/50611549
    然后换用多个版本任然存在此问题。

    解决方式。

    使用第三方库 qextserialport ,使用这个比较古老的库就不会出现本文所述问题。使用这个库可以参考
    http://blog.csdn.net/u010580186/article/details/51595227
    这篇文章,这篇文章详细介绍了如何使用。包括加入.h文件,以及加入.cpp文件等。可以先参考第一部来测试是否丢失数据。

    如何判断是否丢失数据?

    我在上面提到的博文中优化了显示数据,即是可以显示看到是否有数据。数据是否丢失,使用qDebug方法
    void MainWindow::readMyCom() //读串口函数
    {
    //	qDebug() << "进入";
    	
    	if (myCom->bytesAvailable() >= 56)
    	{
    		qDebug() << "1";
    		QByteArray temp = myCom->readAll();
    		//读取串口缓冲区的所有数据给临时变量temp
    		ui->textBrowser->insertPlainText(temp);
    		qDebug() << temp;
    		//将串口的数据显示在窗口的文本浏览器中
    
    		QDataStream out(&temp, QIODevice::ReadWrite);   //将str的数据 读到out里面去
    															   //  QVector <QString> tempstr;
    		QString tempstr[112];
    		// QString buf;
    		int i = 0;
    		while (!out.atEnd())
    		{
    			qint8 outChar = 0;
    			out >> outChar;   //每次一个字节的填充到 outchar
    							  //           qDebug()<<outChar;
    							  //           QString str = QString("%1").arg(outChar&0xFF,2,16,QLatin1Char('0')).toUpper();// + QString(" ");   //2 字符宽度
    
    							  //           tempstr[i] << str;
    			tempstr[i] = QString("%1").arg(outChar & 0xFF, 2, 16, QLatin1Char('0')).toUpper();
    			//qDebug() << "******";
    			//qDebug() << tempstr[i];
    			//qDebug() << "******";
    			if (i<56)
    				i++;
    		}
    		for(int i = 0; i < 96; i++)
    			qDebug()<<tempstr[i];
    	}
    }
    

    同时还要注意串口是串口几,博文默认的是串口1,但是我的是串口3因此需要改动
    myCom = new Win_QextSerialPort("com3", myComSetting, QextSerialBase::EventDriven)



     

    展开全文
  • 项目需要实现下位机和上位机的数据传输,看了网上的很多上位机的处理方法主要有两种。方法一是:port_DataReceived(SerialPort控件的数据接收方法,当有数据来临时会触发)会创建一个线程,因此当串口在等待数据时...

    项目需要实现下位机和上位机的数据传输,看了网上的很多上位机的处理方法主要有两种。方法一是:port_DataReceived(SerialPort控件的数据接收方法,当有数据来临时会触发)会创建一个线程,因此当串口在等待数据时,不影响主窗体或主线程的操作。方法二是:使用缓存机制(参考:http://blog.csdn.net/jiqiang_paul/article/details/6914619)。首先通过定义一个成员变量List ReceBuf  new List(4096);用来存放所有的数据,在接收函数里,通过RecBuf.AddRange()方法不断地将接收到的数据加入到ReceBuf中,并同时对Recebuf中的数据进行检验,如果达到一定的长度并且校验结果正确(校验方法在发送方和接收方一致),再进行处理。

    经过测试发现这两种方法在数据包发送间隔小于200ms时,会出现数据丢包的问题,现在将这两种方法结合起来,同时将方法二改进为双缓存机制,经过测试发现可以解决数据的丢包的问题。
    一、在 public MainForm()中定义串口数据接收事件
      public MainForm()
            {
                InitializeComponent();
                serialPort_port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);//串口接收事件
                System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;//关闭夸线程检查
            }
    二、MainForm类下定义接收事件的委托并编写接收程序
     
      public delegate void PortDelegate();
            private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                PortDelegate proc_PORTGETDATA = new PortDelegate(getComData);
                IAsyncResult async_PORTGETDATA = proc_PORTGETDATA.BeginInvoke(null, null);
            }
    private List ReceBuffer = new List(4096);//串口接收一级缓存,默认分配一页内存并始终不超过 
     private byte[] DataTemp = new byte[10];//从一级缓存拷贝到二级缓存 
     private List DataBuf = new List(1000);//串口接收二级缓存,默认分配1000并始终不超过
     private byte[] DataTemp2 = new byte[10];//从二级缓存拷贝出来分析
     private byte[] DataAnalyBuf = new byte[8]; 
     public void getComData()
     { 
     try
     { 
     int n = serialPort_port.BytesToRead; 
     byte[] Receive = new byte[n]; 
     serialPort_port.Read(Receive, 0, Receive.Length); 
     bool DataCatched = false;//数据可以分析的标志
     //缓存数据 
     ReceBuffer.AddRange(Receive); 
     //完整性判断 
     while(ReceBuffer.Count >= 10)
     { 
     查看帧首和尾数据,判断准确性 
    //这里可以写成对数据的校验如CRC
    if (ReceBuffer[0] == 0x50 && ReceBuffer[9] == 0x42) 
     { 
     ReceBuffer.CopyTo(0, DataTemp, 0, 10); 
     DataBuf.AddRange(DataTemp); 
    DataCatched = true; 
     ReceBuffer.RemoveRange(0, 10);//获得一条正确的数据,删除缓存
     }
     else
     { 
     ReceBuffer.RemoveAt(0);//不是数据头,删除数据
     }
     }
     //分析数据 
     if (DataCatched == true) 
     { 
     while (DataBuf.Count > 0)
     {
     DataBuf.CopyTo(0,DataTemp2,0,10); 
    在这里写自己的数据分析
    DataBuf.RemoveRange(0, 10);
     } 
     }
     } catch { } 
     }

    转载于:https://www.cnblogs.com/cmblogs/p/11129313.html

    展开全文
  • 串口通信数据丢失的问题

    千次阅读 2010-05-20 18:30:00
    担任去中兴软创合作的项目,...昨天调试我写的串口通信程序,发现0x00的数据无法接收。在网上找了一下,发现有不少人有遇到这个问题。 今天早上来,把程序改过了,现在可以很好地接收到0x00数据了。   参考了一些资料 ...
  • 个人认为:GB2312编码中文字是2个字节表示,串口在读数据的时候可能只读到此中文字的第一个字节,第二个字节在下一轮读取。 代码如下,请大牛们帮忙看看,感谢! ``` #!/usr/bin/python # -*-coding: utf-8 -*...
  • STM32 串口 发送 必须 先检测 状态,否则 第一个 字节 无法 发出,发送完毕,必须检测发送状态...接收端收到的数据为:0x02 0x03 0x04,第一个数据丢失。换成发送别的数值的数据,如0x06 0x0ff,则接收到0x0ff,0x0...
  • 串口接收时丢数据问题解决方案

    千次阅读 2019-04-13 13:13:40
    串口接收时丢数据问题解决方案
  • 想写一个简单的串口通信程序(中断接收pc发送的数据,并随之发送给pc),大概内容如下:初始化USART1和NVIC,USART1_Config();NVIC_Config();中断函数如下:voidUSART1_IRQHandler(vo...想写一个简单的串口通信程序...
  • 2、因为数据接收不对,所以我用串口精灵监视发送的数据,发现数据是有正确发送的。 ![图片说明](https://img-ask.csdn.net/upload/202006/02/1591105629_397817.png) 3、这个是接收的arduino程序。我设定了一个...
  • 项目场景: STM32调用接口HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_...实际发送后有等待DMA发送完成,但是连续两个数据发送依旧会导致丢失。 HAL_UART_Transmit_
  • 最开始看一个官方的串口收发数据的示例,然后自己操作后收发数据老是会丢失一个数据,然后看User’s Guide,取消了函数收发的方法直接用寄存器操作,问题解决。 接下来写一个组帧协议,收发完全正常。但是看上去非常...
  • PySerial无法正确接收数据

    千次阅读 2021-02-09 08:33:12
    有时,有时甚至更常见的情况是,发送的数据中存在附加字符或某些字符/部分丢失。看来,PC机和数据发射器没有正确同步。在在当前的示例中,我使用一个arduino,通过以下简单代码将“Hello World”发送到我电脑的串行...
  • android设备使用usb串口传输数据

    千次阅读 2018-06-07 11:19:53
    https://code.google.com/archive/p/android-serialport-api/另一个是我们这次介绍的开源项目:https://github.com/mik3y/usb-serial-for-android   第一步:获取所有的已插入的串口驱动1 UsbManager manager = ...
  • 使用stm32f205调试串口通讯时,发现一个问题,上电后串口发送字符串的第一个字节会丢失,发送测试数据hello,接收端收到的数据为:ello,第一个字符丢失。用示波器抓取波形,发现第一个数据的波型也是丢失的。
  • 在进行串口通讯实验时,一时不仔细可能会发现通讯不正常,数据丢失的现象,包括丢失第一个字符,或只收到最后一个字符等等,本文接下来将就这类问题展开讨论。 首先是通过MCU向上位机发送数据: 若程序如下图所示...
  • 转载来源:嵌入式系统之初学者点滴 (百度空间...此时将显示写入串口成功,但是读串口数据失败。这个奇怪的问题当时之所以没有被发现出来,是因为在这之前,曾经打开过一次minicom。后来实验表明,如果打开过一次mini...
  • 在进行串口通信时由于串口接受的数据为16进制数、在界面传输串口时候是以QString类型传输、进行转换16进制就是以十进制转换成16进制、可以传输成功、但是没一次9-10 19-20 99-100 等就会出现数据丢失、所以进行...
  • STM32串口发送必须先检测状态,否则第一个字节无法发出,发送完毕,必须检测...接收端收到的数据为:0x02 0x03 0x04,第一个数据丢失。换成发送别的数值的数据,如0x06 0x0ff,则接收到0x0ff,0x06丢失。错误依旧。...
  • Android USB串口传输数据

    千次阅读 2019-06-21 20:02:56
    之前介绍了485串口传输数据,使用了https://github.com/cepr/android-serialport-api,本节课我们介绍usb串口数据传输。 使用usb串口传输数据的第三方库:https://github.com/mik3y/usb-serial-for-android 一、...
  • 采用Qt编写双串口子线程接收高速大量数据(921600bps,底层数据发送率是1000Hz,一帧数据16字节),当底层数据缓冲区长度不定的时候,Qt上位机接受数据容易出错。 解决方案: 1.接受采用队列作为缓冲区,剔除错误...
  • 最开始看一个官方的串口收发数据的示例,然后自己操作后收发数据老是会丢失一个数据,然后看User’s Guide,取消了函数收发的方法直接用寄存器操作,问题解决。 接下来写一个组帧协议,收发完全正常。但是看上去非常...
  • 开发一款产品过程中,由于需要使用串口4进行数据收发.接收过程没有问题,发送数据时发现连续发送数据存在数据错误和丢失数据的问题。经过测试发送数组 {0x00,0x01,0x02, 0x03, 0x04,0x05,0x06,0x07,0x08,0x09,0x0A,...
  • 否则第一个字节无法发出,发送完毕,必须检测发送状态是否完成,否则,发送不成功,使用stm32f10x调试串口通讯时,发现一个出错的现象,硬件复位重启之后,发送测试数据0x01 0x02 0x03 0x04..接收端收到的数据为:0x...
  • stm32用printf函数重定向到串口USART1发现第一个字符没打印出来具体如下:刚开始修改fputc函数如下:int fputc(int ch,FILE *f){USART_SendData(USART1,(uint8_t)ch);while(USART_GetFlagStatus(USART1, USART_FLAG...
  • 另外当对方向我发送一串数据,如果其中有0x11,那么我总是漏收此数,这是问题二。由于问题莫名其妙,以为是笔记本的USB转232线缆的问题,换,问题依旧。以为是对方设备的问题,采用串口调试助手模拟通讯设备与ARM板...
  • 使用STM32的串口进行大量数据传输

    万次阅读 热门讨论 2016-11-02 21:51:58
    最近的一个项目需要用单片机和上位机进行大量数据传输,每次传输的内容为一个1000*7的矩阵,矩阵中的每个元素都是一个4位有效数字,通过字符的形式保存,(如:1.000占5个字节)简单计算一下,1000*7*5=35000Byte,...
  • 1、开发平台计算机操作系统:WIN7 64位;开发环境:Keil MDK 5.14;...2、问题描述 在测试用STM32F4xx芯片的串口USART1以DMA方式进行RS485收发通讯时,出现数据字节丢失的现象,一般丢失1~2个字节。 出现问题时...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,185
精华内容 3,274
关键字:

串口传输数据丢失