2010-07-07 91 views
3

我想要通過ftdi_sio內核模塊提供的虛擬串行端口與USB設備進行通信。不過,我遇到了一些麻煩設置端口的波特率爲14400:在Linux下指定FTDI虛擬串行端口的非標準波特率

  • termios.h沒有指定一個常數14400,所以我不能使用cfsetispeedcfsetospeed
  • 在ftdi_sio內核模塊的源代碼中,波特基被設置爲24000000,似乎沒有辦法改變它。這意味着我無法使用ioctl的TIOCSSERIAL定製除數,並以這種方式獲得14400波特率。
  • 模塊源有一個評論,它聽起來像設置結構的alt_speed成員的端口爲14400會做我想做的,但似乎沒有任何方法將其設置爲14400給定現有的接口。

有沒有人有關於此?通過破解內核模塊可以很容易地解決這個問題,但我確實在尋找一種不需要更改內核的解決方案。

+0

ISTR,早在當戴夫·格羅爾是涅槃鼓手,14400點波特的調制解調器的日子與19200波特的端口速度一起使用 - 您的設備不工作在19200? – caf 2010-07-07 06:47:51

+0

不,不幸的是,它是14400或蕭條。 – Hugh 2010-07-07 18:29:00

+1

波特基/除數產生的波特率不是確切的波特率,這是非常普遍的事情。這通常不是問題。 如果您的串行硬件晶振無法提供,您將無法獲得精確的波特率。尤其是與ftdi類似的硬件,我懷疑你可以改變波特率。 – shodanex 2010-07-07 19:09:08

回答

4

您不能更改波特率,我想它是硬件相關的。所以搞亂模塊不會對你有任何好處。在第三點中,您只討論了第一種設置自定義波特率的方法,您需要訪問tty->alt_speed。看起來沒有接口可以直接從用戶空間設置tty結構,至少不用ftdi_sio驅動程序。
然而,還有另一種方法在評論中解釋說:

 * 3. You can also set baud rate by setting custom divisor as follows 
    * - set tty->termios->c_cflag speed to B38400 
    * - call TIOCSSERIAL ioctl with (struct serial_struct) set as 
    *  follows: 
    *  o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST 
    *  o custom_divisor set to baud_base/your_new_baudrate 

你嘗試了嗎?

+0

我試過這個,但是custom_divisor是一個完整的類型,所以雖然我可以得到14405或14397,但14400是不可能的。 Baud base twiddling對我來說看起來很有用,因爲它似乎只用於推導出您提到的第三種情況下使用的實際波特率。但是,我剛剛注意到ftdi_sio.h中有關'FTDI_SIO_SET_BAUDRATE'的註釋 - 我必須檢查是否可以使用它來以有用的方式旋轉除數。 – Hugh 2010-07-07 18:27:50

+1

阿!根據上面的註釋(不會精確到14.4k),我最終仔細看了一下'get_ftdi_divisor'函數 - 使用1666(即14405波特)的除數作爲訣竅,因爲這會導致相同的值通過USB控制消息發送到設備,該消息設置實際的串行波特率將發送給14400.非常感謝! – Hugh 2010-07-07 23:52:22

+0

這些利率都在任何合理的保證金誤差範圍內,並且應該有效。其他設備非常難以生成足夠精確的波特率,以便在14,405或13,397與其他設備通話時檢測到故障。錯誤非常小。 – unwind 2017-02-14 12:06:27

3

Shodanex的解決方案可在Linux下使用NDI Polaris Spectra(波特率1.2mbps)。按照規定,有B38400打開串口設備(的/ dev/ttyUSB0),

int port = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NONBLOCK); 
tcgetattr(port,&g_initialAtt);// save this to restore later 
newAtt=g_initialAtt; 
newAtt.c_cflag = B38400 | CS8 | CLOCAL | CREAD; 
cfmakeraw(&newAtt); 
tcsetattr(port,TCSANOW,&newAtt); 

然後執行:

if(ioctl(port, TIOCGSERIAL, &sstruct) < 0){ 
    printf("Error: could not get comm ioctl\n"); 
    exit(0); 
} 
sstruct.custom_divisor = custDiv; 
//sstruct.flags &= 0xffff^ASYNC_SPD_MASK; NO! makes read fail. 
sstruct.flags |= ASYNC_SPD_CUST; 
if(ioctl(port, TIOCSSERIAL, &sstruct) < 0){ 
    printf("Error: could not set custom comm baud divisor\n"); 
    exit(0); 
} 
+0

也看看這裏http://stackoverflow.com/questions/4968529/how-to-set-baud-rate-to-307200-on-linux/7152671#7152671 – Gellweiler 2013-11-02 18:39:05