久久久91-久久久91精品国产一区二区-久久久91精品国产一区二区三区-久久久999国产精品-久久久999久久久精品

ABB
關(guān)注中國自動化產(chǎn)業(yè)發(fā)展的先行者!
CAIAC 2025
2025工業(yè)安全大會
OICT公益講堂
當(dāng)前位置:首頁 >> 案例 >> 案例首頁

案例頻道

Windows CE環(huán)境下與單片機串行通信的實現(xiàn)
  • 企業(yè):     領(lǐng)域:電源    
  • 點擊數(shù):2173     發(fā)布時間:2005-08-23 11:42:01
  • 分享到:
本文介紹了在Windows CE環(huán)境下與單片機基于多線程的串行通信的實現(xiàn)問題。深入研究了Windows CE中對基于多線程的串口通信的各項設(shè)置和數(shù)據(jù)接收中一些關(guān)鍵問題,并提出了AT89C52單片機的串口通信中波特率正確設(shè)定的方法,特別適用于傳輸?shù)臄?shù)據(jù)量較大且傳輸速度較高的情況。



1. 引言

    隨著科技的發(fā)展,軟硬件資源的成熟和完善,嵌入式系統(tǒng)在現(xiàn)代工業(yè)控制領(lǐng)域中得到了越來越廣泛的應(yīng)用,其應(yīng)用領(lǐng)域涉及通信、自動化、信息家電、軍事等各個方面。而嵌入式操作系統(tǒng)的引入大大提高了嵌入式系統(tǒng)的功能,方便了嵌入式應(yīng)用軟件的設(shè)計。
    Windows CE是微軟公司開發(fā)的一種嵌入式實時操作系統(tǒng),它是一種模塊化的、實時的、有強大的通信功能的、搶先式、多任務(wù)具有強大通信功能的32位嵌入式操作系統(tǒng)。
    在嵌入式系統(tǒng)的實現(xiàn)中一般都會涉及數(shù)據(jù)的采集和處理,因此數(shù)據(jù)的通信成了系統(tǒng)穩(wěn)定可靠運行的關(guān)鍵。串行通信是計算機與外部設(shè)備交換信息的重要途徑,由于其實現(xiàn)簡單,節(jié)省I/O口和線路,傳輸時序明晰等特點,應(yīng)用的非常普遍,同樣在嵌入式系統(tǒng)中它也是一種主要的通信方式。在本文中研究的是基于Windows CE操作系統(tǒng)的掌上電腦和單片機之間的串行通信問題。

2. 系統(tǒng)結(jié)構(gòu)和Windows CE簡介

    本文介紹的是一種基于掌上電腦的便攜式動態(tài)心電信號采集及處理系統(tǒng),主要討論系統(tǒng)串行通信的設(shè)計和實現(xiàn)。整個系統(tǒng)由檢測模塊和掌上電腦兩部分組成。其中,檢測模塊是由AT89C52單片機控制的智能模塊,負(fù)責(zé)心電信號的檢測、放大、濾波與采集;掌上電腦負(fù)責(zé)參數(shù)的設(shè)置,心電波形數(shù)據(jù)存儲、處理、分析以及波形顯示等;掌上電腦基于Windows CE操作系統(tǒng)。圖1為整個系統(tǒng)的功能框圖,檢測模塊與掌上電腦之間通過RS232接口實現(xiàn)通信,而掌上電腦通過RS232或USB接口和PC機進(jìn)行數(shù)據(jù)通信,由PC機對數(shù)據(jù)進(jìn)行深入的分析和處理。整個系統(tǒng)的實現(xiàn)中,數(shù)據(jù)的串行通信是最基本也是最重要的部分。由于掌上電腦和PC機之間的通信由商家提供專門的接口線以及驅(qū)程,因此我們在這不作具體的研究。
    Windows CE作為一種嵌入式操作系統(tǒng),它的很多特性都是為了適應(yīng)嵌入式系統(tǒng)的特殊要求,它與一般的Windows程序有很多區(qū)別,如API函數(shù),存儲器的限制,電源管理方式,硬件特性等等。但是在通信方面Windows CE基本擁有和Windows同樣的Win32 API,因為運行Windows CE的系統(tǒng)或者是移動的,或者需要與遠(yuǎn)程服務(wù)器進(jìn)行連接,因此必須具有強大的通信功能。Windows CE下的應(yīng)用程序是通過文件I/O函數(shù)CreateFile,ReadFile,WriteFile,CloseHandle訪問設(shè)備驅(qū)動程序的,對文件進(jìn)行操作時,在Windows CE下的設(shè)備不支持重疊I/O。



圖1  系統(tǒng)整體結(jié)構(gòu)概略圖



3. Windows CE下基于多線程的串行通信實現(xiàn)

    什么是使用多線程的好時機呢?如果你的程序有許多事要忙,但是你還要隨時保持注意某些外部事件(可能來自硬件或來自使用者),這時就適合使用多線程來幫忙。以通信程序為例,你可以讓主線程負(fù)責(zé)使用者界面,并保持中樞的地位,而以―個分離的線程處理通信端口,這樣就可以在串口讀寫數(shù)據(jù)的同時保持使用者界面依然靈活,不受影響。本文就是采用這種多線程的方法來實現(xiàn)串行通信的,創(chuàng)建了單獨的讀和寫線程來處理串口讀寫數(shù)據(jù)。
    Windows CE下的串行設(shè)備被視為用于打開、關(guān)閉、讀和寫串行端口的常規(guī)、可安裝的流設(shè)備。這里我們構(gòu)造一個串口類CSerial來對Win32 API串口操作函數(shù)CreateFile,ReadFile,WriteFile,CloseHandle等進(jìn)行封裝,并在其中完成對串口的各項設(shè)置。在本系統(tǒng)中主要時在Windows CE環(huán)境中接收單片機上傳的大量數(shù)據(jù),因此我們將對數(shù)據(jù)的接收作比較詳細(xì)的分析。

1) 串口的打開和配置
    在類CSerial中用BOOL Open( int nPort, int nBaud)來完成串口的打開和初始化工作。先調(diào)用CreateFile打開指定的串口,然后通過GetCommState和SetCommState函數(shù)來配置串口,最后設(shè)置串口讀寫數(shù)據(jù)的超時值。
    配置串口時一般先調(diào)用GetCommState得到默認(rèn)的DCB結(jié)構(gòu),然后根據(jù)自己的需要來對它作必要的修改,再用SetCommState來重新配置串口。DCB結(jié)構(gòu)包括波特率、流控制、傳輸模式、起始位、停止位、校驗等設(shè)置。需要注意的是Win32操作系統(tǒng)一般只支持二進(jìn)制的傳輸模式,因此fBinary字段應(yīng)設(shè)為TRUE,另外接收緩沖器應(yīng)該盡量設(shè)的大一些。
    下面具體研究一下讀寫數(shù)據(jù)的超時值,通過GetCommTimeouts和SetCommTimeouts對COMMTIMEOUTS結(jié)構(gòu)的5個字段進(jìn)行設(shè)置。通常在實現(xiàn)串口通信時往往不重視甚至忽略對讀寫數(shù)據(jù)超時值的設(shè)置,這樣可能就會造成串口數(shù)據(jù)讀寫的不可靠性,特別是在接收大量數(shù)據(jù)時,如果超時值的設(shè)置不合適將會使數(shù)據(jù)不能完全接收過來而導(dǎo)致通信出錯。在本系統(tǒng)中如下設(shè)置串口超時值。
    COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout =10; 
    CommTimeOuts.ReadTotalTimeoutMultiplier =10; 
    CommTimeOuts.ReadTotalTimeoutConstant = 10;   
    CommTimeOuts.WriteTotalTimeoutMultiplier = 5; 
    CommTimeOuts.WriteTotalTimeoutConstant = 5; 
    其中ReadIntervalTimeout設(shè)置串口相鄰字節(jié)接收間隔時間的最大值,單位為毫秒。如果前后兩個字節(jié)之間的間隔時間超過該設(shè)定值,ReadFile就返回,終止接收。ReadTotalTimeoutMultiplier用來計算 ReadFile函數(shù)的總超時,單位為毫秒。每次讀取串口操作,將其與要接收字節(jié)數(shù)相乘再與ReadTotalTimeoutConstant相加來計算 ReadFile函數(shù)的總超時時間。寫操作兩個字段的設(shè)置與讀操作類似。
    當(dāng)波特率較高時,ReadIntervalTimeout不能設(shè)的太大,否則兩次接收將會當(dāng)作一次處理,通信將出現(xiàn)錯誤。而對于后兩者,由于 ReadFile當(dāng)總超時時間到時要立刻返回,因此要綜合考慮波特率、應(yīng)接收字節(jié)數(shù)等因素,以期串口的正確運行。很多人在實現(xiàn)串行通信時簡單的將ReadIntervalTimeout設(shè)置為MAXDWORD, ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant設(shè)為0,這種做法在進(jìn)行大量數(shù)據(jù)傳輸中并不適用,可能會導(dǎo)致數(shù)據(jù)的丟失。也不能在設(shè)置了適當(dāng)?shù)淖止?jié)間超時后就簡單的把總超時設(shè)為0以期待直到所有數(shù)據(jù)讀完后ReadFile才返回,這樣可能會使ReadFile一直處于等待狀態(tài),不能正常返回。

2) 數(shù)據(jù)的接收

數(shù)據(jù)的接收我們用DWORD ReadData(char *data,CString FileName)函數(shù)來完成,如下所示。
DWORD CSerial::ReadData( char *data,CString FileName)
{
 char Byte[1000];
    DWORD dwComStatus,dwBytesTransferred;
    DWORD len=0;
    CFile ECGFile;
 ECGFile.Open(FileName,CFile::modeCreate|CFile::modeWrite);
 SetCommMask (m_hComID, EV_RXCHAR | EV_CTS | EV_DSR);
 if (m_hComID!= INVALID_HANDLE_VALUE)
 {
  WaitCommEvent (m_hComID, &dwComStatus, 0);
     if (dwComStatus & EV_RXCHAR)
  {
   do
   {
    ReadFile (m_hComID,
     &Byte,
       1000,
     &dwBytesTransferred,
     0
     );
    if (dwBytesTransferred)
    {
//     strncat(data,Byte,dwBytesTransferred); //接收數(shù)據(jù)較少時
strncpy(data,Byte,dwBytesTransferred); //接收數(shù)據(jù)較多時
     len+=dwBytesTransferred;
     g_nCount=len;
  ECGFile.Write(Byte,dwBytesTransferred);
                    ECGFile.Flush();                  
    }
   }
   while (dwBytesTransferred);
  }  
 }
 ECGFile.Close();  
 return len;
}
    該函數(shù)的調(diào)用是在一個單獨的線程函數(shù)ReadThread中,我們創(chuàng)建一個單獨的線程來讀串口數(shù)據(jù),用如下的語句來創(chuàng)建該讀線程。
    hReadThread = CreateThread (NULL,0,(LPTHREAD_START_ROUTINE)ReadThread, this, 0, &dwThreadID))
    在ReadData函數(shù)中先使用SetCommMask設(shè)置事件掩碼,然后WaitCommEvent就阻塞線程,直到“串口接收到一個字符”的預(yù)定事件發(fā)生線程才繼續(xù)執(zhí)行。

在用ReadFile函數(shù)讀數(shù)據(jù)是要注意以下3點:
    a) 接收緩沖區(qū)Byte的大小最好和ReadFile中第3個參數(shù)(即要讀取的字節(jié)數(shù))一致。
    b) 緩沖區(qū)Byte的大小要根據(jù)實際情況來設(shè)置,當(dāng)要接收的數(shù)據(jù)比較多,波特率又設(shè)的較高時應(yīng)盡量將緩沖區(qū)設(shè)的大些,否則可能會使數(shù)據(jù)丟失。
    c) ReadFile中的第四個參數(shù)是實際接收到的字節(jié)數(shù),由于通信中常常不可預(yù)料的會發(fā)生各種異常情況,每次實際接收到的字節(jié)數(shù)未必和你希望接收的數(shù)量一致,所以當(dāng)每次從接收緩沖區(qū)中取數(shù)據(jù)時應(yīng)以dwBytesTransferred的值為準(zhǔn),這樣可以避免將不是串口得到的數(shù)據(jù)也錯誤的取進(jìn)來。
    當(dāng)接收的數(shù)據(jù)量大時我們不得不考慮到Windows CE系統(tǒng)的內(nèi)存限制問題,那么有限的內(nèi)存根本無法將那么多的數(shù)據(jù)同時放在內(nèi)存中。實際情況確實也是這樣的,在實驗中每次當(dāng)串口接收的數(shù)據(jù)多達(dá)幾十K時,往往會發(fā)生堆棧溢出等異常。于是我們考慮將每次ReadFile接收到的數(shù)據(jù)讀進(jìn)內(nèi)存后就將它永久存儲到對象存儲器中,當(dāng)然也可以是自備的存儲卡,就像上面給出的程序,我們用MFC中的CFile類來完成文件的存儲功能。ReadData函數(shù)的第2個參數(shù)傳入的就是存儲文件的路徑和名字。這樣每次只要消耗固定量的內(nèi)存,解決了內(nèi)存的問題。當(dāng)然,如果在實際中需要從串口接收的數(shù)據(jù)不是很多時,為了方便數(shù)據(jù)的處理,我們通常還是把它們都放在內(nèi)存中。

3) 數(shù)據(jù)的發(fā)送
    主要是在函數(shù)SendData中調(diào)用了API函數(shù)WriteFile,本系統(tǒng)中只需向單片機發(fā)送一些參數(shù)的設(shè)置和簡單的控制指令,應(yīng)用相對比較簡單。我們也創(chuàng)建一個單獨的線程來寫數(shù)據(jù)到串口,對SendData函數(shù)的調(diào)用在線程函數(shù)SendThread中,創(chuàng)建寫線程的方法和讀線程類似。

4) 串口的關(guān)閉
    串口的關(guān)閉是最簡單的,只需使用CloseHandle函數(shù)就可以了。

4. AT89C52單片機的串行通信

    智能采集部分我們采用的是AT89C52單片機,采用中斷的方式來與掌上電腦進(jìn)行數(shù)據(jù)通信。我們設(shè)定單片機的串口控制寄存器SCON=0x50 ,使串口工作在方式1(即10位異步收發(fā)方式),在這種方式下,串行口的波特率是可編程的,由所使用的定時器的溢出率決定。AT89C52除了有定時器0和1外,還增加了定時器2,定時器2是一個16位定時/計數(shù)器,其控制和狀態(tài)位位于T2CON和T2MOD,寄存器對RCAP2H,RCAP2L是定時器2在16位自動重裝載方式下的自動重裝載寄存器。
    在單片機的串行通信中波特率的設(shè)定是最關(guān)鍵的工作,它決定了通信的速度和成敗。波特率最終是由單片機的主機頻率和定時器的工作方式?jīng)Q定的。通常情況下,單片機的晶振頻率一般選用12M或24M等整數(shù),采用定時器1來作為波特率發(fā)生器,因為51系列的單片機沒有定時器2。這樣就會出現(xiàn)問題,大家經(jīng)常會發(fā)現(xiàn)當(dāng)設(shè)置波特率較高時串口接收的數(shù)據(jù)就會發(fā)生錯誤。經(jīng)過了一段時間的研究,我們找到了原因,當(dāng)采用T1作為自動重裝初值的8位計數(shù)器來產(chǎn)生波特率時,由于單片機晶振是12M或24M,T1的計數(shù)頻率是1/12的單片機主頻,根據(jù)T1的溢出率計算得出的定時器初值不夠精確,會產(chǎn)生一定的誤差,而且誤差隨著所設(shè)波特率的提高而增加。這時的波特率計算公式如下:

波特率=

其中fosc是單片機主頻,當(dāng)SMOD=1時,波特率加倍。
有如下2個方法可以解決這個問題:
    1) 調(diào)整單片機的主頻,可以選用11.0592M,22.1184M等來消除波特率設(shè)置的誤差。
    2) 采用具有16位定時/計數(shù)器T2的單片機,如AT89C52。這時使用T2的16位自動重裝初      值的工作方式來產(chǎn)生波特率,在串口工作在工作方式1時,波特率的計算公式如下:
      波特率=        
    由于T2的初值是16位的,且這種工作方式下T2的計數(shù)頻率是1/2的單片機主頻,按照上述公式計算得到的定時器初值的精度足以實現(xiàn)我們所需的波特率。
    根據(jù)上面的分析,我們采用第2個方案,設(shè)置T2CON=0x34,使T2工作于波特率發(fā)生器方式,通過TH2,TL2設(shè)置定時器初值,在該方式下寄存器RCAP2H和RCAP2L中的值應(yīng)與TH2和TL2中相同,以便在T2溢出時,將RCAP2H和RCAP2L中的初值自動重裝到TH2和TL2中。
具體的單片機串口設(shè)置如下:
  SCON=0x50;              //串口工作在方式1
         TH2=0xff;              
         TL2=0xd9;               //設(shè)置波特率為19200
         RCAP2H=0xff;   
         RCAP2L=0xd9;
         T2MOD=0x00;
         T2CON=0x34;             //T2工作工作于波特率發(fā)生器方式
         IE=0x90;                //開串口中斷

5  總結(jié)

    本文介紹了在Windows CE環(huán)境下與單片機的基于多線程的串行通信的實現(xiàn)問題。深入研究了Windows CE中對基于多線程的串口通信的各項設(shè)置和數(shù)據(jù)接收中應(yīng)注意的地方,并提出了AT89C52單片機的串口通信中波特率正確設(shè)定的方法,特別適用于傳輸?shù)臄?shù)據(jù)量較大且波特率較高的情況。在實際工作中,我們利用基于Windows CE的系統(tǒng),通過RS-232C標(biāo)準(zhǔn)接口,與使用單片機的采集模塊進(jìn)行大量數(shù)據(jù)通信,采用文中介紹的方法,實現(xiàn)了準(zhǔn)確、可靠的數(shù)據(jù)傳輸。

熱點新聞

推薦產(chǎn)品

x
  • 在線反饋
1.我有以下需求:



2.詳細(xì)的需求:
姓名:
單位:
電話:
郵件:
主站蜘蛛池模板: 天天色踪合合 | 国产成人高清精品免费软件 | 国产亚洲青色国产 | 国产中文久久精品 | 伊人久久综合 | 日韩亚洲影院 | 嫩操影院| 久久久久国产视频 | 99pao在线视频成精品 | 国语自产自拍秒拍在线视频 | 成人影院www在线观看 | 国产91臀交在线播放 | 成人区视频爽爽爽爽爽 | 亚洲一级大片 | 国产精品久久婷婷六月丁香 | 亚洲 欧美 在线观看 | 国内精品福利爱丝视频_速发 | 日韩高清性爽一级毛片免费 | 成人免费大片a毛片 | 91制服丝袜在线 | 丁香五六月婷婷 | 国产成人拍精品视频网 | 黄片一级毛片 | 久操视频网站 | 欧美一级片a | 精品国产区一区二区三区在线观看 | 亚洲婷婷网 | 综合aⅴ| 欧美太黄太色视频在线观看 | 特级毛片全部免费播放a一级 | 色综合网亚洲精品久久 | 国产亚洲精品一区999 | 日韩一及片 | 国内在线亚洲精品第一线 | 夜夜爽天天狠狠九月婷婷 | 国产在线一区二区 | 黄色成人在线视频 | 免费看片aⅴ免费大片 | 亚洲高清免费观看 | 免费观看黄色一级片 | 亚洲免费美女视频 |