http://blog.sina.com.cn/s/blog_8b58097f0102wxm3.html ARM,STM32,FPGA,AD,PCB同行原創(chuàng)blog http://blog.sina.com.cn/s/articlelist_2337802623_0_1.html 1.
Linux下USB設(shè)備節(jié)點名不固定問題經(jīng)常會遇到
以USB轉(zhuǎn)串口設(shè)備為例,通常設(shè)備節(jié)點名為ttyUSBx(x為0~n),Linux內(nèi)核會根據(jù)設(shè)備插入的先后順序進(jìn)行編號的分配,比如第一個插入的設(shè)備編號為ttyUSB0,然后依此加1,變?yōu)閠tyUSB1,ttyUSB2……
如果僅僅以設(shè)備節(jié)點ttyUSBx來區(qū)別具體是哪個設(shè)備,因為末位的編號是隨時會變的,所以就會造成混亂。無法保證A設(shè)備就是ttyUSB0,B設(shè)備就是ttyUSB1。在設(shè)備文件/dev目錄下并沒有提供固定顯示ttyUSB的方法,但是,其實,每個USB端口都有唯一的端口號,相當(dāng)于每個門店的門牌號。只要我們依據(jù)端口號來進(jìn)行設(shè)備的區(qū)分,那么問題就迎刃而解了。簡單點來說就是找到端口號,然后根據(jù)端口號找到掛載在這個端口號上面的USB設(shè)備是ttyUSB0還是
ttyUSB1….(這個是變化的,前面講到了)。
2.
關(guān)于端口號的查看方法,連接好兩個USB轉(zhuǎn)串口設(shè)備之后:
執(zhí)行命令:ls -l
/sys/class/tty/ttyUSB*
lrwxrwxrwx root
lrwxrwxrwx root
可知:其中ttyUSB0所在的端口號為3-1.1,而ttyUSB1所在的端口號為3-1.2,可以看出,這里的3-1.1端口上比3-1.2上提前插上USB設(shè)備,所以會以這種方式命名。如果插入設(shè)備的順序相反,那么端口號3-1.1上對應(yīng)的設(shè)備應(yīng)該是ttyUSB1,而3-1.2上對應(yīng)的設(shè)備應(yīng)該是ttyUSB0。但是如果在實際過程中我們只需要采集端口3-1.1傳來的數(shù)據(jù),我們該如何通過ttyUSBx不定的設(shè)備節(jié)點,獲取到固定端口的數(shù)據(jù)呢?
3.
實際問題,實際解決:
實際工程中,碰到的一個問題是:硬件上連接有兩個USB轉(zhuǎn)串口設(shè)備,硬件只要一上電,兩個USB設(shè)備幾乎是同時上電的,這將導(dǎo)致ttyUSB0或者ttyUSB1無法每次固定的對應(yīng)到上一次的那個相同端口,上層軟件需要通過串口設(shè)備節(jié)點/dev/ttyUSBx來打開一個串口,并從串口獲取數(shù)據(jù),但是這個ttyUSBx設(shè)備并不是一直都指向固定的一個usb端口號,這直接導(dǎo)致我們無法往下操作了。
解決辦法:這里使用bash語言加Python正則表達(dá)式的相關(guān)知識解決這個問題:解決問題的思路是:
1. 第一次上電的時候,我們需要確定哪個端口上的數(shù)據(jù)是我們所需要的:
ls -l
/sys/class/tty/ttyUSB*
假設(shè)是3-1.1這個端口是我們的data端口。
2.
以后每次上電,我們要找到3-1.1這個端口后面掛載的ttyUSB設(shè)備是ttyUSB0還是ttyUSB1,并建立一個軟鏈接將當(dāng)時獲取到的ttyUSBx生成一個軟鏈接,名字固定為ttydata,那么以后每次打開/dev/ttydata就能找到正確3-1.1這個端口,并獲取數(shù)據(jù)了。
3.
建立一個文件夾getUSB,該文件夾下面包含:
getUSB.py是通過device_usb.txt中的信息,獲取到當(dāng)前掛著在端口3-1.1上的是ttyUSB0還是ttyUSB1并保存在usbdev
中
cmd.sh如下:
#!/bin/bash
declare -i a=0
declare -i b=0
while [[ ! -e "/sys/class/tty/ttyUSB0" ]]
do
sudo sleep 0.01s
a=a+1
if [ $a -eq 300 ];then
break
fi
done
while [[ ! -e "/sys/class/tty/ttyUSB1" ]]
do
sudo sleep 0.01s
b=b+1
if [[ $b -eq 300||$a -ne 0 ]];then
break
fi
done
if [[ ! -e /sys/class/tty/ttyUSB0&&! -e
/sys/class/tty/ttyUSB1 ]]; then #如果不存在ttyUSB設(shè)備
echo "Not have ttyUSB0 or not have ttyUSB1"
else
tty1=$(ls -l /sys/class/tty/ttyUSB0)
tty2=$(ls -l /sys/class/tty/ttyUSB1)
sudo ls -l /sys/class/tty/ttyUSB0 /sys/class/tty/ttyUSB1 >
./device_usb.txt
fi
if [ ! -n "$tty1" ] ;then
echo "tty1 is empty"
fi
#delay 0.01s to make sure the device_usb.txt complete
sudo sleep 0.01s
#remove the old USB device shortcut
if [ ! -e "/dev/ttydata" ] ;then # 如果/dev/ttydata本身不存在
echo "-------------/dev/ttydata not found"
else
echo "/dev/ttydata is exist"
sudo rm /dev/ttydata
fi
#exct Python language to get the rignt USB interface
./getUSB.py
usbdev=$(cat ./usbdev) #獲取到這個設(shè)備
echo "the device is : "
echo $usbdev
sudo ln -s /dev/$usbdev /dev/ttydata
#將這個設(shè)備軟連接到/dev/ttydata以后每次打開這個ttydata即可
getUSB.py:
#!/usr/bin/python
#coding:utf-8
import re
sss = open("./device_usb.txt","rb")
#打開device_usb.txt設(shè)備,并讀取內(nèi)容
www = open("./usbdev","wb")
s_read = sss.read()
r = r"usb3/3-1/3-1\.1.+(ttyUSB[0-9])"
#正則中“.”需要轉(zhuǎn)義,所以使用“\.”表示“.”
#這個規(guī)則是找到usb3/3-1/3-1.1/這個字符串后面緊跟的是此次上電生成的ttyUSB0或者ttyUSB1
output = re.findall(r,s_read)
www.write(output[0]) #將結(jié)果寫到usbdev中
www.close()
sss.close()
完成之后設(shè)置開機(jī)項目,將文件夾當(dāng)?shù)酪粋€位置,然后設(shè)置開機(jī)啟動cmd.sh(在/etc/rc.local中設(shè)置)則每次開機(jī)之后,會從/dev/ttydata獲取到固定端口的數(shù)據(jù)
這兩天在ubuntu中開發(fā)跟串口有關(guān)程序時,發(fā)現(xiàn)來回拔插串口線或者插多個串口線時總是出現(xiàn)串口號ttyUSB*不固定的問題,給應(yīng)用程序帶來不少麻煩,遂google解決。
linux中設(shè)備號一般按先后順序一次向后增大,udev規(guī)則文件可以解決這個蛋疼的問題。udev是一種Linux2.6內(nèi)核采用的/dev
目錄的管理系統(tǒng)(可以把它認(rèn)為是windows中的設(shè)備管理器),它通過從sysfs獲得的信息,可以提供對特定設(shè)備的固定的設(shè)備名。sysfs是linux udev的重要功能就是為為設(shè)備提供固定的設(shè)備名, 根據(jù)Wirting udev rules的詳細(xì)介紹, udev有如下功能:
idVendor和idProduct由 lsusb
保存退出后udev規(guī)則就生效了,重新拔插兩個串口設(shè)備,就可以看到/dev/user_uart指向/dev/ttyUSB0, PS:如果您的兩個串口用的都是PL2303或者都是CH340/CP2102,那就真的無能為力了。。。 常用的匹配類型:
* BUS:匹配總路類型,比如PCI
USB等
* DRIVER :-
匹配Kernel的驅(qū)動程序名
* SUBSYSTEM: -
匹配子系統(tǒng)名。 * ID :- 匹配總路系統(tǒng)的ID (e.g. PCI bus ID)。
* PLACE :- 匹配物理位置 資料鏈接: |
|