樹莓派3配置串口,JAVA實現串口通訊(2016年3月版本,重點提示,3月之後的版本配置貌似不一樣)
因爲公司產品的需求,需要用到樹莓派上的串口功能,但樹莓派3的串口直接不能用,因爲在樹莓派3用的CPU中本身有兩個串口,一個是硬件串口(PL011 UART),一個是迷你串口(mini-uart),在樹莓派2B和B+等老版本上,樹莓派將硬件串口分配給了GPIO14和GPIO15,因此可以直接使用這個串口。但在樹莓派3上,多了一個然並卵的藍牙模塊(起碼我感覺丫就是然並卵的東西,我們有自己的藍牙產品,完全不用這個多餘的貨,各位有其他用的另當別論了),官方將硬件串口無私的給了藍牙,而將一個沒有時鐘源,必須由內核提供時鐘參考源的“迷你串口”分配給了GPIO的串口,這樣以來由於內核的頻率本身是變化的,就會導致“迷你串口”的速率不穩定,這樣就出現了無法正常使用的情況。
網上給的提示是,關閉藍牙,直接回復硬件串口的GPIO,所以呢,如果想用串口的話,還是放棄藍牙吧。
還有一點噁心的,我的測試機用的是2016-03-18-raspbian-jessie,而現在我們正式環境用的是2016-09-23-raspbian-jessie-lite,本來在測試機調試好的,到生產環境就SB了,完全不通,所以各位看這個教程的時候,請務必先確認一下自己系統的版本,對於3月之後版本的,等我研究透了再另行發帖,到時候我會附在本帖後面。目前網上沒找到關於3月之後版本怎麼做串口的,大家靜候吧。
廢話過後,乾貨來了!
第一步,我們需要修改配置文件,
sudo vi /boot/config.txt
在最下面添加兩行內容
dtoverlay=pi3-miniuart-bt-overlay
force_turbo=1
這裏需要注意以下,做這一步的時候先去看看/boot/overlays下面是不是有一個叫pi3-miniuart-bt-overlay.dtb的文件,或者pi3-miniuart-bt.dtb,都行,根據文件名不同,上面配置的那個參數也不一樣
如果沒有,去下載以下,地址 http://ukonline2000.com/?attachment_id=881
第二步,配置串口
sudo vi /boot/cmdline.txt
把裏面的內容改成
dwc_otg.lpm_enable=0 console=serial1,115200 console=tty1 root=/dev/mmcblk0p2 kgdboc=serial1,115200 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
具體爲啥,我還沒來得及研究,有明白人可以回覆一下,或者等我有空了補上這塊內容
第三步,關閉藍牙
sudo systemctl disable hciuart
第四步,修改串口指向
sudo vi /lib/systemd/system/hciuart.service
將 “ttyAMA0”修改爲“ttyS0”就下面圖這樣子
只改這一樣就行了,下面的那個不用管他
如果這時候你看到的是After=def-serial1.device,那說明你是3月之後的版本,這篇教程不適用
第五步,重啓樹莓派,就OK了
還有一點需要提示的,如果你安裝的是精簡版(尾綴-lite的鏡像),有可能串口沒有打開,這個可以先去驅動裏確認一下
ls /dev看看有沒有ttyAMA0,如果沒有,就說明沒打開,這時候去配置中開一下就有了
sudo raspi-config
選擇Advanced Options -> Serial
選擇yes就行了
完事之後重啓樹莓派,就有ttyAMA0了
我們用的是JAVA開發程序,所以才做串口必須藉助一些開發包,當然首選應該是Pi4J,畢竟正在做這塊的翻譯嘛,但是我並沒用他,而是用了RXTX,比較方便。
先說安裝步驟,Windows下直接下載包就可以用了,樹莓派下需要安裝一下。
第一步,下載包
第二步,解壓
unzip rxtx-2.1-7r2.zip
第三步,修改參數
首先需要獲得一個版本號
uname -r
(我的是4.1.19-v7+)
sudo vi /usr/include/linux/version.h
最後面加一行
#define UTS_RELEASE "4.1.19-v7+"
那個版本號就是咱們剛纔查出來的版本號
第四步,修改安裝文件參數
在解壓好的包中,有個configure,我們要把裏面的所有1.2*|1.3*|1.4*|1.5*,都改成1.2*|1.3*|1.4*|1.5*|1.6*|1.7*|1.8*
這一步建議到Windows下面修改,大概有個四五處吧
sudo sh ./configure
make
sudo make install
最後一樣記得加 sudo
出現 /usr/bin/install -c RXTXcomm.jar /usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/jre/lib/ext/就表示安裝成功了!
還有一點要注意的,安裝貌似需要JDK8環境,7試驗失敗,不知道能不能裝,建議大家還是升級一下吧
下面,開始寫程序
RXTX只支持ttyS開頭的設備,而我們要跟串口通訊用的是
ttyAMA0,所以在此之前還要做一下映射
sudo ln -s /dev/ttyAMA0 /dev/ttyS45
45只是我隨便起了個名字而已,大家隨意吧
樹莓派的串口是TTL電平的,所以測試的時候需要注意以下
importgnu.io.CommPortIdentifier;
importgnu.io.PortInUseException;
importgnu.io.SerialPort;
importgnu.io.SerialPortEvent;
importgnu.io.SerialPortEventListener;
importgnu.io.UnsupportedCommOperationException;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.OutputStream;
importjava.util.Enumeration;
importjava.util.TooManyListenersException;
publicclassSerial
{
privateSerialPortport=null;
privateInputStreamin=null;
privateOutputStreamout=null;
privateSerial()
{}
privateSerial(String
name) {
//獲得本地所有串口列表,這裏其實只能獲得ttyS開頭的串口
Enumeration<CommPortIdentifier> portList =CommPortIdentifier.getPortIdentifiers();
while(portList.hasMoreElements()){
//獲得串口的標識符
CommPortIdentifier portId = portList.nextElement();
//通過標識符得到串口名字,並判斷這個名字是不是我們需要的那個串口
if(portId.getName().equals("/dev/"+name)){
SerialPort p=null;
try{
//如果確實是我們需要的串口,則打開這個串口
//open(串口占用進程名稱,串口等待超時時間)
p = (SerialPort) portId.open("TTSTest",
2000);
//給串口一個數據到達偵聽(觸發器)
p.addEventListener(newEventListener());
//把數據到達通知打開
p.notifyOnDataAvailable(true);
//設置串口的波特率,參數依次是(波特率,數據位,停止位,校驗位)
p.setSerialPortParams(9600,SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
//獲得輸入輸出流,方便操作。
out=
p.getOutputStream();
in=
p.getInputStream();
port=p;
}catch(PortInUseException
e) {
e.printStackTrace();
}catch(TooManyListenersException
e) {
e.printStackTrace();
}catch(UnsupportedCommOperationException
e) {
e.printStackTrace();
}catch(IOException
e) {
e.printStackTrace();
}
}
}
}
/**
* 打開串口
*
*@paramport
*/
publicstaticfinalSerial
open(String name) {
Serial serial =newSerial(name);
if(serial.port!=null){
returnserial;
}
returnnull;
}
/**
* 發送數據。
*@paramdata
*/
publicvoidsend(byte[]
data){
try{
out.write(data);
out.flush();
}catch(IOException
e) {
e.printStackTrace();
}
}
/**
* 關閉串口。
*/
publicvoidclose(){
//當然,這裏可以做一下事件偵聽,再給close加個參數,這樣在串口異常報錯的時候能能捕獲到了。
port.close();
port=null;out=null;in=null;
}
privateclassEventListenerimplementsSerialPortEventListener{
@Override
publicvoidserialEvent(SerialPortEvent
event) {
switch(event.getEventType())
{
//這些屬性應該跟串口特性有關,我還沒搞清楚,暫時不解釋
caseSerialPortEvent.BI:
caseSerialPortEvent.OE:
caseSerialPortEvent.FE:
caseSerialPortEvent.PE:
caseSerialPortEvent.CD:
caseSerialPortEvent.CTS:
caseSerialPortEvent.DSR:
caseSerialPortEvent.RI:
caseSerialPortEvent.OUTPUT_BUFFER_EMPTY:
break;
caseSerialPortEvent.DATA_AVAILABLE: //獲取到串口返回信息
byte[]
data =newbyte[512];
intlen=0;
try{
while((len=in.read(data))>=0){
//這裏處理你獲得的數據即可。
}
}catch(IOException
e) {
//讀信息報錯後直接關閉串口
close();
e.printStackTrace();
}
//如果len讀到-1的話,說明串口出問題了,這裏直接關閉就行了
//以下的部分自由發揮吧
close();
break;
default:
break;
}
}
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.