码迷,mamicode.com
首页 > 其他好文 > 详细

Non-standard serial port baud rate setting

时间:2019-05-20 17:02:05      阅读:108      评论:0      收藏:0      [点我收藏+]

标签:perror   超时   oca   转换   r++   time   delay   ios   uart   

////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\n");


    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\n", 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\n", strerror(errno));
        return -2;
    }


    ioctl(fd, TIOCGSERIAL, &ss_set);
    printf("BAUD: success set baud to %d,custom_divisor=%d,baud_base=%d\n",
            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\n");
            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\n");
            return (FALSE);
    }


    /* 设置停止位*/
    switch (stopbits)
    {
        case 1:
            options.c_cflag &= ~CSTOPB;
            break;
        case 2:
            options.c_cflag |= CSTOPB;
            break;
        default:
            fprintf(stderr,"Unsupported stop bits\n");
            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. \n");
                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>\n", 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 \n", dev);
        return -1;
    }

*/
    if((fd = open_dev(dev)) < 0)
    {
        printf("can‘t open port %s \n", 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\n",band_rate);
            close(fd);
            return -1;
        }

        sleep(uart_init_interval_second);
        // if(set_speed(fd, 115200) < 0)
        // {
        // printf("Set Speed Error set_speed\n");
        // return -1;
        // }

        if(set_parity(fd, 8, 1, N) < 0)
        {
            printf("Set Parity Error\n");
            close(fd);
            return -1;
        }
        sleep(uart_init_interval_second);
    }

    while(1){
        if(1 == Read1(fd, &c))
        {
            fprintf(stderr, "c[%c] = 0x%02x \n", c, (unsigned char)c);
        }
    }

    close(fd);

    return 0;
}

 

Non-standard serial port baud rate setting

标签:perror   超时   oca   转换   r++   time   delay   ios   uart   

原文地址:https://www.cnblogs.com/lianghong881018/p/10894737.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!