Windows 10 IoT ARM64平臺(tái)除了支持新的UWP框架,也兼容支持老框架MFC。使得用戶在Windows 10 IoT下可以對(duì)原MFC工程進(jìn)行功能升級(jí),不用在新框架下重寫(xiě)整個(gè)工程。熟悉MFC開(kāi)發(fā)的工程師也可以在Windows 10 IoT平臺(tái)下繼續(xù)使用MFC進(jìn)行開(kāi)發(fā)。
本文展示MFC串口程序開(kāi)發(fā),及需要注意的地方。
1. 打開(kāi)visual studio 2022,點(diǎn)擊“創(chuàng)建新項(xiàng)目”。
2. 選擇篩選條件,語(yǔ)言C++,平臺(tái)選擇Windows,應(yīng)用類型選擇桌面。
3. 選擇“MFC應(yīng)用”,點(diǎn)擊下一步。
4. 應(yīng)用程序類型選擇基于對(duì)話框,其它選項(xiàng)默認(rèn),創(chuàng)建好工程。
拖動(dòng)工具欄中控件到設(shè)計(jì)窗口中,設(shè)置好控件屬性,綁定好控件變量名及消息響應(yīng)函數(shù)。此處與傳統(tǒng)MFC程序開(kāi)發(fā)一樣。
可以參考文章《UWP串口程序開(kāi)發(fā)》,使用新Devices庫(kù)查詢串口,打開(kāi)串口,讀寫(xiě)串口。本文依舊采用傳統(tǒng)的接口Createfile,WriteFile,ReadFile操作串口。
3.1 查詢串口
已知串口名,可以直接通過(guò)CreateFile打開(kāi)串口?;蛘咄ㄟ^(guò)API接口進(jìn)行查詢。
#include <cfgmgr32.h> #include <propkey.h> #include <initguid.h> #include <devpkey.h> std::wstring devicePath; devicePath = GetFirstDevice(); Handle serialHandle= CreateFileW(devicePath.c_str(),GENERIC_READ | GENERIC_WRITE,0,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,NULL)); //Handle serialHandle= CreateFileW(L” \\\\?\\ACPI#NXP0113#2#{86e0d1e0-8089-11d0-9ce4-08003e301f73}\\SERCX”,GENERIC_READ | GENERIC_WRITE,0,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,NULL)); std::wstring GetFirstDevice () { ULONG length; CONFIGRET cr = CM_Get_Device_Interface_List_SizeW( &length, const_cast<GUID*>(&GUID_DEVINTERFACE_COMPORT), nullptr, // pDeviceID CM_GET_DEVICE_INTERFACE_LIST_PRESENT); if (cr != CR_SUCCESS) { throw wexception( L"Failed to get size of device interface list. (cr = 0x%x)", cr); } std::vector<WCHAR> buf(length); cr = CM_Get_Device_Interface_ListW( const_cast<GUID*>(&GUID_DEVINTERFACE_COMPORT), nullptr, // pDeviceID buf.data(), static_cast<ULONG>(buf.capacity()), CM_GET_DEVICE_INTERFACE_LIST_PRESENT); if (cr != CR_SUCCESS) { throw wexception( L"Failed to get device interface list. (cr = 0x%x)", cr); } return std::wstring(buf.data()); }
3.2 打開(kāi)串口
與WINCE不同,Windows 10 IoT需要用FILE_FLAG_OVERLAPPED異步操作模式打開(kāi)和讀寫(xiě)串口,如果使用同步操作模式打開(kāi)串口進(jìn)行讀寫(xiě),讀寫(xiě)效率會(huì)有影響。
HANDLE m_hComm = CreateFile(Port, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0);
設(shè)置串口參數(shù)
GetCommState(m_hComm, &dcb); /* 讀取串口的DCB */ dcb.BaudRate = 115200; dcb.ByteSize = 8; dcb.Parity = 0; dcb.StopBits = 0; dcb.fBinary = TRUE; dcb.fRtsControl = RTS_CONTROL_DISABLE; SetCommState(m_hComm, &dcb); /* 設(shè)置串口的DCB */
3.3 讀串口
異步操作模式需要設(shè)置OVERLAPPED
#include <wrl.h> using namespace Microsoft::WRL::Wrappers; auto overlapped = OVERLAPPED(); overlapped.hEvent = overlappedEvent.Get(); DWORD bytesRead = 0; if (!ReadFile( pDlg->m_hComm, reinterpret_cast<BYTE*>(recvBuf), 1024, &bytesRead, &overlapped) && (GetLastError() != ERROR_IO_PENDING)) { DWORD error = GetLastError(); } if (!GetOverlappedResult( pDlg->m_hComm, &overlapped, &bytesRead, TRUE)) { DWORD error = GetLastError(); } if (bytesRead != 0) { OnCommRecv(pDlg, recvBuf, bytesRead); /* 接收成功調(diào)用回調(diào)函數(shù) */ }
3.4 寫(xiě)串口
用異步模式寫(xiě)串口
auto overlapped = OVERLAPPED(); overlapped.hEvent = overlappedEvent.Get(); if (!WriteFile( m_hComm, psendbuf, len, &dwactlen, &overlapped) && (GetLastError() != ERROR_IO_PENDING)) { DWORD error = GetLastError(); } if (!GetOverlappedResult( m_hComm, &overlapped, &dwactlen, TRUE)) { DWORD error = GetLastError(); }
3.5 串口關(guān)閉
CloseHandle(m_hComm);
3.6 創(chuàng)建timer自動(dòng)發(fā)送
添加對(duì)話框的timer消息響應(yīng)函數(shù)OnTimer
1. 啟動(dòng)timer
SetTimer(1, m_period, NULL);
2. 退出時(shí)關(guān)閉timer
KillTimer(1);
打開(kāi)Win10 IoT板子上的調(diào)試助手。
選擇工程平臺(tái)為ARM64,編譯運(yùn)行,示例如下。
需要程序源碼可以聯(lián)系英創(chuàng)工程師獲得。
成都英創(chuàng)信息技術(shù)有限公司 028-8618 0660