yousuozi 发表于 2014-05-15 09:01

非标准波特率的实现?

请教各位大神 想把波特率设置成28800, 应该怎样实现呢???

网上看到两个方法(如下) 不是很明白 请大神们指教
(一)
#include <termios.h>
#include <sys/ioctl.h>
#include <linux/serial.h>
struct serial_t {
    int   fd;
    char    *device;/*/dev/ttyS0,...*/
    int   baud;
    int   databit;/*5,6,7,8*/
    char    parity;/*O,E,N*/
    int    stopbit;/*1,2*/
    int    startbit;/*1*/
   
    struct termios    options;
};
//设置为特诉波特率,比如28800
int serial_set_speci_baud(struct serial_t *tty,int baud)
{
    struct serial_struct ss,ss_set;
    cfsetispeed(&tty->options,B38400);
    cfsetospeed(&tty->options,B38400);
    tcflush(tty->fd,TCIFLUSH);/*handle unrecevie char*/
    tcsetattr(tty->fd,TCSANOW,&tty->options);
    if((ioctl(tty->fd,TIOCGSERIAL,&ss))<0){
      dprintk("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(tty->fd,TIOCSSERIAL,&ss))<0){
      dprintk("BAUD: error to set serial_struct:%s\n",strerror(errno));
      return -2;
    }
    ioctl(tty->fd,TIOCGSERIAL,&ss_set);
    dprintk("BAUD: success set baud to %d,custom_divisor=%d,baud_base=%d\n",
            baud,ss_set.custom_divisor,ss_set.baud_base);
    return 0;
}

用法:只要指定serial_t的baud就可以了
static struct serial_t __seri_conf[] = {
    = {//connect with b board, ttyS0
      .device = "/dev/ttyS0",
      .baud = 28800,
      .databit = 8,
      .parity = 'N',
      .stopbit = 1,
    },
};

问题:1.这个意思是只在应用层上改就可以了??不用在驱动里做什么改动么??
         2.为什么要先把波特率设置成38400呢??它起到了什么作用啊

(二)
static const speed_t baud_table[] =
{
          0,50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,19200,38400,/*the POSIX std*/
          57600,115200,
          3000000,6000000,12000000/*pl2303 ext*/
};
static const tcflag_t baud_bits[] =
{
          B0,B50,B75,B110,B134,B150,B200,B300,B600,B1200,B1800,B2400,B4800,B9600,B19200,B38400,B57600,B115200,/*the POSIX std*/
          B3000000,B6000000,B12000000/*pl2303 ext*/
};
(2)修改arch/xx/include/asm/termbits.h的Bxxxx定义如下:
#defineB0   0000000         /* hang up */
#defineB50    0000001
#defineB75    0000002
#defineB110   0000003
#defineB134   0000004
#defineB150   0000005
#defineB200   0000006
#defineB300   0000007
#defineB600   0000010
#defineB12000000011
#defineB18000000012
#defineB24000000013
#defineB48000000014
#defineB96000000015
#defineB19200 0000016
#defineB38400 0000017

#defineBOTHER 0010000
#defineB57600 0010001
#defineB115200 0010002


         #define B3000000      0010003
         #define B6000000      0010004
         #define B12000000       0010005
/*后面的波特率本人没有使用到,但如果不定义则内核无法编译通过!*/
         #define   B230400       0010006
         #define   B460800       0010007
         #define   B500000       0010010
         #define   B576000       0010011
         #define   B921600       0010012

(3)重新编译内核,重启后则新内核将支持B3000000/B6000000/B12000000的波特率
2.应用层修改
libc中的cfsetispeed()和cfsetospeed()因为不支持非标波特率,因此调用这两个函数会返回-1,应用程序需要使用如下方式:
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);
}

问题:开始部分我明白 在驱动中添加了你需要的波特率
       后面的应用是什么意思呢??特别是这句 baud_rate -= 4096,怎么又冒出个4096来??还有这句后面的解释 啥1~5囧。。。

求解。。。小女在此谢过!!

amarant 发表于 2014-05-15 13:39

如果驱动是正常的,不需要改代码。通过给kernel穿参数既可以改变波特率
应用层也可以改
波特率大,就相当于收发数据快一点

减4096的代码就是给相应的bit位上的1 去掉

yousuozi 发表于 2014-05-15 14:15

谢谢斑竹大人回复~

驱动是正常的 但是驱动中波特率的索引里没有28800啊, 这样传参也可以么??



用cfsetispeed和cfsetospeed的话,内核会根据它设置的值去驱动的索引表baud_table[]里找是吧。。这样设置的话如果是非标准的 表里没有 就无法设置成功吧。。。。

但要是用ioctl的TIOCGSERIAL和TIOCSSERIAL命令的话 就可以么??? 这两种设置波特率的方法有什么区别呢?

回复 2# amarant


   

amarant 发表于 2014-05-15 15:06

本帖最后由 amarant 于 2014-05-15 15:07 编辑

回复 3# yousuozi


    设置波特率归根到底就是设置分频数。你按照BXXXXX宏传进去就可以设置了表里没有的 估计是不能设置的。我没有细看其代码,有兴趣你可以看看其驱动代码

yousuozi 发表于 2014-05-15 15:12

哦哦 那方法一里 设置了分频数为4了 就可以实现28800的波特率了是吧~

在这之前它先设置了个38400的波特率 是做什么用呢??是为了借用它的serial_struct结构体中除flags还有custom_divisor之外的那些参数么??

回复 4# amarant


   

ddm95 发表于 2014-05-30 16:24

波特率最终通过设置 divisor 这些参数来设置,但这个与系统主频之类的相关。
所以,先用38400获取主频相关参数,倒推算出其他非标波特率需要的 divisor。

但是,这个方法貌似在 3.10 的 linux 内核上没有用。
3.10 的linux已经可以支持在应用层直接设置非标的波特率了。
页: [1]
查看完整版本: 非标准波特率的实现?