今天我们郭工使用我写的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;
//串口初始化 115200 bps,8 N 1
GS_PC_str.fd = Serial_Open("/dev/ttyHS0", B115200, 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
//123456
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(1000000);
}
else if(GS_PC_str.SendBufLen >500)
{
printf("转换数据错误 字节数>500\n");
usleep(1000000);
}
else
{
printf("转换数据正常 字节数%d\n",GS_PC_str.SendBufLen );
Serial_Send(GS_PC_str.fd, GS_PC_str.sendBuf, GS_PC_str.SendBufLen);//发送数据
usleep(1000000);
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;
//串口初始化 115200 bps,8 N 1
GS_PC_str.fd = Ql_UART_Open("/dev/ttyHS0", 115200, 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_115200 //baudrate: 115200
};
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
//123456
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(1000000);
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(1000000);
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秒。所以建议使用多线程去写串口
今天的文章移远EC20串口使用阻塞问题分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/6588.html