我自己用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函式為什么出錯啊
