⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial.c

📁 采用MINIGUI开发的一套GUI界面
💻 C
字号:
#include <stdio.h>              /*printf*/ 
#include <fcntl.h>              /* open  */ 
#include <string.h>             /* bzero */ 
#include <stdlib.h>             /*exit   */ 
#include <sys/times.h>          /* times*/ 
#include <sys/types.h>          /* pid_t*/ 
#include <termios.h>        /*termios, tcgetattr(), tcsetattr()*/ 
#include <unistd.h> 
#include <sys/ioctl.h>          /* ioctl*/


#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
#include <minigui/control.h>


#include <signal.h>     //异步通讯信号处理

#include     <pthread.h>
#include     "common.h"
#include     "meter.h"
#include     "serial.h"




#define    TTY_DEV     "/dev/ttyS"       /*端口路径*/ 
#define TIMEOUT_SEC(buflen,baud)  (buflen*20/baud+2)  /*接收超时*/ 
#define TIMEOUT_USEC  0 
/******************************************* 
 *    获得端口名称 
********************************************/ 
unsigned char *get_ptty(pportinfo_t pportinfo) 
{ 
    unsigned char *ptty; 
 
    switch(pportinfo->tty){ 
        case '0':{ 
            ptty = TTY_DEV"0"; 
        }break; 
        case '1':{ 
            ptty = TTY_DEV"1"; 
        }break; 
        case '2':{ 
            ptty = TTY_DEV"2"; 
        }break; 
    } 
    return(ptty); 
} 
 
/******************************************* 
 *    波特率转换函数(请确认是否正确) 
********************************************/ 
int convbaud(unsigned long int baudrate) 
{ 
    switch(baudrate){ 
        case 2400: 
            return B2400; 
        case 4800: 
            return B4800; 
        case 9600: 
            return B9600; 
        case 19200: 
            return B19200; 
        case 38400: 
            return B38400; 
        case 57600: 
            return B57600; 
        case 115200: 
            return B115200; 
        default: 
            return B9600; 
    } 
} 



void signal_handler_IO (int status) 
{	  
 //printf("signal_handler_IO \n");  
wait_flag=0;
    
}

 
/******************************************* 
 *    Setup comm attr 
 *    fdcom: 串口文件描述符,pportinfo: 待设置的端口信息(请确认) 
 * 
********************************************/ 
int PortSet_normal(int fdcom, const pportinfo_t pportinfo) 
{ 
    struct termios termios_old, termios_new; 
    int     baudrate, tmp; 
    unsigned char    databit, stopbit, parity, fctl; 
 
    bzero(&termios_old, sizeof(termios_old)); 
    bzero(&termios_new, sizeof(termios_new)); 
    cfmakeraw(&termios_new); 
   tcgetattr(fdcom, &termios_old);            /*get the serial port attributions*/ 
    /*------------设置端口属性----------------*/ 
    /*baudrates*/ 
    baudrate = convbaud(pportinfo -> baudrate); 
    cfsetispeed(&termios_new, baudrate);        /*填入串口输入端的波特率*/ 
    cfsetospeed(&termios_new, baudrate);        /*填入串口输出端的波特率*/ 
    termios_new.c_cflag |= CLOCAL;            /*控制模式,保证程序不会成为端口的占有者*/ 
    termios_new.c_cflag |= CREAD;            /*控制模式,使能端口读取输入的数据*/ 
 
    /* 控制模式,flow control*/ 
    fctl = pportinfo-> fctl; 
    switch(fctl){ 
        case '0':{ 
            termios_new.c_cflag &= ~CRTSCTS;        /*no flow control*/ 
        }break; 
        case '1':{ 
            termios_new.c_cflag |= CRTSCTS;            /*hardware flow control*/ 
        }break; 
        case '2':{ 
            termios_new.c_iflag |= IXON | IXOFF |IXANY;    /*software flow control*/ 
        }break; 
    } 
 
    /*控制模式,data bits*/ 
    termios_new.c_cflag &= ~CSIZE;        /*控制模式,屏蔽字符大小位*/ 
    databit = pportinfo -> databit; 
    switch(databit){ 
        case '5': 
            termios_new.c_cflag |= CS5; 
        case '6': 
            termios_new.c_cflag |= CS6; 
        case '7': 
            termios_new.c_cflag |= CS7; 
        default: 
            termios_new.c_cflag |= CS8; 
    } 
 
    /*控制模式 parity check*/ 
    parity = pportinfo -> parity; 
    switch(parity){ 
        case '0':{ 
            termios_new.c_cflag &= ~PARENB;        /*no parity check*/ 
        }break; 
        case '1':{ 
            termios_new.c_cflag |= PARENB;        /*odd check*/ 
            termios_new.c_cflag &= ~PARODD; 
        }break; 
        case '2':{ 
            termios_new.c_cflag |= PARENB;        /*even check*/ 
            termios_new.c_cflag |= PARODD; 
        }break; 
    } 
 
    /*控制模式,stop bits*/ 
    stopbit = pportinfo -> stopbit; 
    if(stopbit == '2'){ 
        termios_new.c_cflag |= CSTOPB;    /*2 stop bits*/ 
    } 
    else{ 
        termios_new.c_cflag &= ~CSTOPB;    /*1 stop bits*/ 
    } 
 
    /*other attributions default*/ 
    termios_new.c_oflag &= ~OPOST;            /*输出模式,原始数据输出*/ 
    termios_new.c_cc[VMIN]  = 1;            /*控制字符, 所要读取字符的最小数量*/ 
    termios_new.c_cc[VTIME] = 2;        /*控制字符, 读取第一个字符的等待时间    unit: (1/10)second*/ 
    tcflush(fdcom, TCIFLUSH);                /*溢出的数据可以接收,但不读*/ 
    tmp = tcsetattr(fdcom, TCSANOW, &termios_new);    /*设置新属性,TCSANOW:所有改变立即生效*/    
 	tcgetattr(fdcom, &termios_old); 
    return(tmp); 
} 

void set_speed( int speed){
	int   i; 
	int fd;
	int   status; 
	struct termios   Opt;
int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300,
		B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400,  19200,  9600,  4800,  2400,  1200,  300, 38400,  
			19200,  9600, 4800, 2400, 1200,  300, };	
	fd=Commfd2;
	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 fd");  
				return;     
			}    
			tcflush(fd,TCIOFLUSH);   
		}  
	}
}
 int  SetBourate(int baudrate )
{
set_speed(baudrate);
/*
int tmp;
   struct termios termios_old2, termios_new2; 
 int fd;
 fd=Commfd2;
    bzero(&termios_old2, sizeof(termios_old2)); 
    bzero(&termios_new2, sizeof(termios_new2)); 
    cfmakeraw(&termios_new2); 
	
    tcgetattr(fd, &termios_old2);  
	termios_new2=termios_old2;
	  baudrate = convbaud(  baudrate); 
    cfsetispeed(&termios_new2, baudrate);  
    cfsetospeed(&termios_new2, baudrate);   
tcflush(fd, TCIFLUSH);   
  tmp =  tcsetattr(fd, TCSANOW, &termios_new2);  //设定新 波特率
 return(tmp); 
 */
}

/******************************************* 
 *    Setup comm attr 
 *    fdcom: 串口文件描述符,pportinfo: 待设置的端口信息(请确认) 
 * 
********************************************/ 
int PortSet(int fdcom, const pportinfo_t pportinfo) 
{ 
    struct termios termios_old, termios_new; 
    int     baudrate, tmp; 
    unsigned char    databit, stopbit, parity, fctl; 
     struct sigaction saio; 
    wait_flag = 1;

    bzero(&termios_old, sizeof(termios_old)); 
    bzero(&termios_new, sizeof(termios_new)); 
    cfmakeraw(&termios_new); 
    tcgetattr(fdcom, &termios_old);            /*get the serial port attributions*/ 
    /*------------设置端口属性----------------*/ 
    /*baudrates*/ 
    baudrate = convbaud(pportinfo -> baudrate); 
    cfsetispeed(&termios_new, baudrate);        /*填入串口输入端的波特率*/ 
    cfsetospeed(&termios_new, baudrate);        /*填入串口输出端的波特率*/ 
    termios_new.c_cflag |= CLOCAL;            /*控制模式,保证程序不会成为端口的占有者*/ 
    termios_new.c_cflag |= CREAD;            /*控制模式,使能端口读取输入的数据*/ 
 
    /* 控制模式,flow control*/ 
    fctl = pportinfo-> fctl; 
    switch(fctl){ 
        case '0':{ 
            termios_new.c_cflag &= ~CRTSCTS;        /*no flow control*/ 
        }break; 
        case '1':{ 
            termios_new.c_cflag |= CRTSCTS;            /*hardware flow control*/ 
        }break; 
        case '2':{ 
            termios_new.c_iflag |= IXON | IXOFF |IXANY;    /*software flow control*/ 
        }break; 
    } 
 
    /*控制模式,data bits*/ 
    termios_new.c_cflag &= ~CSIZE;        /*控制模式,屏蔽字符大小位*/ 
    databit = pportinfo -> databit; 
    switch(databit){ 
        case '5': 
            termios_new.c_cflag |= CS5; 
        case '6': 
            termios_new.c_cflag |= CS6; 
        case '7': 
            termios_new.c_cflag |= CS7; 
        default: 
            termios_new.c_cflag |= CS8; 
    } 
 
    /*控制模式 parity check*/ 
    parity = pportinfo -> parity; 
    switch(parity){ 
        case '0':{ 
            termios_new.c_cflag &= ~PARENB;        /*no parity check*/ 
        }break; 
        case '1':{ 
            termios_new.c_cflag |= PARENB;        /*odd check*/ 
            termios_new.c_cflag &= ~PARODD; 
        }break; 
        case '2':{ 
            termios_new.c_cflag |= PARENB;        /*even check*/ 
            termios_new.c_cflag |= PARODD; 
        }break; 
    } 





	
  //install the signal handler before making the device asynchronous 
    // 在进行设备异步传输前,安装信号处理程序    
    saio.sa_handler = signal_handler_IO;     
   // saio.sa_mask = 0;  
    saio.sa_flags = 0;     
    saio.sa_restorer = NULL;    
    sigaction(SIGIO,&saio,NULL);   

 // allow the process to receive SIGIO   
 // 允许进程接收 SIGIO 信号      
    fcntl(fdcom, F_SETOWN, getpid());    
    // Make the file descriptor asynchronous (the manual page says only  
 //O_APPEND and O_NONBLOCK, will work with F_SETFL...)    
 // 设置串口的文件描述符为异步,man上说,只有 O_APPEND 和 O_NONBLOCK 才能使用F_SETFL
  fcntl(fdcom, F_SETFL, FASYNC);    






	
    /*控制模式,stop bits*/ 
    stopbit = pportinfo -> stopbit; 
    if(stopbit == '2'){ 
        termios_new.c_cflag |= CSTOPB;    /*2 stop bits*/ 
    } 
    else{ 
        termios_new.c_cflag &= ~CSTOPB;    /*1 stop bits*/ 
    } 
 
    /*other attributions default*/ 
    termios_new.c_oflag &= ~OPOST;            /*输出模式,原始数据输出*/ 
    termios_new.c_cc[VMIN]  = 2;            /*控制字符, 所要读取字符的最小数量*/ 
    termios_new.c_cc[VTIME] = 1;        /*控制字符, 读取第一个字符的等待时间    unit: (1/10)second*/ 
 
    tcflush(fdcom, TCIFLUSH);                /*溢出的数据可以接收,但不读*/ 
    tmp = tcsetattr(fdcom, TCSANOW, &termios_new);    /*设置新属性,TCSANOW:所有改变立即生效*/    tcgetattr(fdcom, &termios_old); 
    return(tmp); 
} 
 
/******************************************* 
 *    Open serial port 
 *    tty: 端口号 ttyS0, ttyS1, .... 
 *    返回值为串口文件描述符 
********************************************/ 
int PortOpen(pportinfo_t pportinfo) 
{ 
    int fdcom;    /*串口文件描述符*/ 
    unsigned char *ptty; 
 
    ptty = get_ptty(pportinfo); 
	printf("%s\n",ptty);
    /*fdcom = open(ptty, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY);*/ 
    fdcom = open(ptty, O_RDWR | O_NOCTTY | O_NONBLOCK); 
  
    return (fdcom); 
} 
 
/******************************************* 
 *    Close serial port 
********************************************/ 
void PortClose(int fdcom) 
{ 
    close(fdcom); 
} 
 
/******************************************** 
 *    send data 
 *    fdcom: 串口描述符,data: 待发送数据,datalen: 数据长度 
 *    返回实际发送长度 
*********************************************/ 
int PortSend(int fdcom, unsigned char *data, int datalen) 
{ 
    int len = 0; 
 
    len = write(fdcom, data, datalen);    /*实际写入的长度*/ 
    if(len == datalen){ 
        return (len); 
    } 
    else{ 
        tcflush(fdcom, TCOFLUSH); 
        return -1; 
    } 
} 
 
/******************************************* 
 *    receive data 
 *    返回实际读入的字节数 
 * 
********************************************/ 
int PortRecv(int fdcom, unsigned char *data, int datalen, int baudrate) 
{ 
      
    int readlen, fs_sel; 
    fd_set    fs_read; 
    struct timeval tv_timeout;  
    int bytes; 

    FD_ZERO(&fs_read); 
    FD_SET(fdcom, &fs_read); 
    tv_timeout.tv_sec = 0;//TIMEOUT_SEC(datalen, baudrate); 
    tv_timeout.tv_usec =2;//TIMEOUT_USEC;  
    //printf("TIMEOUT_USEC=%d\n",TIMEOUT_USEC);
	// printf("TIMEOUT_SEC(datalen, baudrate)=%d\n",TIMEOUT_SEC(datalen, baudrate));
    fs_sel = select(fdcom+1, &fs_read,NULL, NULL, &tv_timeout); 
    if(fs_sel){
       // ioctl(fdcom, FIONREAD, &bytes);  
	  //printf( "bytes can read:%d\n",bytes);
        readlen = read(fdcom, data, datalen); 
        return(readlen); 
    } 
    else{ 
        return(-1); 
    } 
 
    return (readlen); 
} 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -