极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 28503|回复: 16

串口数据读不出!开一下监视器才能读出来,求助!

[复制链接]
发表于 2013-8-16 23:50:35 | 显示全部楼层 |阅读模式
本帖最后由 海阳 于 2013-8-17 20:29 编辑

我遇到个奇怪的问题。关于串口通讯的。

串口数据读不出!开一下串口监视器再读就可以了。

MEGA 2560板,用USB线连电脑。

以下程序非常简单。

板卡每秒打印12345 到串口上,PC端每隔一秒从COM4上读并打印出来。

直接用ruby程序读,读不到数据,一直卡在readline那一行,readlines ,gets啥都不行

如果我先用IDE自带的端口监视器看一下。
再执行我的ruby代码。就可以正常运行并打印出来。


然后我重新插拔USB线。再运行我的代码。就会卡死在readlines那一行。
getc也不行。用serialport类或FILE都不行。

有高手 来指导 我一下吗?我是个初学者。谢谢啦。



  1. void setup()
  2. {
  3.   Serial.begin(9600);
  4.   
  5. }
  6. void loop()
  7. {

  8.   Serial.println(12345);
  9.   
  10.   delay(1000);
  11. }
复制代码


[pre lang="ruby" line="1"]#!/usr/bin/ruby
require 'serialport'

sp = SerialPort.new "com4", 9600
while true
puts sp.readline
  sleep 1  
end
[/code]




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

 楼主| 发表于 2013-8-17 10:00:39 | 显示全部楼层
顶下,这个应该是很常用的吧。居然我这个也搞不定。
回复 支持 反对

使用道具 举报

发表于 2013-8-17 10:04:49 | 显示全部楼层
你用的RUBY ?换个串口试试
回复 支持 反对

使用道具 举报

发表于 2013-8-17 10:30:32 | 显示全部楼层
看看板子上有没跳线,uno上有个跳线关于自动重启的,可能和这个有关。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-17 10:46:21 | 显示全部楼层
Fortware 发表于 2013-8-17 10:04
你用的RUBY ?换个串口试试

也不行啊,我换了能电脑都不行。不管是USB线,还是用蓝牙串口都一样。
只要是USB上重新插拔一次,都要开监视器再运行程序。。。太郁闷了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-17 11:12:37 | 显示全部楼层
pathletboy 发表于 2013-8-17 10:30
看看板子上有没跳线,uno上有个跳线关于自动重启的,可能和这个有关。




只有一个reset按钮。
回复 支持 反对

使用道具 举报

发表于 2013-8-17 11:51:10 | 显示全部楼层
海阳 发表于 2013-8-17 11:12
只有一个reset按钮。

我找下,上次看到过说可以关闭自动reset的功能。
回复 支持 反对

使用道具 举报

发表于 2013-8-17 12:05:33 | 显示全部楼层
参考下这个http://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection
回复 支持 反对

使用道具 举报

发表于 2013-8-17 12:06:21 | 显示全部楼层
reset口上接个上拉电阻,应该就OK。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-17 14:00:52 | 显示全部楼层
pathletboy 发表于 2013-8-17 12:06
reset口上接个上拉电阻,应该就OK。

感谢!但是我手头没有电阻。
我把读取代码改成read(10)   读前10位,是可以读到的。
readline就不行。

我怀疑,ruby不认arduino的换行符!但是用监视器一读又好了。真是太怪异了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-17 20:28:32 | 显示全部楼层
我找到问题了,是ruby读串口的方式不对。
看了ArduinoFirmata Ruby版的源码。发现根本不用readline。
直接用read 读。好吧。我自己写了一个读line的类。当然还不完善,只是解决了这个问题。

[pre lang="ruby" line="1"]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[/code]
回复 支持 反对

使用道具 举报

发表于 2013-8-18 23:48:10 | 显示全部楼层
没看监视看不到是正常的。软件经常挂掉!
回复 支持 反对

使用道具 举报

发表于 2013-8-19 18:06:33 | 显示全部楼层
奇怪,怎么这样.... 跟我用 python 操作的相反,我 python 里头如果打开 monitor, 整个就读不到数据了。

我不大懂串口, 我的实际操作经验是打开都是独占的,  我的 python 程序或者 monitor 同时只能有其一操作串口。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-20 13:27:20 | 显示全部楼层
hick 发表于 2013-8-19 18:06
奇怪,怎么这样.... 跟我用 python 操作的相反,我 python 里头如果打开 monitor, 整个就读不到数据了。

...

对,串口是独占的。
我的问题是,我的自己的程序读不到串口发来的数据。
打开其它监视器,收一下,再关掉它。
再运行自己的程序就能读到了。

不过现在已经解决了。
以前是用readline来读。可能是ruby识别不到串口来的换行符。所以读不到。
我就改成一个字节一字节地读,再自己拼成一个line。这样解决了。
回复 支持 反对

使用道具 举报

发表于 2013-8-23 12:56:19 | 显示全部楼层
贡献一下我的代码吧。

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[k+4]=code[k].to_i(16)
  end
  ss[3] = $sxh
  for k in 9..19
    ss[k]=0
  end
  ss[2] = (ss[3]+ss[4]+ss[5]+ss[6]+ss[7]+ss[8]) % 256
  ss
end

def hex_str(ss)
  str = ''
  for k in 0..ss.length-1
    str = str +  sprintf("%02X", ss[k]) + ' '
  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
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-6-4 00:33 , Processed in 0.056725 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表