主頁 > 軟體工程 > MFC撰寫的串口通訊程式接收不到資料

MFC撰寫的串口通訊程式接收不到資料

2020-09-13 15:03:41 軟體工程

我自己用MFC寫的上位機里面有一個串口通訊模塊,可以正常用上位機發送資料給單片機,但是卻接收不到單片機傳來的資料,除此之外用串口通訊助手也試驗了下,發現可以正常發送和接收資料。DEBUG后發現WaitCommEvent()這里沒有接收到任何串口通訊的訊息,不知道哪里出了問題,咨詢下各位大佬。

PS:在上位機的串口通訊模塊代碼如下所示:
CCommox::CCommox(void)
{
memset(&osWrite, 0, sizeof(osWrite));
COMFile = NULL;
osWrite.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (osWrite.hEvent == NULL) {
AfxMessageBox(_T("建立事件失敗!"));
}
memset(&osRead, 0, sizeof(OVERLAPPED));
osRead.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (osRead.hEvent == NULL) {
AfxMessageBox(_T("建立事件失敗!"));
}
memset(lpInBuffer, 0, sizeof(lpInBuffer));
}


CCommox::~CCommox(void)
{
}

bool CCommox::OpenSerialPort(int COMx)
{
DCB dcb;
BOOL fRetVal;
COMMTIMEOUTS CommTimeOuts;
CString szCom;
szCom.Format(_T("\\\\.\\COM%d"), COMx);
COMFile = CreateFile(szCom.GetBuffer(50), GENERIC_READ | GENERIC_WRITE,//可讀、可寫
FILE_SHARE_READ | FILE_SHARE_WRITE, // 不共享FILE_SHARE_READ,FILE_SHARE_WRITE,FILE_SHARE_DELETE
NULL, // 無安全描
OPEN_EXISTING, //打開已存在檔案
/*FILE_ATTRIBUTE_NORMAL | */FILE_FLAG_OVERLAPPED, // 檔案屬性,如果想把串口設定成異步方式,那么要設定成FILE_FLAG_OVERLAPPED
NULL//一個有效的句柄,已存在的設備句柄A valid handle to a template file with the GENERIC_READ access right
);
if (INVALID_HANDLE_VALUE == COMFile/*COMFileTemp*/) {
return (FALSE);
}
// 設定緩沖區,輸入/輸出大小(位元組數)
SetupComm( /*COMFileTemp*/COMFile, 512, 512);
// 指定監視事件_收到字符放入緩沖區
SetCommMask(/*COMFileTemp*/COMFile, EV_RXCHAR); //EV_RXCHAR:輸入緩沖區中已收到資料,即接收到一個位元組并放入輸入緩沖區。


CommTimeOuts.ReadIntervalTimeout =-1 /*0xFFFFFFFF*/; //管理單個字符的讀時限,表示從讀操作(即ReadFile)啟動開始每a毫秒內能讀到下一個字符(包括第一個字符),則OK,否則回傳。
CommTimeOuts.ReadTotalTimeoutMultiplier = -1; //
CommTimeOuts.ReadTotalTimeoutConstant = -2;
CommTimeOuts.WriteTotalTimeoutMultiplier = 2 * CBR_115200 / 115200;
CommTimeOuts.WriteTotalTimeoutConstant = 0;
//給定串口讀與操作限時
SetCommTimeouts(/*COMFileTemp*/COMFile, &CommTimeOuts);

//設定串口引數:波特率=115200;停止位 1個;無校驗;8位
dcb.DCBlength = sizeof(DCB);
GetCommState( /*COMFileTemp*/COMFile, &dcb);
dcb.BaudRate = CBR_115200;//原來是9200,現在被我改了115200
dcb.StopBits = ONESTOPBIT;
dcb.Parity = NOPARITY;
dcb.ByteSize = 8;
dcb.fBinary = TRUE;//二進制通信, 非字符通信
dcb.fOutxDsrFlow = 0;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fOutxCtsFlow = 0;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fInX = dcb.fOutX = 1;
dcb.XonChar = 0X11;
dcb.XoffChar = 0X13;
dcb.XonLim = 100;
dcb.XoffLim = 100;
dcb.fParity = TRUE;

//根據設備控制塊配置通信設備
fRetVal = SetCommState(/*COMFileTemp*/COMFile, &dcb); //如果函式呼叫成功,則回傳值為非0;若函式呼叫失敗,則回傳值為0。

if (!fRetVal) return FALSE;

//刷清緩沖區
PurgeComm( /*COMFileTemp*/COMFile, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

//指定串口執行擴展功能
EscapeCommFunction( /*COMFileTemp*/COMFile, SETDTR);

//  //設定串口 “收到字符放入緩沖區”事件
/*  if (!SetCommMask(COMFile, EV_RXCHAR )) 
return ( FALSE );*/

return TRUE;
}

bool CCommox::CloseSerialPort(int COMx)
{
//禁止串行埠所有事件
SetCommMask(COMFile, 0);

//清除資料終端就緒信號
EscapeCommFunction(COMFile, CLRDTR);

//丟棄通信資源的輸出或輸入緩沖區字符并終止在通信資源上掛起的讀、寫操//場作 
PurgeComm(COMFile, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

CloseHandle(COMFile);
COMFile = NULL;
return true;
}

bool CCommox::TransmitData(PBYTE pOutData, int nDataLen)
{
if (NULL == pOutData || nDataLen < 1)
return FALSE;
//while(nDataLen > 0){
DWORD nLen = 0;
if (!WriteFile(COMFile, (LPCVOID)pOutData, nDataLen, &nLen, &/*ShareEvent*/osWrite)) {//引數從左到右分別為句柄、資料緩沖區指標、寫入的位元組數、用于保存實際寫入的位元組數的存盤區域,用于判斷是否讀取成功、
  //OVERAPPED結構體指標,一般取NULL
if (WAIT_OBJECT_0 == WaitForSingleObject(osWrite.hEvent, 0xffffff))
ResetEvent(osWrite.hEvent);
else
ResetEvent(osWrite.hEvent);
}
return true;
}

void CCommox::QueryKey(HKEY hKey)
{
#define MAX_KEY_LENGTH 255
#define MAX_VALUE_NAME 16383
// TCHAR    achKey[MAX_KEY_LENGTH];   // buffer for subkey name
// DWORD    cbName;                   // size of name string 
TCHAR    achClass[MAX_PATH] = TEXT("");  // buffer for class name 
DWORD    cchClassName = MAX_PATH;  // size of class string 
DWORD    cSubKeys = 0;               // number of subkeys 
DWORD    cbMaxSubKey;              // longest subkey size 
DWORD    cchMaxClass;              // longest class string 
DWORD    cValues;              // number of values for key 
DWORD    cchMaxValue;          // longest value name 
DWORD    cbMaxValueData;       // longest value data 
DWORD    cbSecurityDescriptor; // size of security descriptor 
FILETIME ftLastWriteTime;      // last write time 

DWORD i, retCode;

TCHAR  achValue[MAX_VALUE_NAME];
DWORD cchValue = MAX_VALUE_NAME;

// Get the class name and the value count. 
retCode = RegQueryInfoKey(
hKey,                    // key handle 
achClass,                // buffer for class name 
&cchClassName,           // size of class string 
NULL,                    // reserved 
&cSubKeys,               // number of subkeys 
&cbMaxSubKey,            // longest subkey size 
&cchMaxClass,            // longest class string 
&cValues,                // number of values for this key 
&cchMaxValue,            // longest value name 
&cbMaxValueData,         // longest value data 
&cbSecurityDescriptor,   // security descriptor 
&ftLastWriteTime);       // last write time 

 // Enumerate the subkeys, until RegEnumKeyEx fails.

 //  if (cSubKeys)
 //  {
 //  printf( "\nNumber of subkeys: %d\n", cSubKeys);
 // 
 //  for (i=0; i<cSubKeys; i++) 
 //  { 
 //  cbName = MAX_KEY_LENGTH;
 //  retCode = RegEnumKeyEx(hKey, i,
 //  achKey, 
 //  &cbName, 
 //  NULL, 
 //  NULL, 
 //  NULL, 
 //  &ftLastWriteTime); 
 //  if (retCode == ERROR_SUCCESS) 
 //  {
 //  _tprintf(TEXT("(%d) %s\n"), i+1, achKey);
 //  }
 //  }
 //  } 

 // Enumerate the key values. 
if (cValues > 0) {
for (i = 0, retCode = ERROR_SUCCESS; i < cValues; i++) {
cchValue = MAX_VALUE_NAME;  achValue[0] = '\0';
if (ERROR_SUCCESS == RegEnumValue(hKey, i, achValue, &cchValue, NULL, NULL, NULL, NULL)) {
CString szName(achValue);
if (-1 != szName.Find(_T("Serial")) || -1 != szName.Find(_T("VCom"))) {
BYTE strDSName[10]; memset(strDSName, 0, 10);
DWORD nValueType = 0, nBuffLen = 10;
if (ERROR_SUCCESS == RegQueryValueEx(hKey, (LPCTSTR)achValue, NULL, &nValueType, strDSName, &nBuffLen)) {
int nIndex = -1;
while (++nIndex < 20) {
if (-1 == m_nComArray[nIndex]) {
m_nComArray[nIndex] = atoi((char*)(strDSName + 3));
break;
}
}
}
}
}
}
}
else {
AfxMessageBox(_T("本機沒有串口....."));
}
}

bool CCommox::ReceveData(void)
{
memset(lpInBuffer, 0, sizeof(lpInBuffer));
DWORD dwBytesRead = 1024;
COMSTAT ComStat;
DWORD dwErrorFlags;
DWORD dwEvtMask = 0;
WaitCommEvent(COMFile, &dwEvtMask, &osRead); //用來判斷串口通信事件是否已發生。COMFile:串口句柄  dwEvtMask:函式執行完后如果檢測到串口通信事件的話就將其寫入該引數中。
//osRead:接收事件資訊事件狀態
ClearCommError(COMFile, &dwErrorFlags, &ComStat);
dwBytesRead = min(dwBytesRead, (DWORD)ComStat.cbInQue);
if (!dwBytesRead)
return FALSE;
BOOL bReadStatus;
bReadStatus = ReadFile(COMFile, lpInBuffer,
dwBytesRead, &dwBytesRead, &osRead);
if (!bReadStatus) //如果ReadFile函式回傳FALSE
{
if (GetLastError() == ERROR_IO_PENDING)
//GetLastError()函式回傳ERROR_IO_PENDING,表明串口正在進行讀操作
{
WaitForSingleObject(osRead.hEvent, 2000);
//使用WaitForSingleObject函式等待,直到讀操作完成或延時已達到2秒鐘
//當串口讀操作進行完畢后,m_osRead的hEvent事件會變為有信號
PurgeComm(COMFile, PURGE_TXABORT |
PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
return dwBytesRead;
}
return 0;
}
PurgeComm(COMFile, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
memset(&osRead, 0, sizeof(OVERLAPPED));
return dwBytesRead;
}

uj5u.com熱心網友回復:

協議引數兩邊要完全一致
因為打開串口是用了OVERLAPED異步模式, 所以WaitCommEvent不會阻塞,沒有立即成功時應該判斷是否掛起, 然后用GetOverlappedResult 判斷結果
官方檔案 Serial Communications in Win32



uj5u.com熱心網友回復:

通常情況,直接用檔案讀寫加定時器或多執行緒就OK了

uj5u.com熱心網友回復:

參考
BOOL SetupConnection()
{
BOOL fRetVal;
DCB  dcb;
//
dcb.DCBlength=sizeof(DCB);
GetCommState(g_idComDev,&dcb);
dcb.BaudRate=g_iBaudrate;
dcb.ByteSize=8;          // databit;    
dcb.Parity=NOPARITY;     // parity
dcb.StopBits=0;          // 1 stopbit;
dcb.fInX=dcb.fOutX=FALSE;
dcb.fOutxDsrFlow=TRUE;// FALSE;
dcb.fOutxCtsFlow=FALSE;
dcb.fRtsControl=RTS_CONTROL_DISABLE;
dcb.fDtrControl=DTR_CONTROL_ENABLE;
dcb.fDtrControl=DTR_CONTROL_DISABLE;//DTR_CONTROL_HANDSHAKE;// 
// dcb.XonChar=0x11;
// dcb.XoffChar=0x13;
dcb.fBinary=TRUE;
dcb.fParity=FALSE;
fRetVal=SetCommState(g_idComDev,&dcb);
return fRetVal;// 1=OK
}

uj5u.com熱心網友回復:

用現成的吧,
https://download.csdn.net/download/tajon1226/11102637

轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/25271.html

標籤:硬件/系統

上一篇:共享MS Access資料庫,斷網重連后,client端不能更新

下一篇:我這個BIND函式為什么出錯啊

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • Git本地庫既關聯GitHub又關聯Gitee

    創建代碼倉庫 使用gitee舉例(github和gitee差不多) 1.在gitee右上角點擊+,選擇新建倉庫 ? 2.選擇填寫倉庫資訊,然后進行創建 ? 3.服務端已經準備好了,本地開始作準備 (1)Git 全域設定 git config --global user.name "成鈺" git c ......

    uj5u.com 2020-09-10 05:04:14 more
  • CODING DevOps 代碼質量實戰系列第二課,相約周三

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。**《DevOps 代碼質量實戰(PHP 版)》**為 CODING DevOps 代碼質量實戰系列的第二課,同時也是本系列的 PHP ......

    uj5u.com 2020-09-10 05:07:43 more
  • 推薦Scrum書籍

    推薦Scrum書籍 直接上干貨,推薦書籍清單如下(推薦有順序的哦) Scrum指南 Scrum精髓 Scrum敏捷軟體開發 Scrum捷徑 硝煙中的Scrum和XP : 我們如何實施Scrum 敏捷軟體開發:Scrum實戰指南 Scrum要素 大規模Scrum:大規模敏捷組織的設計 用戶故事地圖 用 ......

    uj5u.com 2020-09-10 05:07:45 more
  • CODING DevOps 代碼質量實戰系列最后一課,周四發車

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。 **《DevOps 代碼質量實戰(Java 版)》**為 CODING DevOps 代碼質量實戰系列的最后一課,同時也是本系列的 ......

    uj5u.com 2020-09-10 05:07:52 more
  • 敏捷軟體工程實踐書籍

    Scrum轉型想要做好,第一步先了解并真正落實Scrum,那么我推薦的Scrum書籍是要看懂并實踐的。第二步是團隊的工程實踐要做扎實。 下面推薦工程實踐書單: 重構:改善既有代碼的設計 決議極限編程 : 擁抱變化 代碼整潔代碼 程式員的職業素養 修改代碼的藝術 撰寫可讀代碼的藝術 測驗驅動開發 : ......

    uj5u.com 2020-09-10 05:07:55 more
  • Jenkins+svn+nginx實作windows環境自動部署vue前端專案

    前面文章介紹了Jenkins+svn+tomcat實作自動化部署,現在終于有空抽時間出來寫下Jenkins+svn+nginx實作自動部署vue前端專案。 jenkins的安裝和配置已經在前面文章進行介紹,下面介紹實作vue前端專案需要進行的哪些額外的步驟。 注意:在安裝jenkins和nginx的 ......

    uj5u.com 2020-09-10 05:08:49 more
  • CODING DevOps 微服務專案實戰系列第一課,明天等你

    CODING DevOps 微服務專案實戰系列第一課**《DevOps 微服務專案實戰:DevOps 初體驗》**將由 CODING DevOps 開發工程師 王寬老師 向大家介紹 DevOps 的基本理念,并探討為什么現代開發活動需要 DevOps,同時將以 eShopOnContainers 項 ......

    uj5u.com 2020-09-10 05:09:14 more
  • CODING DevOps 微服務專案實戰系列第二課來啦!

    近年來,工程專案的結構越來越復雜,需要接入合適的持續集成流水線形式,才能滿足更多變的需求,那么如何優雅地使用 CI 能力提升生產效率呢?CODING DevOps 微服務專案實戰系列第二課 《DevOps 微服務專案實戰:CI 進階用法》 將由 CODING DevOps 全堆疊工程師 何晨哲老師 向 ......

    uj5u.com 2020-09-10 05:09:33 more
  • CODING DevOps 微服務專案實戰系列最后一課,周四開講!

    隨著軟體工程越來越復雜化,如何在 Kubernetes 集群進行灰度發布成為了生產部署的”必修課“,而如何實作安全可控、自動化的灰度發布也成為了持續部署重點關注的問題。CODING DevOps 微服務專案實戰系列最后一課:**《DevOps 微服務專案實戰:基于 Nginx-ingress 的自動 ......

    uj5u.com 2020-09-10 05:10:00 more
  • CODING 儀表盤功能正式推出,實作作業資料可視化!

    CODING 儀表盤功能現已正式推出!該功能旨在用一張張統計卡片的形式,統計并展示使用 CODING 中所產生的資料。這意味著無需額外的設定,就可以收集歸納寶貴的作業資料并予之量化分析。這些海量的資料皆會以圖表或串列的方式躍然紙上,方便團隊成員隨時查看各專案的進度、狀態和指標,云端協作迎來真正意義上 ......

    uj5u.com 2020-09-10 05:11:01 more
最新发布
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:41:12 more
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:35:34 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:05:44 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:00:18 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:20:31 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:55 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:18:51 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:00 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:17:55 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:12:06 more