量子隧道 发表于 2017-2-9 21:07:04

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

我的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;
int R,I,tmp1,tmp2,tmp3,tmp4;
char lpOutBuffer[]="1200 1328 0 7 0 r";
char str;
//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.R=(float)R/16.0;
    Ring.I=(float)I/16.0;
}

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

zjz5717 发表于 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的第一圈,到底读到了什么。

whitezhang 发表于 2017-2-17 23:45:26

比较复杂啊
页: [1]
查看完整版本: 关于arduino通过USB串口与计算机通信的一个奇怪的问题