zoukankan      html  css  js  c++  java
  • linux下串口控制

    /*  本程序符合GPL条约
     *  Beneboy 2003-5-16
    */
    #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 "MyCom.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: 待设置的端口信息s
     *
    ********************************************/
    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[256];
            char writeBuf[256];
     portinfo_t portinfo ={
      '0',                          // print prompt after receiving
       9600,                       // 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> ");
      printf("   eg:");
      printf("        MyPort 0");
      exit(-1);
     }

     fdcom = PortOpen(&portinfo);
     if(fdcom<0){
      printf("Error: open serial port error. ");
      exit(1);
     }

     PortSet(fdcom, &portinfo);

            while(1)
     if(atoi(argv[1]) == 0)
            {
      //send data
      //for(i=0; i<1000; i++)
                    {
                            //fgets(writeBuf,256,stdin);
                            scanf("%s",writeBuf);
       SendLen = PortSend(fdcom, writeBuf, strlen(writeBuf));
       if(SendLen>0)
                            {
        //printf("send data %s", writeBuf);
       }
       else
                            {
        printf("Error: send failed. ");
       }

                            if(strncmp(writeBuf,"exit",4)==0)
                               break;
       sleep(1);
      }
      //PortClose(fdcom);
     }
     else
           {
      //for(;;)
                    {
       RecvLen = PortRecv(fdcom, RecvBuf, 256, portinfo.baudrate);
       if(RecvLen>0)
                            {
        /*for(i=0; i<RecvLen; i++)
                                    {
         printf("Receive data No %d is %x. ", i, RecvBuf[i]);
        }//*/
                                    RecvBuf[RecvLen] = '';
        printf("read data %s ",RecvBuf);

                                    if(strncmp(RecvBuf,"exit",4)==0)
                                        break;
       }
       else
                            {
        //printf("Error: receive error. ");
       }
       sleep(1);
      }
     }
            PortClose(fdcom);
     return 0;
    }

  • 相关阅读:
    Shell脚本:使用rsync备份文件/目录
    如何在 CentOS 中设置 NTP 服务器
    NGINX引入线程池 性能提升9倍
    如何在Quagga BGP路由器中设置IPv6的BGP对等体和过滤
    如何使用Weave以及Docker搭建Nginx反向代理/负载均衡服务器
    在 Ubuntu 上配置高性能的 HHVM 环境
    在 Linux 中怎样将 MySQL 迁移到 MariaDB 上
    如何删除 Ubuntu 上不再使用的旧内核
    如何在 Arch Linux 中安装 DNSCrypt 和 Unbound
    在 CentOS 7 中安装并使用自动化工具 Ansible
  • 原文地址:https://www.cnblogs.com/james1207/p/3253488.html
Copyright © 2011-2022 走看看