WIN32 API 串口编程

1、打开串口

void CMyTestDlg::OnBnClickedBtnOpenCom() { CString str; if (GetDlgItemText(IDC_BTN_OPEN_COM, str), str == L"打开串口") { if (pMyComInfo->hCom) { return; } pMyComInfo->hCom = CreateFile(pMyComInfo->sComNumber[pMyComInfo->iComNumber], GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (pMyComInfo->hCom == INVALID_HANDLE_VALUE) { pMyComInfo->hCom = NULL; MessageBox(L"打开"+pMyComInfo->sComNumber[pMyComInfo->iComNumber] + L"失败"); return; } //指定端口监测的事件集 SetCommMask(pMyComInfo->hCom, EV_RXCHAR);//设置事件驱动的类型 //分配设备缓冲区 SetupComm(pMyComInfo->hCom, 51200, 512); // 设置接收与发送的缓冲区大小 //初始化缓冲区中的信息 PurgeComm(pMyComInfo->hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);//清干净输入、输出缓冲区 //配置串行端口 if(!InitDCB()) { return; } //设置端口超时值 if(!InitCommTimeouts()) { return; } //设置端口上指定信号的状态 // SETDTR: 发送DTR (data-terminal-ready)信号 // SETRTS: 发送RTS (request-to-send)信号 EscapeCommFunction(pMyComInfo->hCom, SETDTR); EscapeCommFunction(pMyComInfo->hCom, SETRTS); //创建串口接收线程 DWORD dwThreadID; pMyComInfo->hMyComRecvThread = CreateThread( (LPSECURITY_ATTRIBUTES) NULL, 0,(LPTHREAD_START_ROUTINE)MyRecvComProc,this,0, &dwThreadID); if (NULL == pMyComInfo->hMyComRecvThread) { OnBnClickedBtnOpenCom(); MessageBox(L"创建串口接收线程失败"); return; } pMyComInfo->bMyBuffToUsersProcessorStatus = 0; pMyComInfo->bComWorkStatus = TRUE; SendMessage(WM_PAINT, 0, 0); SetDlgItemText(IDC_BTN_OPEN_COM, L"关闭串口"); } else { CloseCom(); pMyComInfo->bComWorkStatus = FALSE; SendMessage(WM_PAINT, 0, 0); SetDlgItemText(IDC_BTN_OPEN_COM, L"打开串口"); } }

2、 关闭串口代码

void CMyTestDlg::CloseCom(void) { if (pMyComInfo->hMyComRecvThread) { TerminateThread(pMyComInfo->hMyComRecvThread,0); CloseHandle(pMyComInfo->hMyComRecvThread); } //清除端口上指定信号的状态 EscapeCommFunction(pMyComInfo->hCom,CLRDTR); EscapeCommFunction(pMyComInfo->hCom,CLRRTS); //清除驱动程序内部的发送和接收队列 PurgeComm(pMyComInfo->hCom,PURGE_TXCLEAR|PURGE_RXCLEAR); //关闭串口 CloseHandle(pMyComInfo->hCom); pMyComInfo->hCom = NULL; }

3、初始化DCB

BOOL CMyTestDlg::InitDCB(void) { DCB PortDCB; // DWORD dwError; PortDCB.DCBlength = sizeof (DCB); //得到端口的默认设置信息 GetCommState(pMyComInfo->hCom, &PortDCB); //改变DCB结构设置 PortDCB.BaudRate = _wtoi(pMyComInfo->sComBaudrate[pMyComInfo->iComBaudrate]); //波特率 PortDCB.fBinary = TRUE; //Win32不支持非二进制串行传输模式,必须为TRUE PortDCB.fParity = FALSE; //启用奇偶校验 PortDCB.fOutxCtsFlow = FALSE; //串行端口的输出由CTS线控制 PortDCB.fOutxDsrFlow = FALSE; //关闭串行端口的DSR流控制 PortDCB.fDtrControl = DTR_CONTROL_DISABLE; //启用DTR线 PortDCB.fDsrSensitivity = FALSE; //如果设为TRUE将忽略任何输入的字节,除非DSR线被启用 //PortDCB.fTXContinueOnXoff = TRUE; //当为TRUE时,如果接收缓冲区已满且驱动程序已传送XOFF字符,将使驱动程序停止传输字符 PortDCB.fTXContinueOnXoff = FALSE; PortDCB.fOutX = FALSE; //设为TRUE指定XON/XOFF控制被用于控制串行输出 PortDCB.fInX = FALSE; //设为TRUE指定XON/XOFF控制被用于控制串行输入 PortDCB.fErrorChar = FALSE; //WINCE串行驱动程序的默认执行将忽略这个字段 PortDCB.fNull = FALSE; //设为TRUE将使串行驱动程序忽略收到的空字节 PortDCB.fRtsControl = RTS_CONTROL_DISABLE; //启用RTS线 PortDCB.fAbortOnError = FALSE; //WINCE串行驱动程序的默认执行将忽略这个字段 PortDCB.ByteSize = _wtoi(pMyComInfo->sComDataBit[pMyComInfo->iComDataBit]); //每字节的位数 PortDCB.Parity = NOPARITY; //无奇偶校验 PortDCB.StopBits = ONESTOPBIT; //每字节一位停止位 //根据DCB结构配置端口 if (!SetCommState(pMyComInfo->hCom, &PortDCB)) { //不能配置串行端口 MessageBox(L"不能配置串行端口"); return FALSE; } return TRUE; }

 

4、设置读写超时

BOOL CMyTestDlg::InitCommTimeouts(void) { COMMTIMEOUTS CommTimeouts; // DWORD dwError; //得到超时参数 GetCommTimeouts(pMyComInfo->hCom, &CommTimeouts); //改变COMMTIMEOUTS结构设置 CommTimeouts.ReadIntervalTimeout = MAXDWORD; CommTimeouts.ReadTotalTimeoutMultiplier = 0; CommTimeouts.ReadTotalTimeoutConstant = 0; CommTimeouts.WriteTotalTimeoutMultiplier = 0; CommTimeouts.WriteTotalTimeoutConstant = 0; //设置端口超时值 if (!SetCommTimeouts(pMyComInfo->hCom, &CommTimeouts)) { //不能设置超时值 MessageBox(L"不能设置超时值"); return FALSE; } return TRUE; }

 

5、写函数

5void CMyTestDlg::WriteToCom(BYTE *p, UINT len) { if (pMyComInfo->hCom) { DWORD bufSendLength; BOOL fWriteState; fWriteState=WriteFile(pMyComInfo->hCom, p, len, &bufSendLength, NULL); if (!fWriteState || bufSendLength == 0) { MessageBox(L"不能写入数据"); } } }

 

 

6、读函数

DWORD CMyTestDlg::MyRecvComProc(LPVOID lprama) { BOOL fReadState; DWORD dwCommModemStatus; DWORD dwLength; COMSTAT ComStat; DWORD dwErrorFlags; BYTE recvBuf[256]; CMyTestDlg *pDlg = (CMyTestDlg*)lprama; if (!pMyComInfo->hCom || pMyComInfo->hCom == INVALID_HANDLE_VALUE) { pDlg->MessageBox(L"创建串口读线程失败"); return 0; } while (pMyComInfo->hCom) { /*................................................................. //等待串口的事件发生 //WaitCommEvent(pMyComInfo->hCom, &dwCommModemStatus, 0); //if ((dwCommModemStatus & EV_RXCHAR) == EV_RXCHAR) ->当调用WriteFile() ->会发生WriteFile()不会返回 *.................................................................*/ { ClearCommError(pMyComInfo->hCom,&dwErrorFlags,&ComStat); //cbInQue返回在串行驱动程序输入队列中的字符数 dwLength=ComStat.cbInQue; if(dwLength>0) { //从串口读取数据 fReadState=ReadFile(pMyComInfo->hCom,recvBuf,256,&dwLength,NULL); if(fReadState) { pDlg->OnCommRecv(pDlg,recvBuf,dwLength); } } } GetCommModemStatus (pMyComInfo->hCom, &dwCommModemStatus); } pMyComInfo->hMyComRecvThread = NULL; return 0; }

注意:  

/*.................................................................
  //等待串口的事件发生
  //WaitCommEvent(pMyComInfo->hCom, &dwCommModemStatus, 0);
  //if ((dwCommModemStatus & EV_RXCHAR) == EV_RXCHAR)    

 

                      ->当调用WriteFile()
                     ->会发生WriteFile()不会返回
  *.................................................................*/

 

你可能感兴趣的:(WIN32 API 串口编程)