第一幅图是我自己写的软件的串口流程;
这个流程是我自己的软件的流程;第二幅图是另一个比较成熟的软件的流程;都是用串口监视精灵进行检测的;
可以看到,在第一图中,高亮显示的部分,两次设置了波特率,但是值却改变了,导致我无法对下位机进行读取;
第二图则是在利用别人的软件打开过一次后,再利用我自己的软件进行读取之后的流程;
很明显的,波特率被改变了,而我现在无法找到是哪里的设置错误;
导致我每次在一个新的串口使用时,都得先用其他软件读取一次,将串口的数据进行设置,然后才可以用自己的软件进行读取,而不这样的话,就无法正确读取了。望各位路过的帮忙看看哪里的错误以下是comm口的打开函数BOOL CSerial::OpenComm(int nPort,LONG32 nPaud,char parity /* =  */, 
  DWORD dwCommEvents /* = EV_RXCHAR */,UINT databits /* = 8 */, UINT stopbits /* = 1 */)
{
COMMTIMEOUTS tous;
DCB dcb;
CString strComm;
memset(&tous,0,sizeof(tous));
tous.ReadIntervalTimeout = MAXWORD;
tous.ReadTotalTimeoutMultiplier       =       1000       ;    tous.ReadTotalTimeoutConstant       =       1000       ;    tous.WriteTotalTimeoutMultiplier       =       1000;    tous.WriteTotalTimeoutConstant       =       1000       ;    if (nPort >=10)
{
strComm.Format(_T("\\\\.\\%d"),nPort);
}
else
strComm.Format(_T("COM%d"),nPort); m_hComm = CreateFile(strComm,GENERIC_READ|GENERIC_WRITE,0,
NULL,OPEN_EXISTING,0,NULL);
if (m_hComm!=INVALID_HANDLE_VALUE)
{
GetCommState(m_hComm,&dcb);
dcb.BaudRate = nPaud;
dcb.Parity = parity;
dcb.fOutxCtsFlow = dcb.fOutxDsrFlow = 0;
dcb.fOutX = dcb.fInX = 0;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fDtrControl = DTR_CONTROL_ENABLE; dcb.ByteSize = databits;
dcb.StopBits = stopbits; dcb.XonLim = 512;
dcb.XoffLim = 1; SetCommState(m_hComm,&dcb);
SetupComm(m_hComm,2048,2048);
SetCommTimeouts(m_hComm,&tous);
EscapeCommFunction(m_hComm,SETDTR);
EscapeCommFunction(m_hComm,SETRTS); //  PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
m_nPaud = nPaud;
m_nPort = nPort;
return TRUE;
}
return FALSE;

解决方案 »

  1.   

    if (nPort >=10)
        {
            strComm.Format(_T("\\\\.\\%d"),nPort);
        }
        else
            strComm.Format(_T("COM%d"),nPort);我记得串口超过10也可以用COM10,COM11等来设置,你先去掉判断试试:
    strComm.Format(_T("COM%d"),nPort);
      

  2.   

    另外:
    tous.ReadTotalTimeoutMultiplier       =       1000       ;       tous.ReadTotalTimeoutConstant       =       1000       ;       tous.WriteTotalTimeoutMultiplier       =       1000;       tous.WriteTotalTimeoutConstant       =       1000       ; 
    把这几个值设成再大些试试,1ms好象太小了(和波特率有关),比如60000
    同时,DCB还有一个属性binary,这个是二进制传输,也要设上,并去掉下面几句,使用默认的值:
    dcb.fOutxCtsFlow = dcb.fOutxDsrFlow = 0;
    dcb.fOutX = dcb.fInX = 0;
    dcb.fRtsControl = RTS_CONTROL_ENABLE;
    dcb.fDtrControl = DTR_CONTROL_ENABLE;
    dcb.XonLim = 512;
    dcb.XoffLim = 1;
      

  3.   

    刚按照 hdg3707 说的进行了修改,虽然好像还是老样子。更多的是,我这样子进行设置,却重复出现了两次的baudrate设置,即第一图中,baudrate到lineControl这里,这一步是进行了两次的设置,
    在代码中,是在
    SetCommState
    之后,被重复了,若是我的opencomm函数是在某个我不知道的地方也被调用的话,那也应该是整个被
    调用,而不是在
    SetCommState
    之前的步骤进行重复;
    还有关于
    COMMTIMEOUTS tous;
    这几个值得设置,一般来说,我上面的设置数值应该是够了,应该在第二幅图中,它是可以进行通讯的;但还是很感谢hdg3707提供的思路
      

  4.   

    从哪里看出来自动了??我还不会这么高端的用法
    只知道被什么地方给又设置了一次SetCommState,并且估计还是以默认值的形式进行设置的感谢  schlafenhamster 的捧场
      

  5.   

    不是  这都是我的软件里面的设置的波特率,而且下位机的波特率是固定的,不是非固定,
    呵呵,这个是我没说清楚。
    下位机的串口波特率是已经固定好的了,这点应该不用担心,现在是,另外一个软件,虽然功能是相同的,但是是其他公司的软件,而我要发布给其他客户的话,肯定不能拿别人家的软件发给别人吧,于是就是让我来COPY这么一个功能软件,而原始的软件代码,我的手头有比较早期的版本,现行的版本虽然手头没有,但是以前也看过,关于串口的设置是没啥变化的。
    下面这图是另一个软件打开串口时的流程下面是人家的opencomm函数
    BOOL CSerial::OpenComm(int port, long baud)
    {
    COMMTIMEOUTS touts;
    DCB dcb;
    CString fileComName;
    memset(&touts,0,sizeof(touts));
    touts.ReadIntervalTimeout = MAXDWORD;
    if(port>=10)
    fileComName.Format("\\\\.\\COM%d",port);
    else
    fileComName.Format("COM%d",port);
    m_hComm = CreateFile(fileComName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
    if(m_hComm != INVALID_HANDLE_VALUE)
    {
    GetCommState(m_hComm,&dcb); dcb.BaudRate = baud;
    dcb.Parity = NOPARITY;
    dcb.fOutxCtsFlow= dcb.fOutxDsrFlow=0;
    dcb.fOutX = dcb.fInX = 0;
    dcb.fRtsControl = RTS_CONTROL_ENABLE; //RTS_CONTROL_DISABLE;
    dcb.fDtrControl = DTR_CONTROL_ENABLE; //DTR_CONTROL_DISABLE;
    dcb.ByteSize = 8;
    dcb.StopBits = ONESTOPBIT;
    SetCommState(m_hComm,&dcb); SetupComm(m_hComm,3600,3600);
    SetCommTimeouts(m_hComm,&touts); EscapeCommFunction(m_hComm,SETDTR);
    EscapeCommFunction(m_hComm,SETRTS); //set DTR & RTS high
    // EscapeCommFunction(m_hComm,CLRDTR);
    // EscapeCommFunction(m_hComm,CLRRTS);
    return TRUE;
    }
    return FALSE;
    }
      

  6.   

    你是说几个软件,分别设置了不同的波特率 ?
    那样的话要hook CreateFile(A,W) 在你的 SetupComm 中返回 波特率。
      

  7.   

    不是不是  
    我的意思是,这两个软件,都是实现同样的功能,但是其中功能比较完善的,同时也是我要复制人家功能的那个软件,是有版权的,只提供给我们内部使用,所以不能对外发布啊;
    而我自己写的这个,是属于我们公司的,用于发布给客户,版权是我们自己的;
    这两个软件,都可以对同一个下位机进行操作,下位机的波特率是同样的,都是115200,不变的;
    只是我写的软件,现在出现了这个问题,但是我的串口类基本上是照搬人家的,同样的情况下,却产生了我这种错误,这才是让我疑惑的地方
    在以上的代码中,当执行到
          SetCommState(m_hComm,&dcb);
      
    时设置断点,串口设置就会如图1那样,设置了两次,而且第二次还会把我传入的数值进行改变,导致我无法通讯
      

  8.   

    断点时再看看 dcb 为何值?
      

  9.   

    当我在
    SetCommState(m_hComm,&dcb);
    GetCommState(m_hComm,&dcb);    //新增发现确实再次获取到的DCB的值变化了,一个是波特率,还有一个是parity
    这为啥啊
      

  10.   

    关闭所以使用comm的程序,试试
      

  11.   

    只运行我写的程序的话,也是会有同样的问题的,即便关了串口监视工具唉   这个问题真是有点莫名其妙这个下午 多谢 schlafenhamster 的思路了
      

  12.   

    刚试验了一下,将串口的设置弄成简单直接点,在监视工具上,不会再出现重复设置的现象,虽然不知道是什么缘由,但看来,多余的设置,有时还是有麻烦的,还是得尽量精简设置的部分 if (m_hComm!=INVALID_HANDLE_VALUE)
    {
    m_nPaud = nPaud;
    m_nPort = nPort;
    GetCommState(m_hComm,&dcb);//  dcb.fBinary = 1; dcb.BaudRate = nPaud;
    dcb.Parity = NOPARITY;
    dcb.StopBits = ONESTOPBIT;
    dcb.ByteSize = 8; SetCommState(m_hComm,&dcb);
    GetCommState(m_hComm,&dcb); SetupComm(m_hComm,2048,2048);
    SetCommTimeouts(m_hComm,&tous); EscapeCommFunction(m_hComm,SETDTR);
    EscapeCommFunction(m_hComm,SETRTS); //  PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
    return TRUE;
    }