1.建立項目??
2.在項目中插入MSComm控件?
3.利用ClassWizard定義CMSComm類控制變量
4.在對話框中添加控件??
5.添加串口事件消息處理函數(shù)OnComm()
6.打開和設置串口參數(shù)
7.發(fā)送數(shù)據(jù)
11.什么是VARIANT數(shù)據(jù)類型?如何使用VARIANT數(shù)據(jù)類型?
?
??? 這是串口調(diào)試助手源程序及編程詳細過程(一)的續(xù)篇,首先謝謝朋友們的支持與鼓勵。
??
??? 在主對話框中加入一個復選接鈕,ID為IDC_CHECK_HEXSEND Caption: 十六進制發(fā)送,再利用ClassWizard為其添加控制變量:m_ctrlHexSend;
??? 在ClassView中為SCommTestDlg類添加以下兩個PUBLIC成員函數(shù),并輸入相應代碼;
//由于這個轉(zhuǎn)換函數(shù)的格式限制,在發(fā)送框中的十六制字符應該每兩個字符之間插入一個空隔
//如:A1 23 45 0B 00 29
//CByteArray是一個動態(tài)字節(jié)數(shù)組,可參看MSDN幫助
int CSCommTestDlg::String2Hex(CString str, CByteArray &senddata)
{
int hexdata,lowhexdata;
int hexdatalen=0;
int len=str.GetLength();
senddata.SetSize(len/2);
for(int i=0;i{
char lstr,hstr=str[i];
if(hstr==' ')
{
i++;
continue;
}
i++;
if(i>=len)
break;
lstr=str[i];
hexdata=ConvertHexChar(hstr);
lowhexdata=ConvertHexChar(lstr);
if((hexdata==16)||(lowhexdata==16))
break;
else?
hexdata=hexdata*16+lowhexdata;
i++;
senddata[hexdatalen]=(char)hexdata;
hexdatalen++;
}
senddata.SetSize(hexdatalen);
return hexdatalen;
}
//這是一個將字符轉(zhuǎn)換為相應的十六進制值的函數(shù)
//好多C語言書上都可以找到
//功能:若是在0-F之間的字符,則轉(zhuǎn)換為相應的十六進制字符,否則返回-1
char CSCommTestDlg::ConvertHexChar(char ch)?
{
if((ch>='0')&&(ch<='9'))
return ch-0x30;
else if((ch>='A')&&(ch<='F'))
return ch-'A'+10;
else if((ch>='a')&&(ch<='f'))
return ch-'a'+10;
else return (-1);
}
? 再將CSCommTestDlg::OnButtonManualsend()修改成以下形式:
void CSCommTestDlg::OnButtonManualsend()?
{
// TOD Add your control notification handler code here
UpdateData(TRUE); //讀取編輯框內(nèi)容
if(m_ctrlHexSend.GetCheck())
{
CByteArray hexdata;
int len=String2Hex(m_strTXData,hexdata); //此處返回的len可以用于計算發(fā)送了多少個十六進制數(shù)
m_ctrlComm.SetOutput(COleVariant(hexdata)); //發(fā)送十六進制數(shù)據(jù)
}
else?
m_ctrlComm.SetOutput(COleVariant(m_strTXData));//發(fā)送ASCII字符數(shù)據(jù)
}
現(xiàn)在,你先將串口線接好并打開串口調(diào)試助手V2.1,選上以十六制顯示,設置好相應串口,然后運行我們這個程序,在發(fā)送框中輸入00 01 02 03 A1 CC等十六進制字符,并選上以十六進制發(fā)送,單擊手動發(fā)送,在串口調(diào)試助手的接收框中應該可以看到00 01 02 03 A1 CC了。
??? 這就容易多了:??在主對話框中加入一個復選接鈕,IDC_CHECK_HEXDISPLAY Caption: 十六進制顯示,再利用ClassWizard為其添加控制變量:m_ctrlHexDiaplay。 然后修改CSCommTestDlg::OnComm()函數(shù):
void CSCommTestDlg::OnComm()?
{
// TOD Add your control notification handler code here
VARIANT variant_inp;
COleSafeArray safearray_inp;
LONG len,k;
BYTE rxdata[2048]; //設置BYTE數(shù)組 An 8-bit integerthat is not signed.
CString strtemp;
if(m_ctrlComm.GetCommEvent()==2) //事件值為2表示接收緩沖區(qū)內(nèi)有字符
{
variant_inp=m_ctrlComm.GetInput(); //讀緩沖區(qū)
safearray_inp=variant_inp; //VARIANT型變量轉(zhuǎn)換為ColeSafeArray型變量
len=safearray_inp.GetOneDimSize(); //得到有效數(shù)據(jù)長度
for(k=0;ksafearray_inp.GetElement(&k,rxdata+k);//轉(zhuǎn)換為BYTE型數(shù)組 if(m_ctrlHexDisplay.GetCheck())
for(k=0;k{
BYTE bt=*(char*)(rxdata+k); //字符型
strtemp.Format("%02X ",bt); //將字符以十六進制方式送入臨時變量strtemp存放,注意這里加入一個空隔
else?
strtemp.Format("%c",bt); //將字符送入臨時變量strtemp存放
m_strRXData+=strtemp; //加入接收編輯框?qū)址?
}
}
UpdateData(FALSE); //更新編輯框內(nèi)容
}
測試:在串口調(diào)試助手發(fā)送框中輸入00 01 02 03 A1 CC等十六進制字符,并選上以十六進制發(fā)送,單擊手動發(fā)送,在本程序運行后選上以十六進制顯示,在串口調(diào)試助手中單擊手動發(fā)送或自動發(fā)送,則在本程序的接收框中應該可以看到00 01 02 03 A1 CC了。
???? 最簡單的設定自動發(fā)送周期是用SetTimer()函數(shù),這在數(shù)據(jù)采集中很有用,在控制中指令的傳送也可能用到定時發(fā)送。
??? 方法是:在ClassWizard中選上MessageMap卡,然后在Objects IDs選中CSCommTestDlg類,再在Messages框中選上WM_TIMER消息,單擊ADD_FUNCTION加入void CSCommTestDlg::OnTimer(UINT nIDEvent) 函數(shù),這個函數(shù)是放入“時間到”后要處理的代碼:
void CSCommTestDlg::OnTimer(UINT nIDEvent)?
{
// TOD Add your message handler code here and/or call default
OnButtonManualsend();
CDialog::OnTimer(nIDEvent);
}
再在在主對話框中加入一個復選接鈕,ID為IDC_CHECK_AUTOSEND Caption: 自動發(fā)送(周期1秒),再利用ClassWizard為其添加BN_CLICK消息處理函數(shù)void CSCommTestDlg::OnCheckAutosend():
void CSCommTestDlg::OnCheckAutosend()?
{
// TOD Add your control notification handler code here
m_bAutoSend=!m_bAutoSend;
if(m_bAutoSend)
{
SetTimer(1,1000,NULL);//時間為1000毫秒
}
else
{
KillTimer(1);? //取消定時
}
}
其中:m_bAutoSend為BOOL型變量,在CLASSVIEW中為CSCommTestDlg類加入,并在構(gòu)造函數(shù)中初始化:
????? m_bAutoSen=FALSE;
現(xiàn)在可以運行程序測試了。
11.什么是VARIANT數(shù)據(jù)類型?如何使用VARIANT數(shù)據(jù)類型?
???? 不知如何使用VARIANT數(shù)據(jù)類型, 有不少朋友對VARIANT這個新的數(shù)據(jù)類型大感頭疼。SetOutput()函數(shù)中 需要的VARIANT參數(shù)還可以使用COleVariant類的構(gòu)造函數(shù)簡單生成,現(xiàn)在GetInput()函數(shù)的返回值也成了VARIANT類型,那么如何從返回的值中提取有用的內(nèi)容。 VARIANT及由之而派生出的COleVariant類主要用于在OLE自動化中傳遞數(shù)據(jù)。實際上VARIANT也只不過是一個新定義的結(jié)構(gòu)罷了,它的主要成員包括一個聯(lián)合體及一個變量。該聯(lián)合體由各種類型的數(shù)據(jù)成員構(gòu)成, 而該變量則用來指明聯(lián)合體中目前起作用的數(shù)據(jù)類型。我們所關(guān)心的接收到的數(shù)據(jù)就存儲在該聯(lián)合體的某個數(shù)據(jù)成員中。 該聯(lián)合體中包含的數(shù)據(jù)類型很多,從一些簡單的變量到非常復雜的數(shù)組和指針。由于通過串口接收到的內(nèi)容常常是一個字節(jié)串,我們將使用其中的某個數(shù)組或指針來訪問接收到的數(shù)據(jù)。這里推薦給大家的是指向一個SAFEARRAY(COleSafeArray)類型變量。新的數(shù)據(jù)類型SAFEARRAY正如其名字一樣,是一個“安全數(shù)組”,它能根據(jù)系統(tǒng)環(huán)境自動調(diào)整其16位或32 位的定義,并且不會被OLE改變(某些類型如BSTR在16位或32位應用程序間傳遞時會被OLE翻譯從而破壞其中的二進制數(shù)據(jù))。大家無須了解SAFEARRAY的具體定義,只要知道它是另外一個結(jié)構(gòu),其中包含一個 (void *)類型的指針pvData,其指向的內(nèi)存就是存放有用數(shù)據(jù)的地方。 簡而言之,從GetInput()函數(shù)返回的VARIANT類型變量中,找出parray 指針,再從該指針指向的SAFEARRAY變量中找出pvData指針,就可以向訪問數(shù)組一樣取得所接收到的數(shù)據(jù)了。具體應用請參見void CSCommTestDlg::OnComm()函數(shù)。
??? 大概我現(xiàn)在也說不清這個問題,我自己從第一次接觸這個東西,到現(xiàn)在還是給別人講不清。
另:二進制收發(fā)設置請參考MSComm控件說明。
評論
查看更多