串口接手机,用CreateFile打开串口,WriteFile写数据,ReadFile读数据。打开串口后,用WriteFile写入“AT”,然后用ReadFile读数据。结果如果单步执行,ReadFile可以读出数据,如果直接运行,则读不出数据。请问是什么原因造成这种现象?在网上好像也见别人说过这个问题,但没找到产生这种现象的原因。

解决方案 »

  1.   

    问题原因有以下几种可能:1.你的串口程序可能不是全双工、半双工的、是单工的,双向对流同步写会有一方数据阻塞,单步调试时人的操作时间长,通信不会出现阻塞现象的
    2.CreatFile打开串口后,你初始化的串口缓冲是多少?nWriteBuffer?一般AT命令都很短的,你可以开512字节缓冲就够了
    3.串口通信最好不要让手机开机状态,因为AT命令容易打断你做好的消息封装,当手机开机初始化的时候,会发一些bind:+7等AT命令,理论上不会和你的协议产生冲突的,但是实际当中总是会打断你的通信的
    4.你可以抓TRACE监控手机端具体接受到什么消息
      

  2.   

    另外,忘了说一点,接GPRS猫是正常的,接手机就不正常了。
      

  3.   

    如何确认程序是是全双工、半双工的、或单工?我是以读写方式打开COM口的。
      

  4.   

    打开串口后,用WriteFile写入“AT”,然后用ReadFile读数据。结果如果单步执行,ReadFile可以读出数据,如果直接运行,则读不出数据。--你的写法有问题,直接写两个字节的"AT"是不行的,得加上回车:"at\r";
    至于单步执行可以,估计你打开了Modem的字符回显功能,用这个命令可以打开会关闭回显:
    关闭:ate0\r
    打开:ate1\r
      

  5.   

    TO: zhangnanonnet(鱼欢)我也考虑过这个问题,但我在读写中间加上Sleep,从100ms到数数秒,都没有效果。
      

  6.   

    我没有清空缓冲区呀,我的相关代码如下,大家帮我看看,另外,要说明的是,接GPRS MODEM时没有问题,接西门子3508就不行,它们的波特率分别为115200和19200。打开端口:
    BOOL OpenComm(HANDLE& hComm,const char* pPort , int nBaudRate , int nParity , int nByteSize , int nStopBits)
    {
    if(hComm != INVALID_HANDLE_VALUE)
    return FALSE; DCB dcb;        // 串口控制块
        COMMTIMEOUTS timeouts = {    // 串口超时控制参数
            100,        // 读字符间隔超时时间: 100 ms
            1,          // 读操作时每字符的时间: 1 ms (n个字符总共为n ms)
            500,        // 基本的(额外的)读超时时间: 500 ms
            1,          // 写操作时每字符的时间: 1 ms (n个字符总共为n ms)
            100};       // 基本的(额外的)写超时时间: 100 ms
        
        hComm = CreateFile(pPort,    // 串口名称或设备路径
                GENERIC_READ | GENERIC_WRITE,    // 读写方式
                0,               // 共享方式:独占
                NULL,            // 默认的安全描述符
                OPEN_EXISTING,   // 创建方式
                0,               // 不需设置文件属性
                NULL);           // 不需参照模板文件
        
        if(hComm == INVALID_HANDLE_VALUE) return FALSE;        // 打开串口失败
        
        GetCommState(hComm, &dcb); // 取DCB
        
        dcb.BaudRate = nBaudRate;
        dcb.ByteSize = nByteSize;
        dcb.Parity = nParity;
        dcb.StopBits = nStopBits;
        
        SetCommState(hComm, &dcb); // 设置DCB
        
        SetupComm(hComm, 4096, 1024); // 设置输入输出缓冲区大小
        
        SetCommTimeouts(hComm, &timeouts); // 设置超时
            return CheckCom(hComm);}写:
    void WriteComm(HANDLE hComm,void* pData , int nLength)
    {
    DWORD dwNumWrite;    // 串口发出的数据长度
        
        WriteFile(hComm, pData, (DWORD)nLength, &dwNumWrite, NULL);
    }读:
    int ReadComm(HANDLE hComm, void*  pData, int nLength)
    {
    DWORD dwNumRead;    // 串口收到的数据长度
        
        ReadFile(hComm, pData, (DWORD)nLength, &dwNumRead, NULL);
        
        return (int)dwNumRead;}产生问题的地方:
    BOOL CheckCom(HANDLE hComm)
    {
    int nLength; // 串口收到的数据长度
            char cmd[16]; // 命令串
             char ans[4096]; // 应答串
    char ansTmp[128];          //应答临时串 memset(cmd, 0, sizeof(cmd));
    sprintf(cmd, "AT\r");   // 生成命令  
      
             /* 此行之前设定断点,开始单步执行就不会有问题 */
    WriteComm(hComm, cmd, strlen(cmd));    // 先输出命令串 memset(ans, 0, sizeof(ans));
    do
    {
    memset(ansTmp, 0, sizeof(ansTmp));
    nLength = ReadComm(hComm, ansTmp, sizeof(ansTmp) - 1);              if(nLength > 0)
    {
    strcat(ans, ansTmp);
    }
    }while(nLength > 0);
    if(strlen(ans) > 0 && strstr(ans, "OK") != NULL)
    {
    return TRUE;
    }
    else
    {
    return FALSE;
    }
    }
      

  7.   

    在读数据之前,最好先判断是否有数据可读。下面给出我的代码供参考:
    int TagBaseComm::recTest(void)
    {
      ClearCommError(hCom, &lComStat, &comStat);
      return((int)comStat.cbInQue);
    }...
          int num = pCom->recTest();
          if( num>0 ){  // 如果有数据
             pCom->Read();
             ...
      

  8.   

    也可以下载我的DLL试试:
    http://www.bluespace.com.cn/koodoo/examples_sms.htm
      

  9.   

    谢谢楼上,你的DLL的头文件好像不是VC的吧?
      

  10.   

    波特率19200的时候出了问题,那说明你需要调整DCB的设计,我建议你调整一下SetCommTimeouts(hComm, &timeouts);中timeouts的设置,有这么一种可能,因为通讯输率比较慢,你READ等待超时已经过去,数据还没有写入BUF,你把READ超时设大一些,还有就是你为什么不把不特率调上去呢?手机的AT指令都有一条是调整波特率的,你把波特率调上去,然后shut down掉串口从新用新的波特率打开就可以了
      

  11.   

    肯定可以设定的,一般初始BUADRATE是19200,然后能网上调一直调到115200,这个波特率是通过master->slaver协商解决的,也就是我说的用修改波特率的指令完成。你最好查查你用的那款MODULE的AT指令集
      

  12.   

    19200波特率时我接的是西门子M35i,在超级终端上测试指令AT+IPR?或AT+IPR=?返回ERROR。
      

  13.   

    那说明M35I并不支持AT+IPR的指令,你应该找找M35I的指令集。看看它协商波特率是什么命令