免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5008 | 回复: 5
打印 上一主题 下一主题

[应用] 非标准波特率的实现? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 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[] = {
    [0] = {//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定义如下:
  #define  B0     0000000         /* hang up */
  #define  B50    0000001
  #define  B75    0000002
  #define  B110   0000003
  #define  B134   0000004
  #define  B150   0000005
  #define  B200   0000006
  #define  B300   0000007
  #define  B600   0000010
  #define  B1200  0000011
  #define  B1800  0000012
  #define  B2400  0000013
  #define  B4800  0000014
  #define  B9600  0000015
  #define  B19200 0000016
  #define  B38400 0000017

  #define  BOTHER 0010000
  #define  B57600 0010001
  #define  B115200 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囧。。。

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

论坛徽章:
22
丑牛
日期:2014-08-15 14:32:0015-16赛季CBA联赛之同曦
日期:2017-12-14 15:28:14黑曼巴
日期:2017-08-10 08:14:342017金鸡报晓
日期:2017-02-08 10:39:42黑曼巴
日期:2016-11-15 15:48:38CU十四周年纪念徽章
日期:2016-11-09 13:19:1015-16赛季CBA联赛之同曦
日期:2016-04-08 18:00:03平安夜徽章
日期:2015-12-26 00:06:30程序设计版块每日发帖之星
日期:2015-12-03 06:20:002015七夕节徽章
日期:2015-08-21 11:06:17IT运维版块每日发帖之星
日期:2015-08-09 06:20:002015亚冠之吉达阿赫利
日期:2015-07-03 08:39:42
2 [报告]
发表于 2014-05-15 13:39 |只看该作者
如果驱动是正常的,不需要改代码。通过给kernel穿参数既可以改变波特率
应用层也可以改
波特率大,就相当于收发数据快一点

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

论坛徽章:
0
3 [报告]
发表于 2014-05-15 14:15 |只看该作者
谢谢斑竹大人回复~

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



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

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

回复 2# amarant


   

论坛徽章:
22
丑牛
日期:2014-08-15 14:32:0015-16赛季CBA联赛之同曦
日期:2017-12-14 15:28:14黑曼巴
日期:2017-08-10 08:14:342017金鸡报晓
日期:2017-02-08 10:39:42黑曼巴
日期:2016-11-15 15:48:38CU十四周年纪念徽章
日期:2016-11-09 13:19:1015-16赛季CBA联赛之同曦
日期:2016-04-08 18:00:03平安夜徽章
日期:2015-12-26 00:06:30程序设计版块每日发帖之星
日期:2015-12-03 06:20:002015七夕节徽章
日期:2015-08-21 11:06:17IT运维版块每日发帖之星
日期:2015-08-09 06:20:002015亚冠之吉达阿赫利
日期:2015-07-03 08:39:42
4 [报告]
发表于 2014-05-15 15:06 |只看该作者
本帖最后由 amarant 于 2014-05-15 15:07 编辑

回复 3# yousuozi


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

论坛徽章:
0
5 [报告]
发表于 2014-05-15 15:12 |只看该作者
哦哦 那方法一里 设置了分频数为4了 就可以实现28800的波特率了是吧~

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

回复 4# amarant


   

论坛徽章:
0
6 [报告]
发表于 2014-05-30 16:24 |只看该作者
波特率最终通过设置 divisor 这些参数来设置,但这个与系统主频之类的相关。
所以,先用38400获取主频相关参数,倒推算出其他非标波特率需要的 divisor。

但是,这个方法貌似在 3.10 的 linux 内核上没有用。
3.10 的linux已经可以支持在应用层直接设置非标的波特率了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP