串口数据读不出!开一下监视器才能读出来,求助!
本帖最后由 海阳 于 2013-8-17 20:29 编辑我遇到个奇怪的问题。关于串口通讯的。
串口数据读不出!开一下串口监视器再读就可以了。
MEGA 2560板,用USB线连电脑。
以下程序非常简单。
板卡每秒打印12345 到串口上,PC端每隔一秒从COM4上读并打印出来。
直接用ruby程序读,读不到数据,一直卡在readline那一行,readlines ,gets啥都不行
如果我先用IDE自带的端口监视器看一下。
再执行我的ruby代码。就可以正常运行并打印出来。
然后我重新插拔USB线。再运行我的代码。就会卡死在readlines那一行。
getc也不行。用serialport类或FILE都不行。
有高手 来指导 我一下吗?我是个初学者。谢谢啦。
void setup()
{
Serial.begin(9600);
}
void loop()
{
Serial.println(12345);
delay(1000);
}
#!/usr/bin/ruby
require 'serialport'
sp = SerialPort.new "com4", 9600
while true
puts sp.readline
sleep 1
end
顶下,这个应该是很常用的吧。居然我这个也搞不定。 你用的RUBY ?换个串口试试 看看板子上有没跳线,uno上有个跳线关于自动重启的,可能和这个有关。 Fortware 发表于 2013-8-17 10:04 static/image/common/back.gif
你用的RUBY ?换个串口试试
也不行啊,我换了能电脑都不行。不管是USB线,还是用蓝牙串口都一样。
只要是USB上重新插拔一次,都要开监视器再运行程序。。。太郁闷了。:L pathletboy 发表于 2013-8-17 10:30 static/image/common/back.gif
看看板子上有没跳线,uno上有个跳线关于自动重启的,可能和这个有关。
http://arduino.cc/en/uploads/Main/ArduinoMega2560_R3_Front.jpg
只有一个reset按钮。 海阳 发表于 2013-8-17 11:12 static/image/common/back.gif
只有一个reset按钮。
我找下,上次看到过说可以关闭自动reset的功能。 参考下这个http://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection reset口上接个上拉电阻,应该就OK。 pathletboy 发表于 2013-8-17 12:06 static/image/common/back.gif
reset口上接个上拉电阻,应该就OK。
感谢!但是我手头没有电阻。
我把读取代码改成read(10) 读前10位,是可以读到的。
readline就不行。
我怀疑,ruby不认arduino的换行符!但是用监视器一读又好了。真是太怪异了。 我找到问题了,是ruby读串口的方式不对。
看了ArduinoFirmata Ruby版的源码。发现根本不用readline。
直接用read 读。好吧。我自己写了一个读line的类。当然还不完善,只是解决了这个问题。
class SerialPortReader
def readline
sp = SerialPort.open("com4", 9600 , 8,1,SerialPort::NONE) do |sp|
line =""
while true
c = sp.read(1)
line = line + c
if c=="\n"
#这里留个位,用块处理line
yield line
line = ""
end
end
end
end
end 没看监视看不到是正常的。软件经常挂掉! 奇怪,怎么这样.... 跟我用 python 操作的相反,我 python 里头如果打开 monitor, 整个就读不到数据了。
我不大懂串口, 我的实际操作经验是打开都是独占的,我的 python 程序或者 monitor 同时只能有其一操作串口。 hick 发表于 2013-8-19 18:06 static/image/common/back.gif
奇怪,怎么这样.... 跟我用 python 操作的相反,我 python 里头如果打开 monitor, 整个就读不到数据了。
...
对,串口是独占的。
我的问题是,我的自己的程序读不到串口发来的数据。
打开其它监视器,收一下,再关掉它。
再运行自己的程序就能读到了。
不过现在已经解决了。
以前是用readline来读。可能是ruby识别不到串口来的换行符。所以读不到。
我就改成一个字节一字节地读,再自己拼成一个line。这样解决了。
贡献一下我的代码吧。
require 'serialport'
sp = SerialPort.new "com3", 9600
#sp = SerialPort.new "/dev/tty.PL2303-00002006", 9600
puts "serial opened"
$sxh = 50
def set_k(cmd)
ss="\n\r\00645678901234567890"
$sxh = ($sxh+1) % 128
$sxh = $sxh+1 if $sxh==10 || $sxh == 13
code = cmd.split(' ')
for k in 0..code.size-1
ss=code.to_i(16)
end
ss = $sxh
for k in 9..19
ss=0
end
ss = (ss+ss+ss+ss+ss+ss) % 256
ss
end
def hex_str(ss)
str = ''
for k in 0..ss.length-1
str = str +sprintf("%02X", ss) + ' '
end
str
end
Thread.new {
while true do
ss = sprintf("%02X ", sp.getc)
if ss == "0A "
puts "New Frame:"
k = 0
end
k = k+1
puts "#{k}: #{ss}"
end
}
#0A 0D 99 34 F2 50 22 01 00 00 00 00 00 00 00 00 00 00 00 00
while (l = gets) do
l = l.chomp
if l == "exit"
exit
elsif l == "open"
ss=set_k("F2 50 22 01 00")
puts("#{Time.now.to_f}:#{hex_str(ss)}")
sp.write(ss)
elsif l == "close"
ss=set_k("F2 50 22 00 00")
puts("#{Time.now.to_f}:#{hex_str(ss)}")
sp.write(ss)
else
puts("#{Time.now.to_f}:#{hex_str(l.sub("\n", "\r"))}")
sp.write(l.sub("\n", "\r"))
end
end
sp.close
页:
[1]
2