1. 程式人生 > >【C語言實現串列埠通訊知識點整理(一)】執行緒、開啟串列埠、設定波特率、設定校驗位、互斥鎖等實現基本的通訊

【C語言實現串列埠通訊知識點整理(一)】執行緒、開啟串列埠、設定波特率、設定校驗位、互斥鎖等實現基本的通訊

 

部分程式碼借鑑地址:https://blog.csdn.net/wangqingchuan92/article/details/73497354/ 謝謝!

1.建立執行緒線上程內進行串列埠之間的收發

void CREAT_pthread(void)
{
	pthread_t t0;

	//建立執行緒1
	if(pthread_create(&t0, NULL, print_a, NULL) == -1){
		puts("fail to create pthread t0");
		exit(1);
	}else
		{
			printf("\n\nt0 create success!!!");
		}
}

遇到的問題:在一開始建立執行緒的時候,呼叫了pthread_join()函式,主執行緒需要等子執行緒完成操作後才會執行。由於子執行緒是電視開機後一直在執行,隨時會接收資料傳送資料,因此導致主執行緒沒辦法執行,電視宕機沒辦法正常操作。

    // 等待執行緒結束
    void * result;
    if(pthread_join(t0, &result) == -1){
        puts("fail to recollect t0");
        //exit(1);
    }

    if(pthread_join(t1, &result) == -1){
        puts("fail to recollect t1");
       // exit(1);
    }

2.開啟串列埠

 int OpenDev(char *Dev)
 {
	 int fd = open(Dev,O_RDWR | O_NOCTTY | O_NONBLOCK);
	 if(-1 == fd)
	 {
		 perror("Can't Open Serial Port");
		 return -1;
	 } else 
		 {
			 printf("Open com success!!!!!!!!!!!");
			 return fd;
		 }
 } 

函式原型:int open(constchar*pathname,intflags,mode_tmode);返回值:成功則返回檔案描述符,否則返回-1

對於open函式來說,第三個引數僅當建立新檔案時(即 使用了O_CREAT 時)才使用,用於指定檔案的訪問許可權位(access permission bits)。pathname 是待開啟/建立檔案的POSIX路徑名(如/home/user/a.cpp);flags 用於指定檔案的開啟/建立模式,這個引數可由以下常量(定義於fcntl.h)通過邏輯位或邏輯構成。

O_RDONLY只讀模式    O_WRONLY只寫模式     O_RDWR讀寫模式

開啟/建立檔案時,至少得使用上述三個常量中的一個。以下常量是選用的:

1

2

3

4

5

6

O_APPEND每次寫操作都寫入檔案的末尾

O_CREAT如果指定檔案不存在,則建立這個檔案

O_EXCL如果要建立的檔案已存在,則返回-1,並且修改errno的值

O_TRUNC如果檔案存在,並且以只寫/讀寫方式開啟,則清空檔案全部內容(即將其長度截短為0)

O_NOCTTY如果路徑名指向終端裝置,不要把這個裝置用作控制終端。

O_NONBLOCK如果路徑名指向FIFO/塊檔案/字元檔案,則把檔案的開啟和後繼I/O

3.設定波特率

unsigned int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, };
unsigned int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, };

void set_speed(int fd, unsigned int speed)
{ 
	unsigned int i; 
	int status; 
	struct termios Opt;
	tcgetattr(fd, &Opt); 
	for ( i= 0; i < sizeof(speed_arr) /sizeof(int); i++)
	{ 
  		if (speed == name_arr[i]) 
		{ 
			tcflush(fd, TCIOFLUSH); 
			cfsetispeed(&Opt, speed_arr[i]);
			cfsetospeed(&Opt, speed_arr[i]);
			status = tcsetattr(fd, TCSANOW, &Opt); 
			if (status != 0) perror("tcsetattr fd1");
			return;
		} 
	tcflush(fd,TCIOFLUSH);
	}
}

4.設定校驗位()

int set_Parity(int fd,int databits,int stopbits,int parity) 
{ 
	struct termios options; 
	if ( tcgetattr( fd,&options) != 0) 
	{
		perror("SetupSerial 1");
		return 0;
	} 
	bzero(&options,sizeof(options)); 
	options.c_cflag |= CLOCAL | CREAD;
	options.c_cflag &= ~CSIZE; 
	switch (databits) 
	{ 
		case 7: 
			options.c_cflag |= CS7;
			break;
		case 8:
			options.c_cflag |= CS8;
			break; 
		default: fprintf(stderr,"Unsupported data size\n");
		return 0; 
	} 
	switch (parity) 
	{
		case 'n': 
		case 'N':
			options.c_cflag &= ~PARENB;
			options.c_iflag &= ~INPCK; 
			break; 
		case 'o':
		case 'O': 
			options.c_cflag |= (PARODD | PARENB);
			options.c_iflag |= (INPCK | ISTRIP); 
			break; 
		case 'e': 
		case 'E': 
			options.c_cflag |= PARENB;
			options.c_cflag &= ~PARODD; 
			options.c_iflag |= (INPCK | ISTRIP); 
			break; 
		case 'S': 
		case 's': 
			options.c_cflag &= ~PARENB; 
			options.c_cflag &= ~CSTOPB;
			break;
		default: fprintf(stderr,"Unsupported parity\n"); 
		return 0; 
	} 
	switch (stopbits)
	{ 
		case 1:
			options.c_cflag &= ~CSTOPB; 
			break; 
		case 2: 
			options.c_cflag |= CSTOPB;
			break; 
		default: fprintf(stderr,"Unsupported stop bits\n"); 
		return 0; 
	} 
	if (parity != 'n') 
	{
		options.c_iflag |= INPCK; 
		options.c_cc[VTIME] = 0;
		options.c_cc[VMIN] = 0;
		tcflush(fd,TCIFLUSH); 
	}
	if (tcsetattr(fd,TCSANOW,&options) != 0)
	{  
		perror("SetupSerial 3"); 
		return 0;
	} 
	return 0;
}

5.讀寫加異常判斷以及加鎖

            pthread_mutex_lock(&mutex_r);
			memset(buff,0,30);
			nread = read(fd,buff,sizeof(buff));
			pthread_mutex_unlock(&mutex_r);     //返回讀到的位元組數
------------------------------------------------------------------------------
			pthread_mutex_lock(&mutex_w);
            if((flag=write(fd,string,len)) != len)
			{
				printf("write error!!!\n");	
			}
			pthread_mutex_unlock(&mutex_w);     // //返回寫入的的位元組數
------------------------------------------------------------------------------

當pthread_mutex_lock()返回時,該互斥鎖已被鎖定。執行緒呼叫該函式讓互斥鎖上鎖,如果該互斥鎖已被另一個執行緒鎖定和擁有,則呼叫該執行緒將阻塞,直到該互斥鎖變為可用為止。 

互斥鎖提供一個可以在同一時間,只讓一個執行緒訪問臨界資源的的操作介面。互斥鎖(Mutex)是個提供執行緒同步的基本鎖。讓上鎖後,其他的執行緒如果想要鎖上,那麼會被阻塞,直到鎖釋放後(說明,一般會把訪問共享記憶體這段程式碼放在上鎖程式之後。)。

如果,在鎖釋放後,有多個執行緒被阻塞,那麼,所有的被阻塞的執行緒會被設為可執行狀態。第一個執行的執行緒,取得鎖的控制權,上鎖。其他的執行緒繼續阻塞。