极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 13042|回复: 3

关于arduino通过USB串口与计算机通信的一个奇怪的问题

[复制链接]
发表于 2017-2-9 21:07:04 | 显示全部楼层 |阅读模式
我的arduino是Mega2560。我在计算机上用C++,用winAPI串口函数编了一个程序,用来和Mega2560通信。通信通过USB内的虚拟串口进行。这个串口在我的计算机上显示是com5。
调试过程中发现,上位机程序和单片机是可以通信,但是有一个前提,就是每次单片机上电以后,我必须在计算机上启动arduino IDE里边的串口监视器,然后再关闭它,然后我的上位机程序才能够和单片机通信。如果我不事先启动串口监视器,看起来上位机程序可以向单片机发数据(2560的RX灯会闪),但是单片机不向计算机发送数据(tx灯不闪,计算机程序也等不到数据)。不知是否有前辈曾经有过类似的经历?这一般是怎么回事?
附上计算机上的相关源码:
  HANDLE hCom;
  hCom=CreateFile(Edit3 -> Text.c_str(),
                  GENERIC_READ|GENERIC_WRITE,
                  0,
                  NULL,
                  OPEN_EXISTING,
                  0,
                  NULL
                 );
  if(hCom==(HANDLE)-1)
  {
    Edit3 -> Text = "打开串口失败";
    return;
  }

  SetupComm(hCom,64,64);

  COMMTIMEOUTS TimeOuts;
  TimeOuts.ReadIntervalTimeout=2;
  TimeOuts.ReadTotalTimeoutMultiplier=50;
  TimeOuts.ReadTotalTimeoutConstant=100;
  TimeOuts.WriteTotalTimeoutMultiplier=500;
  TimeOuts.WriteTotalTimeoutConstant=1000;
  SetCommTimeouts(hCom,&TimeOuts);

  DCB dcb;
  GetCommState(hCom,&dcb);
  dcb.BaudRate = CBR_115200;
  dcb.ByteSize = 8;
  dcb.Parity = NOPARITY;
  dcb.StopBits = ONESTOPBIT;
  dcb.fParity = FALSE;
  SetCommState(hCom,&dcb);

  PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);
  Sleep(1000);  //wait at least900ms to wait MCU to ready

  complex Ring[200];
  int R,I,tmp1,tmp2,tmp3,tmp4;
  char lpOutBuffer[]="1200 1328 0 7 0 r";
  char str[64];
//  int i=0;
  for(int i=0;i<5;i++)
  {
    DWORD dwBytesWrite=20;
    COMSTAT ComStat;
    DWORD dwErrorFlags;
    ClearCommError(hCom,&dwErrorFlags,&ComStat);
    WriteFile(hCom,lpOutBuffer,dwBytesWrite,&dwBytesWrite,NULL);
    Sleep(50);

    DWORD wCount;
    ReadFile(hCom,str,64,&wCount,NULL);
    Label6 -> Caption = str;
    sscanf(str,"%d %d %d %d %d %d",&R,&I,&tmp1,&tmp2,&tmp3,&tmp4);
    Ring[i].R=(float)R/16.0;
    Ring[i].I=(float)I/16.0;
  }

  CloseHandle(hCom); //handle to object to close
回复

使用道具 举报

发表于 2017-2-10 20:49:13 | 显示全部楼层
能发一下单片机程序吗
谢谢
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-2-17 23:05:43 | 显示全部楼层
zjz5717 发表于 2017-2-10 20:49
能发一下单片机程序吗
谢谢

问题解决了,不过我还是不知道背后的原因。确实是单片机的问题。我把有问题的单片机程序简化了一下,是这样:
void setup() {
  Serial.begin(115200);
  //配置我的硬件电路
  delay(30);
  while(Serial.read() >= 0){;}    //读清串口
}
void loop() {
  if (Serial.available() > 0) {
    delay(2);
    N_RF = Serial.parseInt();
    N_LO = Serial.parseInt();
    F = Serial.parseInt();
    DIVA = Serial.parseInt();
    APWR_RF = Serial.parseInt();
    while(Serial.read() != 'r'){;}
    while(Serial.read() >= 0){;}
....     //根据串口收到的这些数据干活
...      //返回测试结果
}
我发现,尽管在setup里边读清了串口,可是单片机还是会因为读到了不知什么数据而死锁在了loop的第一圈,当然就不响应我的上位机程序了。当我打开并关闭串口监视器,貌似复位了一下单片机,就没问题了。
我后来在单片机程序里做了一些改进,解决了问题。改进包括两方面。第一个改进,可以理解为给每条消息加了左右括号,约束了消息格式,防止把错误的东西当做消息而死锁。第二个改进就是即使读错了消息,单片机也仍然可以一遍遍地进行loop循环,而不会陷在loop的第一圈里死在那里。
虽然问题解决了,可是我的疑问是,进入loop的第一圈,到底读到了什么。
回复 支持 反对

使用道具 举报

发表于 2017-2-17 23:45:26 | 显示全部楼层
比较复杂啊
回复 支持 反对

使用道具 举报

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

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

Archiver|联系我们|极客工坊

GMT+8, 2024-3-29 14:59 , Processed in 0.043089 second(s), 20 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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