1. 程式人生 > >解決Linux串列埠查詢一次只能返回8位的問題

解決Linux串列埠查詢一次只能返回8位的問題

問題描述:

專案中有定時查詢感測器並將查詢到的資料記錄下來的需要,在做的時候發現通過whlie迴圈配合select監測串列埠上的資料,然後將資料儲存在陣列的過程中,read函式的第三個引數即選擇讀取的位元組數,在大於8的情況下返回的個數仍然為8,而感測器返回的資料包一般都是十幾位,無法一次性返回,就需要記錄好幾次。更為嚴重的是,如果資料包的位元組數大於16的情況下,第二次返回8個位元組的同時,會將第一次的返回的8個位元組覆蓋掉,從而導致記錄的資料不完整。

解決思路:

串列埠每次查詢只能返回8位受制於緩衝的大小,一般情況下無法改變,那麼應該著手通過對返回的資料包進行處理,不要每次返回都進行記錄,而是在一次資料包返回完整之後,再將它傳遞給用於儲存的陣列進行記錄。
程式修改前如下:


int receive(char *str , unsigned int length)

{     	
	fd_set fs_read;
	struct timeval time;
	FD_ZERO(&fs_read);
	FD_SET(fd,&fs_read);
	time.tv_sec=0;
	time.tv_usec=0;
 	unsigned int i_counter=0;
	int len=0;     

      while(select(fd+1,&fs_read,NULL,NULL,&time) > 0 )
      {
		if((len=read(fd,str,128))<0)
			{
			perror("read");
			return -1;
			}

              else{ 
 		i_counter+= len;
		 }

       }
       return i_counter;

}

上述程式碼中的str會傳遞到另外一個記錄資料包的函式裡面,本來以為將read的第三個引數設為128就可以完全滿足需要,返回全部的資料長度,但是實際上一次最多隻能返回8位,如果總的位元組數大於16位,還會將前面的資料重新整理掉,而只能夠記錄到最後小於16個位元組的包。
程式修改後如下:

unsigned int i_counter=0;
int receive (char *str,unsigned int length)
{
	int len=0;
	unsigned char str_house[2056]={0};
	fd_set fs_read;
	struct timeval time;
	FD_ZERO(&fs_read);
	FD_SET(fd,&fs_read);
	time.tv_sec=0;
	time.tv_usec=0;
	int j_count=0;
	while(select(fd+1,&fs_read,NULL,NULL,&time)>0){
		if((len=read(fd,str_house,8))<0)
		{
			perror("read");
			return -1;
		}
		else{
			i_counter+=len;
			if(i_counter>length)
			{
				i_counter=8;
			}
			printf("len is %d counter is %d\n",len,i_counter);
			if(len==8)
			{
				for(j_count=0;j_count<8;j_count++)
				{
					str[i_counter-8+j_count]=str_house[j_count];
				}
			}
			else if(len<8)
			{
				for(j_count=0;j_count<len;j_count++)
				{
					str[i_counter-len+j_count]=str_house[j_count];
				}
			}
		}
	}
	return i_counter;
}


上述程式中,i_counter用來記錄當前已經收到的資料包中元素的個數,如果放在函式內部的話,每次呼叫該函式來查詢,該值都會被初始化為零,起不到計數的作用,所以應該作為全域性變數,但是當它計數超過我們本次查詢返回位元組的最大值之後,會被清零,否則會一直無限增長下去,然後就可以建立一個暫時存放資料包的倉庫,即陣列str_house,每次讀八位並記錄,直到它讀到的位元組大於零且小於八,說明它返回的是最後幾個位元組,這幾個位元組存完之後,這一條查詢指令所返回的資料包就全部存放到str_house這個數組裡了,該陣列通過被其他寫函式呼叫,就可以存放到SD卡或者SATA硬碟等儲存裝置,從而解決Linux下串列埠查詢一次只能返回8位的情況。