linux 下串口通信程序(转载)

现在正在做有关linux下串口通信的工作,在网上找到一篇文章关心com通信的,所以先记下来,看着比较靠谱,随后再试试.


转载地址:https://www.cnblogs.com/yklevy/articles/6494726.html


/*本程序符合GPL条约  
MyCom.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 "uart.h"    
   
#define TTY_DEV "/dev/ttyS" //端口路径    
   
#define TIMEOUT_SEC(buflen,baud) (buflen*20/baud+2)  //接收超时    
#define TIMEOUT_USEC 0    
/*******************************************  
 *  获得端口名称  
********************************************/   
char *get_ptty(pportinfo_t pportinfo)   
{   
    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;   
    }   
}   
   
/*******************************************  
 *  Setup comm attr  
 *  fdcom: 串口文件描述符,pportinfo: 待设置的端口信息(请确认)  
 *  
********************************************/   
int PortSet(int fdcom, const pportinfo_t pportinfo)   
{   
    struct termios termios_old, termios_new;   
    int     baudrate, tmp;   
    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] = 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;  //串口文件描述符    
    char *ptty;   
   
    ptty = get_ptty(pportinfo);   
    //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, 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, char *data, int datalen, int baudrate)   
{   
    int readlen, fs_sel;   
    fd_set  fs_read;   
    struct timeval tv_timeout;   
   
    FD_ZERO(&fs_read);   
    FD_SET(fdcom, &fs_read);   
    tv_timeout.tv_sec = TIMEOUT_SEC(datalen, baudrate);   
    tv_timeout.tv_usec = TIMEOUT_USEC;   
   
    fs_sel = select(fdcom+1, &fs_read, NULL, NULL, &tv_timeout);   
    if(fs_sel){   
        readlen = read(fdcom, data, datalen);   
        return(readlen);   
    }   
    else{   
        return(-1);   
    }   
   
    return (readlen);   
}   
   
//*************************Test*********************************    
int main(int argc, char *argv[])   
{   
    int fdcom, i, SendLen, RecvLen;   
    struct termios termios_cur;   
    char RecvBuf[10];   
    portinfo_t portinfo ={   
        '0',                            // print prompt after receiving    
        115200,                         // baudrate: 9600    
        '8',                            // databit: 8    
        '0',                            // debug: off    
        '0',                            // echo: off    
        '2',                            // flow control: software    
        '0',                            // default tty: COM1    
        '0',                            // parity: none    
        '1',                            // stopbit: 1    
         0                          // reserved    
    };   
   /*
    if(argc != 2){   
        printf("Usage: <type 0 -- send 1 -- receive>\n");   
        printf("   eg:");   
        printf("        MyPort 0");   
        exit(-1);   
    }   
   */
    fdcom = PortOpen(&portinfo);   
    if(fdcom<0){   
        printf("Error: open serial port error.\n");   
        exit(1);   
    }   
   
    PortSet(fdcom, &portinfo);   
   
    if(atoi(argv[1]) == 0){   
        //send data    
        for(i=0; i<100; i++){   
            SendLen = PortSend(fdcom, "1234567890", 10);   
            if(SendLen>0){   
                printf("No %d send %d data 1234567890.\n", i, SendLen);   
            }   
            else{   
                printf("Error: send failed.\n");   
            }   
            sleep(1);   
        }   
        PortClose(fdcom);   
    }   
    else{   
        for(;;){   
            RecvLen = PortRecv(fdcom, RecvBuf, 10, portinfo.baudrate);   
            if(RecvLen>0){   
                for(i=0; i<RecvLen; i++){   
                    printf("Receive data No %d is %x.\n", i, RecvBuf[i]);   
                }   
                printf("Total frame length is %d.\n", RecvLen);   
            }   
            else{   
                printf("Error: receive error.\n");   
            }   
            sleep(2);   
        }   
    }   
    return 0;   
}  

 

/*本程序符合GPL条约 
MyCom.h  
一组操作串口的函数 
*/ 
 
//串口结构 
typedef struct{ 
 char prompt;  //prompt after reciving data 
 int  baudrate;  //baudrate 
 char databit;  //data bits, 5, 6, 7, 8 
 char  debug;  //debug mode, 0: none, 1: debug 
 char  echo;   //echo mode, 0: none, 1: echo 
 char fctl;   //flow control, 0: none, 1: hardware, 2: software 
 char  tty;   //tty: 0, 1, 2, 3, 4, 5, 6, 7 
 char parity;  //parity 0: none, 1: odd, 2: even 
 char stopbit;  //stop bits, 1, 2 
 const int reserved; //reserved, must be zero 
}portinfo_t; 
typedef portinfo_t *pportinfo_t; 
/* 
 * 打开串口,返回文件描述符 
 * pportinfo: 待设置的串口信息 
*/ 
int PortOpen(pportinfo_t pportinfo); 
/* 
 * 设置串口 
 * fdcom: 串口文件描述符, pportinfo: 待设置的串口信息 
*/ 
int PortSet(int fdcom, const pportinfo_t pportinfo); 
/* 
 * 关闭串口 
 * fdcom:串口文件描述符 
*/ 
void PortClose(int fdcom); 
/* 
 * 发送数据 
 * fdcom:串口描述符, data:待发送数据, datalen:数据长度 
 * 返回实际发送长度 
*/ 
int PortSend(int fdcom, char *data, int datalen); 
/* 
 * 接收数据 
 * fdcom:串口描述符, data:接收缓冲区, datalen.:接收长度, baudrate:波特率 
 * 返回实际读入的长度 
*/ 
int PortRecv(int fdcom, char *data, int datalen, int baudrate);


猜你喜欢

转载自blog.csdn.net/jacky198554/article/details/78673381