移远EC20串口使用阻塞问题

移远EC20串口使用阻塞问题今天我们郭工使用我写的 EC20 程序发现了一个严重的问题 就是运行一段时间后会出现丢数据的情况 使用供应商的程序却能很好的运行我很奇怪 仔细看了供应商的历程发现他们用的是 select 机制 我突然有个灵感是不是我的读取串口导致了串口阻塞 一查果然是 Linux 下直接用 read 读串口可能会造成堵塞 或数据读出错误 然而用 select 先查询 com 口是否可读则可以

      今天我们郭工使用我写的EC20程序发现了一个严重的问题,就是运行一段时间后会出现丢数据的情况。使用供应商的程序却能很好的运行我很奇怪,仔细看了供应商的历程发现他们用的是select机制。

      我突然有个灵感是不是我的读取串口导致了串口阻塞?一查果然是。

      Linux下直接用read读串口可能会造成堵塞,或数据读出错误。然而用select先查询com口是否可读则可以避免这个问题。但是也会引起另一个问题,那就是会使使用select的线程在没有收到数据时像休眠阻塞一样。因为select是在 一定的时间内循环的去判断串口是否可读。

     之前的旧程序

int main() { unsigned int i; int return_value = 0; unsigned long startCount = 0;//开机计时 重启后30分钟不变化 unsigned char Signal_Strength_temp; unsigned char WIFIName_temp[33]; int TFcardState;//卡状态 int I_temp; GS_PC_str.RevBufLen = 0; //串口初始化  bps,8 N 1 GS_PC_str.fd = Serial_Open("/dev/ttyHS0", B, EIGHT_BIT, PARITY_NONE, ONE_BIT, FLOW_CONTROL_NONE); if(GS_PC_str.fd<0) { printf("serial open fail\n"); return 0; } else { printf("serial open success fd = %d\n",GS_PC_str.fd); } //卡状态 TFcardState = Hk_Camera_Get_SD_State(&GS_TF_state); printf("return_value = %d\n", TFcardState); printf("state->f_blocks = %d\n", GS_TF_state.f_blocks); printf("state->f_bavail = %d\n", GS_TF_state.f_bavail); printf("state->used_percent = %d\n", GS_TF_state.can_used_percent); //配置自己的IP地址 HK_Camera_Init_Internet_Ip("192.168.1.5"); //拨号状态 GS_Call_state = Hk_Camera_Data_Call(); //开启摄像头功能 Hk_Camera_Paramete_Init(); Hk_Camera_Init_Camera("192.168.1.64", 13851, 0, 3);//开启第1(1~4) Hk_Camera_Start_Camera_Communicate(); while(1) { //读取信号强度 GS_Signal_Strength = Hk_Camera_Get_Signal_Strength(); printf("Signal Strength = %d\n", GS_Signal_Strength); if(GS_Signal_Strength>99) { Signal_Strength_temp = 98; } else { Signal_Strength_temp = GS_Signal_Strength; } //拨号状态 GS_Call_state = Hk_Camera_Get_Call_Data_State(); //读IMEI号 IMEI[0]=0x31; IMEI[1]=0x39; IMEI[2]=0x30; IMEI[3]=0x38; IMEI[4]=0x30; IMEI[5]=0x35; IMEI[6]=0x31; IMEI[7]=0x34; IMEI[8]= 0; //判定摄像头是否在线 GS_camera_state = Hk_Camera_Get_Camera_State_By_Id(0); romdatasCopeToRamDataS("摄像:", WIFIName_temp);//0~4 if(GS_camera_state == 1 ) {//CURRENT_STATE_NO_CONNECT romdatasCopeToRamDataS("无", WIFIName_temp+5);//5~8 } else if(GS_camera_state == 14 ) {//摄像正常 romdatasCopeToRamDataS("正常", WIFIName_temp+5);//5~8 } else {//没有配置 romdatasCopeToRamDataS("中断", WIFIName_temp+5);//5~8 } //TF卡状态 13 romdatasCopeToRamDataS(";TF:",WIFIName_temp+9);//9~12 if(TFcardState == (-1)) { romdatasCopeToRamDataS(" 无 ",WIFIName_temp+13);//13~16 } else { romdatasCopeToRamDataS("正常",WIFIName_temp+13);//13~16 } //卡状态 romdatasCopeToRamDataS("\n拨号:", WIFIName_temp+17);//17~22 if(GS_Call_state == 0) {//CURRENT_STATE_DATA_CALL_SUCCESS romdatasCopeToRamDataS("正常", WIFIName_temp+23);//23~26 } else if(GS_Call_state == 3) {//CURRENT_STATE_SIM_CARD_ERROR romdatasCopeToRamDataS("SIM", WIFIName_temp+23);//23~26 } else if(GS_Call_state == 5) {//CURRENT_STATE_DATA_CALL_SERVER_ERROR romdatasCopeToRamDataS("失败", WIFIName_temp+23);//23~26 } else if(GS_Call_state == 7) {//CURRENT_STATE_INIT_DATA_CALL_ERROR romdatasCopeToRamDataS("失败", WIFIName_temp+23);//23~26 } else if(GS_Call_state == 9) {//CURRENT_STATE_CANT_GET_DATA_CALL_INFO romdatasCopeToRamDataS("失败", WIFIName_temp+23);//23~26 } else if(GS_Call_state == 10) {//CURRENT_STATE_HAVE_DATA_CALL romdatasCopeToRamDataS("拨号", WIFIName_temp+23);//23~26 } else {//CURRENT_STATE_START_DATA_CALL_ERROR romdatasCopeToRamDataS("失败", WIFIName_temp+23);//23~26 } romdatasCopeToRamDataS("C", WIFIName_temp+27);//27~27 // WIFIName_temp[28] = (startCount%1000)/100+'0'; WIFIName_temp[29] = (startCount%100)/10+'0'; WIFIName_temp[30] = (startCount%10)+'0'; WIFIName_temp[31] = 0; printf("IMEI = %s\n", IMEI); printf("WIFIName_temp = %s\n", WIFIName_temp); printf("信号强度 = %d\n", Signal_Strength_temp); GS_PC_str.SendBufLen =WX_3_SendData(Signal_Strength_temp,IMEI, WIFIName_temp,GS_PC_str.sendBuf); if(GS_PC_str.SendBufLen == 0) { printf("转换数据错误 字节数= 0\n"); usleep(); } else if(GS_PC_str.SendBufLen >500) { printf("转换数据错误 字节数>500\n"); usleep(); } else { printf("转换数据正常 字节数%d\n",GS_PC_str.SendBufLen ); Serial_Send(GS_PC_str.fd, GS_PC_str.sendBuf, GS_PC_str.SendBufLen);//发送数据 usleep(); I_temp = Serial_Receive(GS_PC_str.fd, GS_PC_str.RevBuf, 500);//读接收数据 if(I_temp>0) { printf("主板回应字节数:%d\n",I_temp); } else { printf("主板没有回应\n"); } } //计数 startCount++; if(startCount>999) { startCount=999; } } return 0; }

       因为直接去read串口会出现后面串口堵塞再也不会发生任何数据和接收数据直接堵死。

       修改后如下

int main() { unsigned int i; fd_set fdset; struct timeval timeout = {3, 0}; int iRet; int return_value = 0; unsigned long startCount = 0;//开机计时 重启后30分钟不变化 unsigned char Signal_Strength_temp; unsigned char WIFIName_temp[33]; int TFcardState;//卡状态 int I_temp; GS_PC_str.RevBufLen = 0; //串口初始化  bps,8 N 1 GS_PC_str.fd = Ql_UART_Open("/dev/ttyHS0", , FC_NONE); if(GS_PC_str.fd<0) { printf("serial open fail\n"); return 0; } else { printf("serial open success fd = %d\n",GS_PC_str.fd); } ST_UARTDCB dcb = { .flowctrl = FC_NONE, //none flow control .databit = DB_CS8, //databit: 8 .stopbit = SB_1, //stopbit: 1 .parity = PB_NONE, //parity check: none .baudrate = B_ //baudrate:  }; iRet = Ql_UART_SetDCB(GS_PC_str.fd, &dcb); printf("SET DCB ret: %d\n", iRet); iRet = Ql_UART_GetDCB(GS_PC_str.fd, &dcb); //卡状态 TFcardState = Hk_Camera_Get_SD_State(&GS_TF_state); printf("return_value = %d\n", TFcardState); printf("state->f_blocks = %d\n", GS_TF_state.f_blocks); printf("state->f_bavail = %d\n", GS_TF_state.f_bavail); printf("state->used_percent = %d\n", GS_TF_state.can_used_percent); //配置自己的IP地址 HK_Camera_Init_Internet_Ip("192.168.1.5"); //拨号状态 GS_Call_state = Hk_Camera_Data_Call(); //开启摄像头功能 Hk_Camera_Paramete_Init(); Hk_Camera_Init_Camera("192.168.1.64", 13851, 0, 3);//开启第1(1~4) Hk_Camera_Start_Camera_Communicate(); while(1) { //读取信号强度 GS_Signal_Strength = Hk_Camera_Get_Signal_Strength(); printf("Signal Strength = %d\n", GS_Signal_Strength); if(GS_Signal_Strength>99) { Signal_Strength_temp = 98; } else { Signal_Strength_temp = GS_Signal_Strength; } //拨号状态 GS_Call_state = Hk_Camera_Get_Call_Data_State(); //读IMEI号 IMEI[0]=0x31; IMEI[1]=0x39; IMEI[2]=0x30; IMEI[3]=0x38; IMEI[4]=0x30; IMEI[5]=0x35; IMEI[6]=0x31; IMEI[7]=0x34; IMEI[8]= 0; //判定摄像头是否在线 GS_camera_state = Hk_Camera_Get_Camera_State_By_Id(0); romdatasCopeToRamDataS("摄像:", WIFIName_temp);//0~4 if(GS_camera_state == 1 ) {//CURRENT_STATE_NO_CONNECT romdatasCopeToRamDataS("无", WIFIName_temp+5);//5~8 } else if(GS_camera_state == 14 ) {//摄像正常 romdatasCopeToRamDataS("正常", WIFIName_temp+5);//5~8 } else {//没有配置 romdatasCopeToRamDataS("中断", WIFIName_temp+5);//5~8 } //TF卡状态 13 romdatasCopeToRamDataS(";TF:",WIFIName_temp+9);//9~12 if(TFcardState == (-1)) { romdatasCopeToRamDataS(" 无 ",WIFIName_temp+13);//13~16 } else { romdatasCopeToRamDataS("正常",WIFIName_temp+13);//13~16 } //卡状态 romdatasCopeToRamDataS("\n拨号:", WIFIName_temp+17);//17~22 if(GS_Call_state == 0) {//CURRENT_STATE_DATA_CALL_SUCCESS romdatasCopeToRamDataS("正常", WIFIName_temp+23);//23~26 } else if(GS_Call_state == 3) {//CURRENT_STATE_SIM_CARD_ERROR romdatasCopeToRamDataS("SIM", WIFIName_temp+23);//23~26 } else if(GS_Call_state == 5) {//CURRENT_STATE_DATA_CALL_SERVER_ERROR romdatasCopeToRamDataS("失败", WIFIName_temp+23);//23~26 } else if(GS_Call_state == 7) {//CURRENT_STATE_INIT_DATA_CALL_ERROR romdatasCopeToRamDataS("失败", WIFIName_temp+23);//23~26 } else if(GS_Call_state == 9) {//CURRENT_STATE_CANT_GET_DATA_CALL_INFO romdatasCopeToRamDataS("失败", WIFIName_temp+23);//23~26 } else if(GS_Call_state == 10) {//CURRENT_STATE_HAVE_DATA_CALL romdatasCopeToRamDataS("拨号", WIFIName_temp+23);//23~26 } else {//CURRENT_STATE_START_DATA_CALL_ERROR romdatasCopeToRamDataS("失败", WIFIName_temp+23);//23~26 } romdatasCopeToRamDataS("C", WIFIName_temp+27);//27~27 // WIFIName_temp[28] = (startCount%1000)/100+'0'; WIFIName_temp[29] = (startCount%100)/10+'0'; WIFIName_temp[30] = (startCount%10)+'0'; WIFIName_temp[31] = 0; printf("IMEI = %s\n", IMEI); printf("WIFIName_temp = %s\n", WIFIName_temp); printf("信号强度 = %d\n", Signal_Strength_temp); GS_PC_str.SendBufLen =WX_3_SendData(Signal_Strength_temp,IMEI, WIFIName_temp,GS_PC_str.sendBuf); /*GS_PC_str.SendBufLen = 49; I_temp = Serial_Receive(GS_PC_str.fd, GS_PC_str.RevBuf, 250);//读接收数据 if(I_temp>0) { printf("主板回应字节数:%d\n",I_temp); } else { printf("主板没有回应\n"); } //计数 startCount++; if(startCount>999) { startCount=999; } usleep(); Serial_Send(GS_PC_str.fd, GS_PC_str.sendBuf, GS_PC_str.SendBufLen);//发送数据*/ startCount++; if(startCount>999) { startCount=999; } FD_ZERO(&fdset); FD_SET(GS_PC_str.fd, &fdset); iRet = select(GS_PC_str.fd + 1, &fdset, NULL, NULL, &timeout); if (-1 == iRet) { printf("< failed to select >\n"); exit(-1); } else if (0 == iRet) {// no data in Rx buffer printf("< no data >\n"); timeout.tv_sec = 3; timeout.tv_usec = 0; } else {// data is in Rx data if (FD_ISSET(GS_PC_str.fd, &fdset)) { do { memset(GS_PC_str.RevBuf, 0x0, sizeof(GS_PC_str.RevBuf)); iRet = Ql_UART_Read(GS_PC_str.fd, GS_PC_str.RevBuf, 100); printf("> read(uart)=%d:%s\n", iRet, GS_PC_str.RevBuf); } while (100 == iRet); } } usleep(); iRet = Ql_UART_Write(GS_PC_str.fd, GS_PC_str.sendBuf, GS_PC_str.SendBufLen); printf("< write(fd=%d)=%d\n", GS_PC_str.fd, iRet); } return 0; }

          这样就能很正常的运行,美中不足就是没数据时会"卡"3秒。所以建议使用多线程去写串口

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/216675.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 上午11:19
下一篇 2026年3月18日 上午11:19


相关推荐

  • bootstrapValidator验证表单后清除当次验证的方法

    bootstrapValidator验证表单后清除当次验证的方法用 bootstrapVal 的 resetForm 方法 lt createserver gt lt divclass modalfade id server create server modal tabindex 1 role dialog aria labelledby myModalLabel amp

    2026年3月16日
    2
  • MyEclipse10激活成功教程_MyEclipse激活码

    MyEclipse10激活成功教程_MyEclipse激活码myEclipse10可以去很多地方下载,我这里是从电脑管家下载的,下载完成后安装,安装很简单,不在多说安装完成后会发现你只有一个月的试用时间,我们就需要激活成功教程,这里需要下载一个激活成功教程补丁https://pan.baidu.com/s/1ivE2yauZRDdDq8zBxpK06A可以去网盘里下载,下载后解压,会有如下文件然后运行run.bat,会出现这个界面…

    2022年9月30日
    5
  • linux 编译安装GCC4.9.3(完整版)「建议收藏」

    linux 编译安装GCC4.9.3(完整版)「建议收藏」第一步首先下载gcc源码包wgethttp://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-4.9.3/gcc-4.9.3.tar.bz2第二步将下载好的文件放在非root用户也有读权限的地方,例如/home/myuser或者/usr/gcc-build/下面第四步我会讲为什么要这么做.第三步解压文件,做一些准备工作tar

    2022年5月25日
    37
  • 局域网的dos攻击指定ip_局域网被攻击

    局域网的dos攻击指定ip_局域网被攻击1.确保自己的网卡支持monitor模式https://blog.csdn.net/qq_33826977/article/details/628977182.用mdk3工具实施dos攻击2.1信标洪水攻击:mdk3mon0b-c12.2身份验证洪水攻击mdk3mon0a-a08-57-00-43-1E-B22.3取消身份验证洪水攻击aireplay-ng-o…

    2022年10月1日
    11
  • Lua使用心得(2)

    在lua脚本调用中,如果我们碰到一种不好的脚本,例如:while1dodoend那我们的程序主线程也会被阻塞住。那我们如何防止这种问题呢?下面就给出一个解决的办法。首先为了不阻塞主线程,

    2021年12月25日
    57
  • __builtin_expect详解

    __builtin_expect详解在 GTK 2 0 源码中有很多这样的宏 G LIKELY 和 G UNLIKELY 比如下面这段代码 if G LIKELY acat 1 nbsp nbsp nbsp nbsp allocatethro nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp ThreadMemory tmem thread memory from self nbsp nbsp nbsp nbsp nbsp guintix

    2026年3月18日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号