• Non-standard serial port baud rate setting


    ////combuad_recv.cpp
    
    #include <stdio.h>      /*标准输入输出定义*/
    #include <stdlib.h>     /*标准函数库定义*/
    #include <unistd.h>     /*Unix 标准函数定义*/
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>      /*文件控制定义*/
    #include <termios.h>    /*PPSIX 终端控制定义*/
    #include <errno.h>      /*错误号定义*/
    #include <string.h>
    
    
    #include <sys/ioctl.h>
    #include <linux/serial.h>
    
    
    #define FALSE   -1
    #define TRUE   0
    
    
    /*
       设置串口
       最基本的设置串口包括波特率设置,效验位和停止位设置。
       串口的设置主要是设置 struct termios 结构体的各成员值。
    
    
       struct termio
       {
       unsigned short  c_iflag; // 输入模式标志
       unsigned short  c_oflag; // 输出模式标志
       unsigned short  c_cflag; // 控制模式标志
       unsigned short  c_lflag; // local mode flags
       unsigned char  c_line; // line discipline
       unsigned char  c_cc[NCC];   // control characters
       };
     */
    
    
    /**
     *@brief  设置串口通信速率
     *@param  fd     类型 int  打开串口的文件句柄
     *@param  speed  类型 int  串口速度
     *@return  void
     */
    static int speed_arr[] = { B200, B300, B600, B1200, B1800, B2400, B4800, B9600, B19200, B38400, B57600, B115200, /*B200000,*/ B230400 };
    static int name_arr[] =  {  200,  300,  600,  1200,  1800,  2400,  4800,  9600,  19200,  38400,  57600,  115200, /*200000,*/ 230400 };
    static int set_speed(int fd, int speed)
    {
        int   i;
        int   status;
        struct termios   Opt;
        int baud_rate;
    
    
        tcgetattr(fd, &Opt);
    
    
        for (i = 0; i < sizeof(speed_arr)/sizeof(int); i++)
        {
            if(speed == name_arr[i])
            {
                baud_rate = speed_arr[i];
    
    
                if(baud_rate <= B38400)
                {
                    cfsetispeed(&Opt, baud_rate);
                    cfsetospeed(&Opt, baud_rate);
                }
                else
                {
                    Opt.c_cflag |= CBAUDEX;
                    baud_rate -= 4096;/*baud_rate取值为1 ~ 5,分别对应B57600/B115200/B3000000/B6000000/B12000000*/
                    cfsetispeed(&Opt, baud_rate);
                    cfsetospeed(&Opt, baud_rate);
                }
    
    
                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 FALSE;
                }
                tcflush(fd,TCIOFLUSH);
    
    
                return TRUE;
            }
        }
    
    
        fprintf(stderr, "Unsupported speed
    ");
    
    
        return FALSE;
    }
    
    
    // uart_set_info
    // 设置为特诉波特率,比如200000
    int set_speci_baud(int fd, int baud)
    {
        struct serial_struct ss, ss_set;
        struct termios Opt;
        tcgetattr(fd, &Opt);
    
    
        cfsetispeed(&Opt, B38400);
        cfsetospeed(&Opt, B38400);
    
    
        tcflush(fd, TCIFLUSH);/*handle unrecevie char*/
        tcsetattr(fd, TCSANOW, &Opt);
    
    
        if((ioctl(fd, TIOCGSERIAL, &ss)) < 0)
        {
            printf("BAUD: error to get the serial_struct info:%s
    ", strerror(errno));
            return -1;
        }
    
    
        ss.flags = ASYNC_SPD_CUST;
        ss.custom_divisor = ss.baud_base / baud;
        if((ioctl(fd, TIOCSSERIAL, &ss)) < 0)
        {
            printf("BAUD: error to set serial_struct:%s
    ", strerror(errno));
            return -2;
        }
    
    
        ioctl(fd, TIOCGSERIAL, &ss_set);
        printf("BAUD: success set baud to %d,custom_divisor=%d,baud_base=%d
    ",
                baud, ss_set.custom_divisor, ss_set.baud_base);
    
    
        return 0;
    }
    
    
    /**
     *@brief   设置串口数据位,停止位和效验位
     *@param  fd     类型  int  打开的串口文件句柄
     *@param  databits 类型  int 数据位   取值 为 7 或者8
     *@param  stopbits 类型  int 停止位   取值为 1 或者2
     *@param  parity  类型  int  效验类型 取值为N,E,O,,S
     */
    static 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
    ");
                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
    ");
                return (FALSE);
        }
    
    
        /* 设置停止位*/
        switch (stopbits)
        {
            case 1:
                options.c_cflag &= ~CSTOPB;
                break;
            case 2:
                options.c_cflag |= CSTOPB;
                break;
            default:
                fprintf(stderr,"Unsupported stop bits
    ");
                return (FALSE);
        }
    
    
        // important
        options.c_cflag |= CLOCAL | CREAD;
        options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
        options.c_oflag &= ~OPOST;
        options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
    
    
        /* Set input parity option */
        if (parity != 'n')
            options.c_iflag |= INPCK;
        tcflush(fd, TCIFLUSH);
        options.c_cc[VTIME] = 10; /* 设置超时*/
        options.c_cc[VMIN] = 0; /* Update the options and do it NOW */
    
    
        if (tcsetattr(fd, TCSANOW, &options) != 0)
        {
            perror("SetupSerial 3");
            return (FALSE);
        }
    
    
        return (TRUE);
    }
    
    
    static int open_dev(const char *dev)
    {
        int fd = open(dev, O_RDWR);         //| O_NOCTTY | O_NDELAY
        if (-1 == fd)
        {
            perror("can't open serial port");
            return -1;
        }
        else
        {
            return fd;
        }
    }
    
    
    ssize_t Read1(int fd, char *ptr)
    {
        static int read_cnt = 0;
        static char *read_ptr = NULL;
        static char read_buf[1024];
    
        if (read_cnt <= 0) 
        {
    again:
            if (-1 == (read_cnt = read(fd, read_buf,
                            sizeof(read_buf)))) 
            {
                if (EINTR == errno)
                {
                    fprintf(stdout, "[lgw] we received a int signal. 
    ");
                    goto again;
                }
    
                return -1;
            }
            else if (0 == read_cnt)
            {
                return 0;
            }
    
            read_ptr = read_buf;
        }
    
        --read_cnt;
        *ptr = *read_ptr++;
    
        return 1;
    }
    
    
    int main(int argc, char *argv[])
    {
        int fd;
        int band_rate;
        int uart_init_interval_second;
        char *dev;
    
        int cnt = -1, i = 0;
        unsigned char recv_buff[512] = { 0 };
        char c;
    
    
    
        if(4 != argc)
        {
            printf("Usage: %s <rs232_dev> <band_rate> <uart_init_interval_second>
    ", argv[0]);
            return -1;
        }
    
    
        dev = (char *)argv[1];
        band_rate = atoi((char *)argv[2]);
        uart_init_interval_second = atoi((char *)argv[3]);
    /*
        if((fd = open_dev(dev)) < 0)
        {
            printf("can't open port %s 
    ", dev);
            return -1;
        }
    
    */
        if((fd = open_dev(dev)) < 0)
        {
            printf("can't open port %s 
    ", dev);
            return -1;
        }
        else
        {
            if(set_speci_baud(fd, band_rate) < 0)
            //if(set_speci_baud(fd, 500000) < 0)
            {
                printf("Set Speed Error set_speci_baud: %d
    ",band_rate);
                close(fd);
                return -1;
            }
    
            sleep(uart_init_interval_second);
            // if(set_speed(fd, 115200) < 0)
            // {
            // printf("Set Speed Error set_speed
    ");
            // return -1;
            // }
    
            if(set_parity(fd, 8, 1, 'N') < 0)
            {
                printf("Set Parity Error
    ");
                close(fd);
                return -1;
            }
            sleep(uart_init_interval_second);
        }
    
        while(1){
            if(1 == Read1(fd, &c))
            {
                fprintf(stderr, "c[%c] = 0x%02x 
    ", c, (unsigned char)c);
            }
        }
    
        close(fd);
    
        return 0;
    }
  • 相关阅读:
    Android核心分析 ---- 电话系统之GSMCallTacker
    Android核心分析 ----- Android电话系统之RIL-Java
    Android核心分析 ------ 电话系统之rilD
    Android核心分析 ----- Android电话系统-概述篇
    AndroidRuntime 流程
    关于++和--运算符的理解
    使用eclips开发java时的闪退问题
    Android--控件的滑动事件
    Running Hero.
    软件工程第三次大作业分工说明
  • 原文地址:https://www.cnblogs.com/lianghong881018/p/10894737.html
Copyright © 2020-2023  润新知