用VC實(shí)現(xiàn)PC機(jī)與單片機(jī)的通信
掃描二維碼
隨時(shí)隨地手機(jī)看文章
在工業(yè)檢測(cè)及自動(dòng)控制系統(tǒng)中,微機(jī)與微機(jī)、微機(jī)與單片機(jī)之間經(jīng)常需要進(jìn)行數(shù)據(jù)交換,串行通信是主要的通信手段,它高效、方便,并遵循統(tǒng)一的國(guó)家標(biāo)準(zhǔn)。 Visual C++ 6.0作為一種強(qiáng)大的開發(fā)工具幾乎在Windows軟件開發(fā)的任何領(lǐng)域都得到廣泛的應(yīng)用。一般用Visual C++ 6.0開發(fā)串行通信程序有二種方法:一是利用Windows的通信 API函數(shù);另一種是采用Visual C++ 6.0標(biāo)準(zhǔn)控件MSComm來實(shí)現(xiàn)。第一種方法需要聲明及調(diào)用許多API函數(shù),十分煩瑣。第二種方法實(shí)現(xiàn)簡(jiǎn)便,且可滿足一般情況下通信要求。本文利用Visual C++ 6.0提供的MSComm通信控件編寫較簡(jiǎn)單的VC程序, 完成了微機(jī)與單片機(jī)之間的 RS-232串行口通信。
1、硬件結(jié)構(gòu)
PC微機(jī)的COM口接口電平為RS-232標(biāo)準(zhǔn),若兩臺(tái)微機(jī)間通信,只需簡(jiǎn)單地直接連接(TXD RXD)及地(GND)三根線。若微機(jī)與單片機(jī)通信,由于單片機(jī)UART為TTL電平,故需將RS-232電平與TTL電平轉(zhuǎn)換,可直接使用 MAX232,MC1489等實(shí)現(xiàn)電平轉(zhuǎn)換功能。
2、串行通信控件MSComm
在VC環(huán)境下單擊Project菜單,從中選擇Add to Project,在彈出的對(duì)話框中單擊Components and Controls選項(xiàng),然后在彈出的對(duì)話框中再單擊Registered ActiveX Controls選項(xiàng)。在列表中選擇Microsoft Communications Control (version6.0),形狀為帶有紅色底座的黃色電話機(jī)。單擊Insert按鈕,確認(rèn)后,會(huì)出現(xiàn)一個(gè)Confirm Classes對(duì)話框,其中列出了該控件的類名(CMSComm)、頭文件名(MSComm.h)、執(zhí)行文件名(MSComm.cpp)。關(guān)閉此對(duì)話框,在程序主界面的控件列表中,可以看到該通信控件已被加入,拖動(dòng)該控件就可以將其放入程序中。
MSComm控件提供了功能完善的串口數(shù)據(jù)的發(fā)送和接收功能, MSComm控件具有兩種處理方式: 1、事件驅(qū)動(dòng)方式:由MSComm控件的OnComm事件捕獲并處理通信錯(cuò)誤及事件;2、查詢方式:通過檢查CommEvent屬性的值來判斷事件和錯(cuò)誤。
MSComm控件的通信功能實(shí)現(xiàn),實(shí)際上是調(diào)用了API函數(shù),而API函數(shù)是由Comm.drv解釋并傳給設(shè)備驅(qū)動(dòng)程序執(zhí)行的,對(duì)于VC程序開發(fā)者只需知道MSComm控件的屬性和事件的用法即可以實(shí)現(xiàn)串口的操作。
以下是MSComm控件的主要屬性和方法:
1) CommPort:設(shè)置或返回串行端口號(hào),其取值范圍為1~99,缺省為1。
2) Setting:設(shè)置或返回串行端口的波特率、奇偶校驗(yàn)位、數(shù)據(jù)位數(shù)、停止位。如:M scomm.Setting="9600,N,8,1"。
3) PortOpen:打開或關(guān)閉串行端口,格式為:MSComm.PortOpen={T RUE|FALSE}。
4) InBufferSize:設(shè)置或返回接收緩沖區(qū)的大小,缺省為1024字節(jié)。
5) InBufferCount:返回接收緩沖區(qū)內(nèi)的等待讀取的字節(jié)個(gè)數(shù),可通過設(shè)置該屬性為0來清除接收緩沖區(qū)。
6) Rthreshold:該屬性為一閥值,它確定當(dāng)接收緩沖區(qū)內(nèi)字節(jié)個(gè)數(shù)達(dá)到或超過該值后就產(chǎn)生代碼為MSCOMM_EV_RECEIVE的OnComm事件 。
7) InputLen::設(shè)置或返回接收緩沖區(qū)內(nèi)用Input讀入的個(gè)數(shù)。若取0,則INPUT讀取整個(gè)緩沖區(qū)的內(nèi)容。
8) Input: 該屬性表示從接收緩沖區(qū)移走一串字符。 類型:VARIANT。
9) OutBufferSize:設(shè)置或返回發(fā)送緩沖區(qū),缺省為512字節(jié)。
10) OutBufferCount:返回發(fā)送緩沖區(qū)內(nèi)等待發(fā)送的字符數(shù),可用來清空緩沖區(qū)。
11) Output:向發(fā)送緩沖區(qū)傳送一字符串。類型:VARIANT。
如果在通信過程中發(fā)生錯(cuò)誤或事件,就會(huì)引發(fā)OnComm事件并且改 變屬性值,由CommEvent屬性代碼反映錯(cuò)誤類型,在通信程序的設(shè)計(jì)中 可根據(jù)該屬性值來執(zhí)行不同的操作,以下是部分屬性常數(shù)值及其含義:
1) ComEvSend: 其值為1,發(fā)送緩沖區(qū)的內(nèi)容少于SThreshold指定 的值。
2) ComEvReceive: 其值為2,接收緩沖區(qū)內(nèi)字符數(shù)達(dá)到 RThreshold 值,該事件在緩沖區(qū)中數(shù)據(jù)被移走前將持續(xù)產(chǎn)生。
3) ComEventFrame: 其值為1004,硬件檢測(cè)到幀錯(cuò)誤。
4) ComEventRxOver:其值為1008,接收緩沖區(qū)溢出。
5) ComEventTxFull: 其值為1010,發(fā)送緩沖區(qū)溢出。
6) ComEventRxParity:其值為1009,奇偶校驗(yàn)。
7) ComEvEOF: 其值為7,接收數(shù)據(jù)中出現(xiàn)文件結(jié)束(ASCII 碼為 2 6)字符。
3、串口通信微機(jī)程序設(shè)計(jì)
下面程序可實(shí)現(xiàn)簡(jiǎn)單通信,程序主要有兩個(gè)編輯框,一為發(fā)送,用戶在此編輯框內(nèi)鍵入字符將通過串口發(fā)送出去;另一為接收,顯示串口接收到字符。如在兩臺(tái)微機(jī)相連,分別運(yùn)行此程序,即可實(shí)現(xiàn)兩機(jī)之間通信。具體實(shí)現(xiàn)步驟如下:
1)啟動(dòng)Visual C++ 6.0,創(chuàng)建一名為Chat應(yīng)用程序項(xiàng)目,程序類型為Dialog based。
2)如2所述在應(yīng)用程序中插入通信控件。
3)MFC的ClassWizard 對(duì)話框的Member Variables選項(xiàng)卡如下所示
控件ID 類型 數(shù)據(jù)成員
IDC_EDIT1_SEND Cstring m_send
IDC_EDIT2_RECV Cstring m_recv
IDC_MSCOMM1 CMSComm m_comm
IDCANCEL
4)部分源程序代碼如下:
BOOL CChatDlg::OnInitDialog( )
{
CDialog::OnInitDialog( );
// TODO: Add extra initialization here
m_comm.SetCommPort(1); //選擇串口1
if(!m_comm.GetPortOpen( ))
m_comm.SetPortOpen(TRUE); //打開串口1
m_comm.SetSettings("9600,n,8,1"); //串口參數(shù)設(shè)置
m_comm.SetRThreshold(1); //當(dāng)串口接收緩沖區(qū)內(nèi)接收字符多于或等于1將觸發(fā)一關(guān)于comEvReceive的OnComm事件。
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CChatDlg::OnChangeEdit1Send( )
{ // TODO: Add your control notification handler code here
int count;
CString temp;
UpdateData(TRUE); //獲取用戶輸入數(shù)據(jù)
count=m_send.GetLength( ); //獲取編輯框內(nèi)字符數(shù)
temp=m_send.GetAt(count-1); //取最新輸入字符
if(!m_comm.GetPortOpen( ))
m_comm.SetPortOpen(TRUE);
m_comm.SetOutput(COleVariant(temp)); //發(fā)送數(shù)據(jù)
if(count= =40) //如輸入字符超過40,清空發(fā)送編輯框
{ m_send.Empty( );
UpdateData(FALSE); //更新編輯框
}
}
void CChatDlg::OnOnCommMscomm 1( )
{
// TODO: Add your control notification handler code here
VARIANT temp;
int count;
if(m_comm.GetCommEvent( )= =2) //串行口數(shù)據(jù)接收處理;
{ count=m_comm.GetInBufferCount( );
m_comm.SetInputLen(count); //利用Input接收字符數(shù)為count
temp=m_comm.GetInput( ); //接收字符
m_recv+=temp.bstrVal; //將接收字符添加到接收框變量中
if(m_recv.GetLength( )= =40) //如輸入字符超過40,清空發(fā)送編輯框
m_recv.Empty( );
UpdateData(FALSE); //更新編輯框
}
}
4、串行通信單片機(jī)程序設(shè)計(jì)
在此作為演示,此單片機(jī)程序功能只是簡(jiǎn)單將所收字符再發(fā)送出去,類似可實(shí)現(xiàn)各種復(fù)雜通信協(xié)議。將微機(jī)與單片機(jī)相連后,微機(jī)運(yùn)行chat.exe,單片機(jī)運(yùn)行此程序即可實(shí)現(xiàn)兩機(jī)通信。
下面是MC68HC908GP32為例的程序清單。
*==========Registers===========
SCCR1 equ $0013
b_ENSCI equ 6
SCCR2 equ $0014
b_TE equ 3
b_RE equ 2
BAUD equ $0019
SCS1 equ $0016
SCS2 equ $0017
SCDR equ $0018
CONFIG2 equ $001e
CONFIG1 equ $001f
PCTL equ $0036
b_PLLON equ 5
b_BCS equ 4
PBWC equ $0037
b_AUTO equ 7
PMSH equ $0038
PMSL equ $0039
PMRS equ $003a
*==========Initial Codes========
ORG $8000
RESET_INIT:
SEI
LDHX #$023F
TXS
LDA #$01
STA CONFIG2
LDA #$3D
STA CONFIG1
*========== Initial CGMC=========
CLR PCTL
MOV #$01,PCTL
MOV #$01,PMSH
MOV #$2C,PMSL
MOV #$80,PMRS
BSET b_PLLON,PCTL ;32.768khz --2.4576Mhz
BSET b_AUTO,PBWC
BSET b_BCS,PCTL
*========= Initial SCI==========*
LDA #$02
STA BAUD ;9600baud
BSET b_ENSCI,SCCR1 ;ENABLE SCI
MOV #$0C,SCCR2 ;ENABLE TRANSMITTER AND RECEIVER
*==========Main program========*
START:CLI
JSR GETDATA
JSR SENDATA
JMP START
GETDATA:BRCLR 5,SCS1,GETDATA
LDA SCDR
RTS
SENDATA:BRCLR 7,SCS1,SENDATA
STA SCDR
RTS
*===========Vector=============*
ORG $FFFE
DW RESET_INIT
若要實(shí)現(xiàn)一臺(tái)微機(jī)(主機(jī))與多臺(tái)GP32通信,可用SCI接收器喚醒功能(空閑線或地址位)。主機(jī)與從機(jī)通信時(shí),發(fā)送信息的開頭一般為從機(jī)地址,各從機(jī)接收信息開頭的地址,如發(fā)現(xiàn)地址與自己的地址相同,則準(zhǔn)備接收后面的數(shù)據(jù),負(fù)責(zé)不予理睬。至此我們用Visual C++ 6.0實(shí)現(xiàn)了微機(jī)與微機(jī)以及微機(jī)與單片機(jī)之間的串行通信,通過更復(fù)雜的通信協(xié)議,完全可滿足工業(yè)測(cè)控系統(tǒng)中的一般數(shù)據(jù)通信要求。
參考文獻(xiàn):
[1]劉慧根等. MC68HC08原理及其嵌入是應(yīng)用. 清華大學(xué)出版社,2001.
[2]劉瑜. Windows環(huán)境下串行通信程序設(shè)計(jì). 計(jì)算機(jī)應(yīng)用與研究,1999.