bcb 6 win7 下 用API做 串口收发的问题

sinozw 2019-05-23 09:03:59
代码是网上找的,如下:

1.定义变量

bool ComState = FALSE;   //串口状态
HANDLE hCom = 0;           //串口打开返回值
DCB dcb;
OVERLAPPED OverRead, OverWrite;
COMSTAT comstat;
OVERLAPPED os;
DWORD dwEvtMask=0;
String dat;
HANDLE m_pThread;

COMMTIMEOUTS ComTimeouts;

char ReadBuff[1024];        //读缓冲区
DWORD ReadCount;        //读字节数

2.串口初始化

void __fastcall TForm1::btn1ClickSerialPortInit(TObject *Sender)
{
              
        if(FALSE == ComState)
        {
               hCom=CreateFile( "COM3", //文件名
                             GENERIC_READ|GENERIC_WRITE,//访问模式允许读写
                             0, //此项必须是0
                             NULL,//无安全参数
                             OPEN_EXISTING,//创建方式
                          //   FILE_FLAG_OVERLAPPED,//异步工作方式
                            0,
                             NULL);
            if (hCom==INVALID_HANDLE_VALUE)
            {
                    ShowMessage("Can not open the port !");
                    CloseHandle(hCom);
                    hCom = 0;

            }

            if(!GetCommState(hCom,&dcb)) //获得串口设置并用它填充dcb结构体
            {
                ShowMessage("GetCommState failed");
            }      

            if (!SetupComm(hCom,1024,1024)) //设置输入输出缓冲区大小
            {
                ShowMessage("SetupComm failed");
            }

            // 设置接收超时限定

            ComTimeouts.ReadIntervalTimeout = MAXDWORD;
            ComTimeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
            ComTimeouts.ReadTotalTimeoutConstant = 1000;
            SetCommTimeouts(hCom,&ComTimeouts);


            //设置dcb结构成员变量
            dcb.BaudRate=115200;
            dcb.fParity=0;
            dcb.Parity=NOPARITY;
            dcb.StopBits=ONESTOPBIT;
            dcb.ByteSize=8;
            dcb.fNull=FALSE;

            if(!SetCommState(hCom,&dcb)) //重新配置串口
            {
                ShowMessage("SetCommState failed");
            }

            //清空串口缓冲区,退出所有相关操作
            PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);
            Form1->Caption=comname+" 通信成功!";
ComState = TRUE;
            btn1->SetTextBuf("关闭串口");
        }
        else
        {
            CloseHandle(hCom);

            ComState = FALSE;
            btn1->SetTextBuf("打开串口");
        }


}

2.发送函数

void __fastcall TForm1::btn2ClickSendData(TObject *Sender)
{
         //发送数据
        BOOL WriteState;
        unsigned long Written ;
        DWORD dwError;

        int Size = EditSndData->GetTextLen(); //Get length of string in Edit1
        char *p = new char[Size];               //Creates Buffer dynamic variable
   //分配内存,必须有,要不然程序会出现错误
        EditSndData->GetTextBuf(p,Size);

        WriteState = WriteFile(hCom,//用CreateFile 获得的文件句柄
                                p,//输出缓冲区首址
                                Size,//要求输出的字节数
                                &Written,//实际输出字节数
                                &OverWrite);//重叠操作方式数据结构地址

        if (WriteState && GetLastError()== ERROR_IO_PENDING )
        {
             ShowMessage("Error !!!");
        }   
}

3.接收数据(定时查询接收)

void __fastcall TForm1::tmr1TimerReceiveData(TObject *Sender)
{
             //TODO: Add your source code here
 
        DWORD nBytesRead, dwEvent, dwError;
          COMSTAT cs; // 用于存放串口状态

          if(hCom==INVALID_HANDLE_VALUE) return;
          ClearCommError(hCom,&dwError,&cs);
          if(cs.cbInQue>sizeof(ReadBuff))
          {
                PurgeComm(hCom, PURGE_RXCLEAR);
                 return;
          } // 数据多于缓冲区?是:接收数据无效,清除
          ReadFile (hCom, ReadBuff, cs.cbInQue, &nBytesRead,
          NULL); // 读取接收数据
            ReadBuff[cs.cbInQue] = '\0';
          if(cs.cbInQue > 0)
          {
                 EditRcvData->Text = ReadBuff; // 将数据显示出来
          }
        
}


上述代码在bcb6,win7下编译,发现有3个问题

1、接收的数据存在丢帧现象。用串口助手每次都接收到76条,用该软件收到60左右。(有时是59,有时是60,有时是61)
2、初始化串口后,点发送按钮后报错 依次为“Can not open the port”“GetCommState failed”"SetupComm failed" "GetCommState failed"
3、把发送代码合并到到 btn1ClickSerialPortInit(TObject *Sender) 里面,不报错,但也没有发送。

请哪位朋友知道是什么原因?如果谁有bcb 6 win7 能运行的 基于API的串口 收发程序,也请发我一份参考,sinozw@163.com 谢谢。
...全文
219 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
vc_dreamver 2019-06-05
  • 打赏
  • 举报
回复
1、在调用GetCommState之前,对传入的结构体成员DCBlength做一个初始化。 dcb.DCBlength = sizeof(dcb);这样试试。 2、关于丢帧现象,你创建端口句柄的时候没有使用重叠方式。 hCom=CreateFile( "COM3", //文件名 GENERIC_READ|GENERIC_WRITE,//访问模式允许读写 0, //此项必须是0 NULL,//无安全参数 OPEN_EXISTING,//创建方式 // FILE_FLAG_OVERLAPPED,//异步工作方式 0, NULL); 但是在发送数据的时候却用了重叠方式。 WriteState = WriteFile(hCom,//用CreateFile 获得的文件句柄 p,//输出缓冲区首址 Size,//要求输出的字节数 &Written,//实际输出字节数 &OverWrite);//重叠操作方式数据结构地址 不过我不清楚这样有没有使用问题 :D,没试过。 另外,char *p = new char[Size]; 这个数据分配了内存也没有释放。 另外,不知道发送的数据量大不大,频率怎么样,还有定时器里的周期是多少。 如果数据量比较频率,可以采用线程接收一下。 下面这代码去掉看看。 //---------------------------------------------------------------- ClearCommError(hCom,&dwError,&cs); if(cs.cbInQue>sizeof(ReadBuff)) { PurgeComm(hCom, PURGE_RXCLEAR); return; } // 数据多于缓冲区?是:接收数据无效,清除 //---------------------------------------------------------------------
xdn1ce 2019-05-23
  • 打赏
  • 举报
回复
CreateFile 第一个参数 传一个指针试一下。


 if (hCom==INVALID_HANDLE_VALUE)
{
ShowMessage("Can not open the port !");
//CloseHandle(hCom); //打开失败,无效指针
hCom = 0;
return; //打开串口失败,就直接退出,继续往下 也是报更多错

}
zhgwbzhd 2019-05-23
  • 打赏
  • 举报
回复
ReadFile (hCom, ReadBuff, cs.cbInQue, &nBytesRead,
NULL); // 读取接收数据
ReadBuff[cs.cbInQue] = '\0';
if(cs.cbInQue > 0)
{
EditRcvData->Text = ReadBuff; // 将数据显示出来
}

这么处理是不是不合理?如果在数据中遇到空字符(非空格),这样直接就断开了。

1,221

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧