非标准波特率的实现?
请教各位大神 想把波特率设置成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囧。。。
求解。。。小女在此谢过!!
如果驱动是正常的,不需要改代码。通过给kernel穿参数既可以改变波特率
应用层也可以改
波特率大,就相当于收发数据快一点
减4096的代码就是给相应的bit位上的1 去掉 谢谢斑竹大人回复~
驱动是正常的 但是驱动中波特率的索引里没有28800啊, 这样传参也可以么??
用cfsetispeed和cfsetospeed的话,内核会根据它设置的值去驱动的索引表baud_table[]里找是吧。。这样设置的话如果是非标准的 表里没有 就无法设置成功吧。。。。
但要是用ioctl的TIOCGSERIAL和TIOCSSERIAL命令的话 就可以么??? 这两种设置波特率的方法有什么区别呢?
回复 2# amarant
本帖最后由 amarant 于 2014-05-15 15:07 编辑
回复 3# yousuozi
设置波特率归根到底就是设置分频数。你按照BXXXXX宏传进去就可以设置了表里没有的 估计是不能设置的。我没有细看其代码,有兴趣你可以看看其驱动代码 哦哦 那方法一里 设置了分频数为4了 就可以实现28800的波特率了是吧~
在这之前它先设置了个38400的波特率 是做什么用呢??是为了借用它的serial_struct结构体中除flags还有custom_divisor之外的那些参数么??
回复 4# amarant
波特率最终通过设置 divisor 这些参数来设置,但这个与系统主频之类的相关。
所以,先用38400获取主频相关参数,倒推算出其他非标波特率需要的 divisor。
但是,这个方法貌似在 3.10 的 linux 内核上没有用。
3.10 的linux已经可以支持在应用层直接设置非标的波特率了。
页:
[1]