Ejemplo de lectura y escritura del puerto serie de Linux

#include <sys/types.h>
 
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>


// rcp uart [email protected]:/usr/



#define BAUDRATE        B115200
#define UART_DEVICE     "/dev/ttyS1"
 
#define FALSE  -1
#define TRUE   0



/**
*@brief  设置串口通信速率
*@param  fd     类型 int  打开串口的文件句柄
*@param  speed  类型 int  串口速度
*@return  void
*/
const int speed_arr[] = {
    
    B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300,
          		   B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300, };
const int name_arr[] = {
    
    115200, 38400, 19200, 9600, 4800, 2400, 1200,  300, 
		  		  115200, 38400, 19200, 9600, 4800, 2400, 1200,  300, };

void set_speed(int fd, int speed)
{
    
    
  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);   
    }  
  }
}

/**
*@brief   设置串口数据位,停止位和效验位
*@param  fd     类型  int  打开的串口文件句柄
*@param  databits 类型  int 数据位   取值 为 7 或者8
*@param  stopbits 类型  int 停止位   取值为 1 或者2
*@param  parity  类型  int  效验类型 取值为N,E,O,,S
*/
int set_parity(int fd,int databits,int stopbits,int parity)
{
    
     
	struct termios options; 
	if  ( tcgetattr( fd,&options)  !=  0) {
    
     
		perror("SetupSerial 1");     
		return(FALSE);  
	}
    

	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 (FALSE);  
	}
	switch (parity) 
	{
    
       
		case 'n':
		case 'N':    
			options.c_cflag &= ~PARENB;   /* Clear parity enable */
			options.c_iflag &= ~INPCK;     /* Enable parity checking */ 
			break;  
		case 'o':   
		case 'O':     
			options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/  
			options.c_iflag |= INPCK;             /* Disnable parity checking */ 
			break;  
		case 'e':  
		case 'E':   
			options.c_cflag |= PARENB;     /* Enable parity */    
			options.c_cflag &= ~PARODD;   /* 转换为偶效验*/     
			options.c_iflag |= INPCK;       /* Disnable parity checking */
			break;
		case 'S': 
		case 's':  /*as no parity*/   
			options.c_cflag &= ~PARENB;
			options.c_cflag &= ~CSTOPB;break;  
		default:   
			fprintf(stderr,"Unsupported parity\n");    
			return (FALSE);  
		}  
	/* 设置停止位*/  
	switch (stopbits)
	{
    
       
		case 1:    
			options.c_cflag &= ~CSTOPB;  
			break;  
		case 2:    
			options.c_cflag |= CSTOPB;  
		   break;
		default:    
			 fprintf(stderr,"Unsupported stop bits\n");  
			 return (FALSE); 
	} 
	/* Set input parity option */ 
	if (parity != 'n')   
		options.c_iflag |= INPCK; 
	tcflush(fd,TCIFLUSH);

    //时间控制,原始模式有效
	options.c_cc[VTIME] = 10*10; /* 设置超时10 seconds(单位1/10s 100ms)*/   
	options.c_cc[VMIN] = 0; 

//     options.c_cc[VMIN] = FRAME_MAXSIZE;   //阻塞条件下有效
    //如果不是开发终端之类的,只是串口传输数据,而不需要串口来处理,那么使用原始模式(Raw Mode)方式来通讯,~ICANON设置串口为原始模式,设置方式如下:
    options.c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG);  /*Input*/
    options.c_oflag  &= ~OPOST;   /*Output*/

    /* Update the options and do it NOW */
	if (tcsetattr(fd,TCSANOW,&options) != 0)   
	{
    
     
		perror("SetupSerial 3");   
		return (FALSE);  
	} 

	return (TRUE);  
}

// int main(int argc, char *argv[])
void *uart_thread(void *arg)
{
    
    
 
    int   fd, c=0, res;
 
    char  buf[1024];
 
    printf("uart Start...\n");
    fd = open(UART_DEVICE, O_RDWR|O_NOCTTY/*|O_NDELAY*/);
 
    if (fd < 0) {
    
    
        perror(UART_DEVICE);
        exit(1);
    }
 
    printf("uart Open...\n");
    set_speed(fd,115200);
	if (set_parity(fd,8,1,'N') == FALSE)  {
    
    
		printf("Set Parity Error\n");
		exit (0);
	}
    
    printf("uart Reading...\n");
    while(1) {
    
    
        //读数据
        res = read(fd, buf, 255);         

        if(res==0)
            continue;

        printf("read=%d\n", res);

        buf[res]=0;
        printf("%s", buf);
        
        //写数据
        res = write(fd, buf, strlen(buf));
        printf("write=%d\n\n",strlen(buf));
        
        //退出
        if (buf[0] == '#') break;
    }
 
    printf("uart Close...\n");
    close(fd);
 
    return 0;
}

int main(int argc, char *argv[])
{
    
    
    int res;
    pthread_t thread1;
    res = pthread_create(&thread1, NULL, uart_thread, NULL);
    if(res != 0) {
    
    
        printf("create uart_thread thread fail\n");
        exit(res);
    }

    while (1) {
    
    
        sleep(100);
    }
    return 0;
}

Si el paquete de datos es largo, los datos leídos serán interceptados. Se puede procesar de la siguiente manera y leer varias veces. Con el modo sin bloqueo, se puede lograr una lectura rápida y eficiente

        pos=0;
        do{
    
    
            usleep(2000);
//             printf("\tpos=%d\n", pos);
            res = read(fd, buf+pos, 255);         
            pos += res;
//             printf("\tsingle read=%d\n", res);
            
        }while(res);

Solo este registro

Supongo que te gusta

Origin blog.csdn.net/pyt1234567890/article/details/107726427
Recomendado
Clasificación