今天我们郭工使用我写的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
