專注差異化嵌入式產(chǎn)品解決方案 給智能產(chǎn)品定制注入靈魂給予生命
提供開(kāi)發(fā)工具、應(yīng)用測(cè)試 完善的開(kāi)發(fā)代碼案例庫(kù)分享
從全面的產(chǎn)品導(dǎo)入到強(qiáng)大技術(shù)支援服務(wù) 全程貼心伴隨服務(wù),創(chuàng)造無(wú)限潛能!
提供新的芯片及解決方案,提升客戶產(chǎn)品競(jìng)爭(zhēng)力
提供最新的單片機(jī)資訊,行業(yè)消息以及公司新聞動(dòng)態(tài)
摘 要 介紹一種運(yùn)用PIC16F84單片機(jī)實(shí)現(xiàn)與PC機(jī)串行通信的方法,并給出其硬件接口電路及通信源程序。
1 前言 美國(guó)Microchip公司的PIC16系列單片機(jī)是一種新型的CMOS工藝的8位單片機(jī)。其中,PIC16FXX單片機(jī)的程序存儲(chǔ)器為電可擦除閃速存儲(chǔ)器(flash),可多次修改程序,甚至可以在線編程。PIC16F83和PIC16F84片內(nèi)數(shù)據(jù)存儲(chǔ)器除RAM外,還有64字節(jié)的EEPROM,可以當(dāng)作一般的或非易失性的數(shù)據(jù)存儲(chǔ)器使用,簡(jiǎn)單方便。它還具有片內(nèi)上電復(fù)位、延時(shí)電路、看門狗電路等。另外,PIC16系列單片機(jī)功耗極低,因而是一種非常適合在各種便攜式設(shè)備中使用的高性價(jià)比的單片機(jī),并已經(jīng)得到了越來(lái)越廣泛的應(yīng)用。 但是在許多需要大量計(jì)算的運(yùn)用中,還必須借助微機(jī)的強(qiáng)大數(shù)據(jù)處理能力。這樣必須通過(guò)通信電路實(shí)現(xiàn)PIC單片機(jī)與微機(jī)間的可靠數(shù)據(jù)傳輸。有的PIC16單片機(jī)內(nèi)并沒(méi)有提供串行口,所以串行通信必須通過(guò)自己設(shè)計(jì)的硬件電路和通信軟件來(lái)實(shí)現(xiàn)。 下面介紹用查詢法實(shí)現(xiàn)異步串行通訊的方法。同時(shí)給出了用PIC16F84單片機(jī)的兩個(gè)I/O口模擬2線串行口的硬件接口電路、程序流程框圖、單片機(jī)內(nèi)通信程序以及微機(jī)內(nèi)的通信程序等。
1 前言 美國(guó)Microchip公司的PIC16系列單片機(jī)是一種新型的CMOS工藝的8位單片機(jī)。其中,PIC16FXX單片機(jī)的程序存儲(chǔ)器為電可擦除閃速存儲(chǔ)器(flash),可多次修改程序,甚至可以在線編程。PIC16F83和PIC16F84片內(nèi)數(shù)據(jù)存儲(chǔ)器除RAM外,還有64字節(jié)的EEPROM,可以當(dāng)作一般的或非易失性的數(shù)據(jù)存儲(chǔ)器使用,簡(jiǎn)單方便。它還具有片內(nèi)上電復(fù)位、延時(shí)電路、看門狗電路等。另外,PIC16系列單片機(jī)功耗極低,因而是一種非常適合在各種便攜式設(shè)備中使用的高性價(jià)比的單片機(jī),并已經(jīng)得到了越來(lái)越廣泛的應(yīng)用。 但是在許多需要大量計(jì)算的運(yùn)用中,還必須借助微機(jī)的強(qiáng)大數(shù)據(jù)處理能力。這樣必須通過(guò)通信電路實(shí)現(xiàn)PIC單片機(jī)與微機(jī)間的可靠數(shù)據(jù)傳輸。有的PIC16單片機(jī)內(nèi)并沒(méi)有提供串行口,所以串行通信必須通過(guò)自己設(shè)計(jì)的硬件電路和通信軟件來(lái)實(shí)現(xiàn)。 下面介紹用查詢法實(shí)現(xiàn)異步串行通訊的方法。同時(shí)給出了用PIC16F84單片機(jī)的兩個(gè)I/O口模擬2線串行口的硬件接口電路、程序流程框圖、單片機(jī)內(nèi)通信程序以及微機(jī)內(nèi)的通信程序等。
PIC16F84單片機(jī)內(nèi)通信程序的設(shè)計(jì)
接收子程序框圖 圖3發(fā)送子程序框圖 圖2和圖3分別是串行發(fā)送和接收的子程序流程框圖。發(fā)送時(shí),通過(guò)使數(shù)據(jù)發(fā)送端DX為低電平并保持B秒(9600波特率時(shí)為104μs)來(lái)發(fā)送起始位。隨后每B秒鐘通過(guò)置位或清零DX端把數(shù)據(jù)發(fā)送出去。這里的B是指一位所持續(xù)的時(shí)間(B=1/波特率)。接收時(shí),數(shù)據(jù)接收端DR大約要每B/2秒(9600波特率時(shí)為52μs)查詢一次以檢測(cè)起始位,如果檢測(cè)到起始位,則在大約1.5B秒(9600波特率時(shí)為156μs)后檢測(cè)第一位數(shù)據(jù)位,隨后每B秒鐘檢測(cè)一次其它的數(shù)據(jù)位。 相應(yīng)的源程序如下: ;接收子程序 Rcvr clrwdt ;清片內(nèi)看門狗 ;定時(shí)器 btfsc RA,DR ;檢測(cè)起始位 goto Rcvr ;未檢測(cè)到起始位 movlw 8 ;檢測(cè)到起始位 movwf R_CNT ;8位數(shù)據(jù)位 Rnext call Delay ;延時(shí)B/2秒 bcf STATUS,C ;清進(jìn)位標(biāo)志 rrf RevReg ;LSB在先 btfsc RA,DR ;該位為0 ;還是為1 bsf RcvReg,MSB ;為1 call Delay ;延時(shí)B/2秒 decfsz R_CNT goto Rnext retlw0 ;返回 ;發(fā)送子程序 Xmtr clrwdt ;清片內(nèi)看門狗 ;定時(shí)器 movlw 8 ;發(fā)送位數(shù)為8 movwf X_CNT bcf RA,DX ;發(fā)送起始位 Xnext call Delay ;延時(shí)B/2秒 call Delay ;延時(shí)B/2秒 rrf XmtReg ;LSB在先 btfsc STATUS,C ;檢測(cè)將要發(fā)送 ;的數(shù)據(jù)位 bsf RA,DX ;數(shù)據(jù)位為1 btfss STATUS,C bcf RA,DX ;數(shù)據(jù)位為0 decfsz X_CNT ;位計(jì)數(shù)為0則 ;發(fā)停止位 goto Xnext ;位計(jì)數(shù)不為0 ;則發(fā)下一位數(shù)據(jù)位 Xstop call Delay ;延時(shí)B/2秒 call Delay ;延時(shí)B/2秒 Bsf RA,DX ;發(fā)送停止位 Retlw 0 ;返回 ;延時(shí)子程序 Delay movlw 12 ;52μS延時(shí) movwf DCNT ; Dnext decfsz DCNT goto Dnext ; retlw 0 ;
4 Win95的串行通信機(jī)制及串口查詢法的原理 常用的DOS系統(tǒng)主要是工作在響應(yīng)中斷方式。PC機(jī)串行通信程序大多利用其BIOS塊的INT14H中斷,以查詢串口的方式完成異步串行通信。 Windows系統(tǒng)函數(shù)即包含了通信支持中斷功能。Win95系統(tǒng)為每個(gè)通信設(shè)備開(kāi)辟了用戶定義的輸入輸出緩沖區(qū)(即讀/寫(xiě)緩沖區(qū)),數(shù)據(jù)進(jìn)出通信口均由系統(tǒng)后臺(tái)來(lái)完成。應(yīng)用程序只需完成對(duì)輸入輸出緩沖區(qū)操作就可以了。實(shí)際過(guò)程是每接收一個(gè)字符就產(chǎn)生一個(gè)低級(jí)硬件中斷,Win95系統(tǒng)中的串行驅(qū)動(dòng)程序就取得了控制權(quán),并將接收到的字符放入輸入數(shù)據(jù)緩沖區(qū)。然后將控制權(quán)返還正在運(yùn)行的應(yīng)用程序。如果輸入緩沖區(qū)數(shù)據(jù)已滿,串行驅(qū)動(dòng)程序用當(dāng)前定義的流控制機(jī)制通知發(fā)送方停止發(fā)送數(shù)據(jù)。隊(duì)列中的數(shù)據(jù)按“先進(jìn)先出”的次序處理。 (1) 按協(xié)議的設(shè)置初始化并打開(kāi)串口,這樣做就是通知Windows本應(yīng)用程序需要這個(gè)串口,并封鎖其他應(yīng)用程序使它們不能使用此串口。 (2) 配置這個(gè)串口。 (3) 在串口上往返地傳輸數(shù)據(jù),并在傳輸過(guò)程中進(jìn)行校驗(yàn)。 (4) 不需要此串口時(shí),關(guān)閉串口。即釋放串口以供其它應(yīng)用程序使用。 在這四個(gè)步驟中,主要的程序代碼集中在第(3)步。 串口查詢法是一種主要工作在查詢方式下的實(shí)現(xiàn)方法。當(dāng)通信程序工作在“查詢”方式時(shí),可以不考慮Win95的進(jìn)程和線程的問(wèn)題。僅在串口有數(shù)據(jù)時(shí),去讀串口緩沖區(qū)就可以了,如圖4所示。這種方法下確定串口讀取的時(shí)機(jī)、握手協(xié)議及軟件糾錯(cuò)的實(shí)現(xiàn)是程序員應(yīng)考慮的主要問(wèn)題。
串口初始化流程 由于這種方法主要工作在查詢方式。程序員必須完成相當(dāng)一部分通信狀態(tài)的檢測(cè)工作,許多細(xì)節(jié)(甚至包括通信過(guò)程中的字符屬性的轉(zhuǎn)換)也必須通過(guò)程序代碼完成。這種查詢方法對(duì)通信雙方協(xié)議的依賴性尤其大。雙方通信協(xié)議的約定對(duì)程序?qū)崿F(xiàn)的難易程度影響很大。 串口查詢法中,一般串口初始化的流程如圖5。 值得注意的一點(diǎn)是,此方法下協(xié)議的約定必須滿足以下條件:即甲方發(fā)送時(shí),乙方必須在甲方發(fā)送動(dòng)作之前進(jìn)入循環(huán)接收狀態(tài),直到接收到字符后通過(guò)對(duì)串口讀取函數(shù)ReadFile返回值的判斷跳出循環(huán)狀態(tài)。 同時(shí),一般為了不使系統(tǒng)因循環(huán)等待接收而進(jìn)入“死循環(huán)”狀態(tài),可以人為設(shè)置讀取串口的循環(huán)次數(shù),一般1000~10000次即可。 本程序的實(shí)現(xiàn)平臺(tái)是VB4,這是一種極為靈活的高級(jí)語(yǔ)言,它可以方便地引入?yún)R編語(yǔ)言的思維,利用其GoTo轉(zhuǎn)向語(yǔ)句方便地控制程序的流程,靈活方便。
5 PC機(jī)內(nèi)通信程序的實(shí)例 現(xiàn)約定甲方是PC機(jī),乙方是單片機(jī)系統(tǒng)(如讀卡器)。通信格式設(shè)置為2400波特率,8位數(shù)據(jù)位,1位停止位,無(wú)奇偶校驗(yàn)。 下面是一個(gè)約定好通訊協(xié)議的程序?qū)嵗?,協(xié)議流程如圖6所示。 以下是甲方(PC機(jī))的幾個(gè)子函數(shù)的程序?qū)嵗?nbsp; 通信協(xié)議流程 Private Function OpenThePort(cPort as String,cBaud as String,cParity as String,cData as String,tStops asString)As Boolean ’ 打開(kāi)串口的子過(guò)程 Dim lResult as Long Dim lHandle as Long Dim DCB_COMM as DCB Dim cDCBConfig as String lHandle = CreateFile(cPort,GENERIC_READ Or GENERIC_WRITE, 0&,0&,OPEN_EXISTING,0&,0&) If lHandle = -1 Then ’打開(kāi)串口失敗 OpenThePort = False MsgBox “串口可能正被其他應(yīng)用程序占用!” lResult = CloseHandle(lHandle) ’先關(guān)閉串口后再打開(kāi) If lResult = 0 Then OpenThePort Exit Function End If End If cDCBConfig.band = 2400 ’設(shè)置DCB cDCBConfig.parity = None cDCBConfig.data = 8 cDCBConfig.stop = 1 lResult = BuildCommDCB(cDCBConfig,DCB_COMM 按用戶設(shè)定配置一個(gè)DCB結(jié)構(gòu) If lResult = 0 Then OpenThePort = False MsgBox “無(wú)法建立DCB設(shè)備控制塊” Exit Function End If lResult = SetCommState(lHandle,DCB_Comm) ’實(shí)際設(shè)置一個(gè)串口的DCB If lResult = 0 Then OpenThePort = False MsgBox “無(wú)法建立DCB設(shè)備控制塊” Exit Function End If OpenThePort = True End Function Private Sub SendHand ( ) ’發(fā)送握手信號(hào)的子過(guò)程 Dim Nchars As Long Static Readbuff As String * 1 Static Writebuff As String * 1 Dim lpDCB As DCB Dim lRet As Long Dim lHandle As Long Dim lpOverlapped As OVERLAPPED Dim RNum As Integer MsgBox “請(qǐng)把讀卡器插在串口2上!”, 48,“提示窗口” lHandle = OpenThePort(COMM1,2400,None,8,1) lRet = PurgeComm( lHandle,1 ) ’清輸出緩沖區(qū) lRet = PurgeComm( lHandle,0 ) ’清輸入緩沖區(qū) lRet = GetCommState ( lHandle,lpDCB ) ’獲得通訊口的狀態(tài) Shand: Writebuff$= Chr$(&H8F) lRet = WriteFile (lHandle,Writebuff$,1,Nchars,lpOverlapped ) ’送握手信號(hào)入串口緩沖區(qū) If lRet <= 0 Then MsgBox “發(fā)送操作出錯(cuò),卡握手信號(hào)未發(fā)送成功”, 16 GoTo Shand ’不成功則重發(fā) Else GoTo Qtest End If GoTo Shand Qtest: Readbuff$ =“ ” ’清除緩沖區(qū)為空 Do While lHandle ’循環(huán)查詢串口 RNum = 0 ’設(shè)置讀串口次數(shù)的指針為0 ReadAgain: lRet = ReadFile( lHandle, Readbuff$,1,Nchars,lpOverlapped ) If lRet < 0 Then MsgBox “讀取應(yīng)答信號(hào)時(shí)出錯(cuò)”, 16 End If If lRet = 0 Then If RNum > 1000 Then ’只讀1000次串口,以免陷入死循環(huán) MsgBox "卡沒(méi)有插接好或卡沒(méi)有接在串口上!" GoTo CloseP End If RNum = RNum + 1 GoTo ReadAgain End If If Hex$(Asc(Readbuff)) <> Hex$(&HFF) Then GoTo Shand ’回送碼不正確則返回繼續(xù)發(fā)送握手信號(hào) Else Label1.Caption = “握手信號(hào)是:” +Hex$(Asc(Readbuff$)) Msgbox “握手信號(hào)正確,已正確聯(lián)機(jī)” GoTo CloseP End If Loop CloseP:lRet = CloseHandle( lHandle ) If lRet = 0 Then MsgBox “串行通訊口關(guān)閉成功”, 48,“提示窗口” End If End Sub 這里要注意的是:當(dāng)PC機(jī)與單片機(jī)系統(tǒng)通信時(shí),單片機(jī)數(shù)據(jù)存儲(chǔ)區(qū)( RAM )內(nèi)的數(shù)據(jù)是十六進(jìn)制,在信號(hào)線上傳輸?shù)氖鞘M(jìn)制數(shù)的ASCII碼的二進(jìn)制形式;而Windows系統(tǒng)下使用的是ANSI碼,ANSI碼僅在前126個(gè)與ASCII碼相同。即在Win95下接收到的是十六進(jìn)制數(shù)的ASCII碼的字符串,可先轉(zhuǎn)換為ANSI碼后再在Win95下還原為十六進(jìn)制數(shù)。 具體為:Code$=Hex$(Asc ( Readbuff$ ) ) 另外,由于32位API函數(shù)參數(shù)的數(shù)據(jù)類型的變化,所有整形參數(shù)都被換為長(zhǎng)整型(Long)以支持32位的處理,這一點(diǎn)在設(shè)置返回值時(shí)尤其如此。 6 結(jié)束語(yǔ) 以上的軟硬件在我們的實(shí)踐中達(dá)到了較為理想的效果。通過(guò)軟件節(jié)省了硬件的開(kāi)銷,并通過(guò)在PIC16F84單片機(jī)系統(tǒng)和PC機(jī)雙方的通信軟件內(nèi)增加握手信號(hào),達(dá)到了軟件數(shù)據(jù)校驗(yàn)的目的,獲得了較高的通信可靠性。