嵌入式linux串口通讯 阻塞 非阻塞

参考 

(128条消息) linux下串口的阻塞和非阻塞操作_wuhengwudi的博客-CSDN博客_linux 阻塞 非阻塞

稍作修改  阻塞  非阻塞

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <asm/ioctls.h>
#include <termios.h>
#include <sys/stat.h>
#include <limits.h>

//编译 aarch64-linux-gnu-gcc -o t02_testserialRW testrw.c 

#define CSCS "AT+CSCS=\"GSM\"\r\n"

#define BUFFER_SIZE 4096
char buff[BUFFER_SIZE];


static int setNewtio(int fd, int nSpeed, int nBits, char nEvent, float nStop)   
{   
    struct termios newtio;   
    struct termios oldtio;   
       
    if(tcgetattr(fd,&oldtio) != 0)   
    {   
        perror("SetupSerial 1");   
        return -1;   
    }   
       
    bzero(&newtio,sizeof(newtio));   
    newtio.c_cflag |= CLOCAL |CREAD;   //CLOCAL--忽略 modem 控制线,本地连线, 不具数据机控制功能, CREAD--使能接收标志 
	
	/***********数据位选择****************/    
    newtio.c_cflag &= ~CSIZE;   
	switch(nBits)   
    {   
        case 8:
			newtio.c_cflag |= CS8;
		break;
		case 7:
			newtio.c_cflag |= CS7;
		break;
		case 6:
			newtio.c_cflag |= CS6;
		break;
		case 5:
			newtio.c_cflag |= CS5;
		break;
		default:
			newtio.c_cflag |= CS8;
		break;     
    }   
	/***********校验位选择****************/  
    switch(nEvent)   
    {   
        case 'N':                              /* 无校验          */
		case 'n':
			newtio.c_cflag &= ~PARENB;
			break;
		case 'E':                              /* 偶校验          */
		case 'e':
			newtio.c_cflag |= PARENB;
			newtio.c_cflag &= ~PARODD;
			break;
		case 'O':                              /* 奇校验           */
		case 'o':
			newtio.c_cflag |= PARENB;
			newtio.c_cflag |= ~PARODD;
			break;
		case 'S':
		case 's':
			newtio.c_cflag &= ~PARENB;        /*清除校验位   disable pairty checking Space校验  */
			newtio.c_cflag &= ~CSTOPB;        
			newtio.c_iflag |= INPCK;   
			break;
		default:                               /* 其它选择为无校验 */
			newtio.c_cflag &= ~PARENB;
	}
/***********波特率选择****************/   
    switch(nSpeed)   
    {   
        case 2400:   
			cfsetispeed(&newtio,B2400);   
			cfsetospeed(&newtio,B2400);   
        	break;   
		case 4800:   
			cfsetispeed(&newtio,B4800);   
			cfsetospeed(&newtio,B4800);   
        	break;   
    	case 9600:   
			cfsetispeed(&newtio,B9600);   
			cfsetospeed(&newtio,B9600);   
        	break; 
    	case 57600:   
			cfsetispeed(&newtio,B57600);   
			cfsetospeed(&newtio,B57600);   
        	break;   
    	case 115200:   
			cfsetispeed(&newtio,B115200);   
			cfsetospeed(&newtio,B115200);   
        	break;   
     	case 460800:   
			cfsetispeed(&newtio,B460800);   
			cfsetospeed(&newtio,B460800);   
        	break;             
    	default:   
			cfsetispeed(&newtio,B9600);   
			cfsetospeed(&newtio,B9600);   
			break;   
    }   
	/***********停止位选择****************/ 
	int	_nStop = (int)(nStop*10);
	switch(_nStop)   
    {
		case 10:   
			newtio.c_cflag &= ~CSTOPB;     
        	break;  		
		case 15:   
			newtio.c_cflag &= ~CSTOPB;     
        	break; 		
		case 20:   
			newtio.c_cflag |= CSTOPB;    
        	break;             
    	default:   
			newtio.c_cflag &= ~CSTOPB;  
			break;   
	}
	
    
	/*
	//其他参数
	newtio.c_cflag &= ~CRTSCTS;   // 不使用硬件流控制
    // IXON--启用输出的 XON/XOFF 流控制
    // IXOFF--启用输入的 XON/XOFF 流控制
    // IXANY--允许任何字符来重新开始输出
    // IGNCR--忽略输入中的回车
    newtio.c_iflag &= ~(IXON | IXOFF | IXANY);
    newtio.c_oflag &= ~OPOST; //启用输出处理
    
    // ICANON--启用标准模式 (canonical mode)。允许使用特殊字符 EOF, EOL,
        // EOL2, ERASE, KILL, LNEXT, REPRINT, STATUS, 和 WERASE,以及按行的缓冲。
    // ECHO--回显输入字符
    // ECHOE--如果同时设置了 ICANON,字符 ERASE 擦除前一个输入字符,WERASE 擦除前一个词
    // ISIG--当接受到字符 INTR, QUIT, SUSP, 或 DSUSP 时,产生相应的信号
    newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 
	*/
	
    newtio.c_cc[VTIME] = 1;   
    newtio.c_cc[VMIN] = 255;   //阻塞条件下有效
	
  
    tcflush(fd,TCIFLUSH);   
    if((tcsetattr(fd,TCSANOW,&newtio)) != 0)   
    {   
        perror("com set error");   
        return -1;   
    }   
    printf("set done!\n");   
    return 0;   
}   

int main (int argc,char **argv)
{
	printf("serial test version:0.0.17  [%s %s]\n", __DATE__, __TIME__);

	int fd;             //串口返回值
	int len;        	//串口收发数据

	//初始化串口
	fd = open("/dev/ttySAC5",O_RDWR|O_NOCTTY|O_NDELAY);//非阻塞 O_RDWR|O_NOCTTY|O_NDELAY
	if(fd<0){
		printf("open port device error\n");
		return -1;
	}
	

    if(setNewtio(fd,115200,8,'N',1) < 0) 
    {
      printf("set uart1 arrt faile \n");
      exit(-1);
    }
	
	if(argc>1){
		if(fcntl(fd,F_SETFL,FNDELAY) < 0){ //非阻塞,覆盖前面open的属性   
			printf("fcntl failed\n");   
		}
		printf("set no block\n");
	}
	else{//默认阻塞
		if(fcntl(fd,F_SETFL,0) < 0){   //阻塞,即使前面在open串口设备时设置的是非阻塞的,这里设为阻塞后,以此为准
			printf("fcntl failed\n");   
		} 
		printf("set block\n");
	}
   
	
	

	len = write(fd,CSCS,sizeof(CSCS));
	printf(CSCS);
	if(len<0){
		printf("write cscs erro\n");
		return -1;
    }
	
	do
	{
		if(argc<=1)printf("TEST BLOCK\n");
		memset(buff, 0, BUFFER_SIZE);
		if (read(fd, buff, BUFFER_SIZE) > 0)
		{
			printf("buff:%s\n", buff);
			len = write(fd,CSCS,sizeof(CSCS));
			if(len<0){
				printf("write buff error\n");
				return -1;
			}
		}
	} while(strncmp(buff, "quit", 4));
	printf("close\n");
	close(fd);
	return 0;

}

  

 

 

 

//

posted @ 2022-08-09 16:55  小城熊儿  阅读(570)  评论(0编辑  收藏  举报