【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)是个提供线程同步的基本锁。让上锁后,其他的线程如果想要锁上,那么会被阻塞,直到锁释放后(说明,一般会把访问共享内存这段代码放在上锁程序之后。)。

如果,在锁释放后,有多个线程被阻塞,那么,所有的被阻塞的线程会被设为可执行状态。第一个执行的线程,取得锁的控制权,上锁。其他的线程继续阻塞。

猜你喜欢

转载自blog.csdn.net/Beyond_1024/article/details/81624523
今日推荐