本文介紹一種在 80C51 串行通訊應(yīng)用中自動(dòng)檢測(cè)波特率的方法。按照經(jīng)驗(yàn),程序起動(dòng)后所接收到的第1個(gè)字符用于測(cè)量波特率。 這種方法可以不用設(shè)定難于記憶的開關(guān),還可以免去在有關(guān)應(yīng)用中使用多種不同波特率的煩惱。人們可以設(shè)想:一種可靠地實(shí)現(xiàn)自動(dòng)波特檢測(cè)的方法是可能的,它無須嚴(yán)格限制可被確認(rèn)的字符。問題是:在各種的條件下,如何可以在大量允許出現(xiàn)的字符中找出波特率的定時(shí)間隔。 顯然,最快捷的方法是檢測(cè)一個(gè)單獨(dú)位時(shí)間(single bit time),以確定接收波特率應(yīng)該是多少。可是,在 RS-232 模式下,許多 ASCII 字符并不能測(cè)量出一個(gè)單獨(dú)位時(shí)間。對(duì)于大多數(shù)字符來說,只要波特率存在合理波動(dòng)(這里的波特率是指標(biāo)準(zhǔn)波特率),從起始位到最后一位“可見”位的數(shù)據(jù)傳輸周期就會(huì)在一定范圍內(nèi)發(fā)生變化。此外,許多系統(tǒng)采用 8 位數(shù)據(jù)、無奇偶校驗(yàn)的格式傳輸 ASCII 字符。在這種格式里,普通 ASCII 字節(jié)不會(huì)有 MSB 設(shè)定,并且,UART總是先發(fā)送數(shù)據(jù)低位(LSB),后發(fā)送數(shù)據(jù)高位(MSB),我們總會(huì)看見數(shù)據(jù)的停止位。 在下面的波特率檢測(cè)程序中,先等待串行通訊輸入管腳的起始信號(hào)(下降沿),然后起動(dòng)定時(shí)器T0。在其后的串行數(shù)據(jù)的每一個(gè)上升沿,將定時(shí)器 T0的數(shù)值捕獲并保存。當(dāng)定時(shí)器T0溢出時(shí),其最后一次捕獲的數(shù)值即為從串行數(shù)據(jù)起始位到最后一個(gè)上升沿(我們假設(shè)是停止位)過程所持續(xù)的時(shí)間。 CmpTable 表格列出了每一波特率的最大測(cè)量時(shí)間。這些數(shù)據(jù)是經(jīng)過選擇的,所以,4 個(gè)數(shù)據(jù)位時(shí)間(加上起始位時(shí)間)仍可產(chǎn)生正確的波特率。 使用這種方法時(shí),必須遵守一個(gè)假設(shè):這種技術(shù)僅取決于所接收到的一個(gè)字符,接收這個(gè)字符的波特率必須大于最低波特率。本質(zhì)上來說,這意味著這個(gè)字符必須來自正常敲擊鍵盤時(shí)所產(chǎn)生的字符。 在PC上,我們不可能快速、連續(xù)地敲擊兩個(gè)字符,以欺騙程序。但是,PC的功能鍵具有一個(gè)問題,因?yàn)樗鼤?huì)連續(xù)發(fā)送兩個(gè)緊挨著的字符,使程序檢測(cè)得到錯(cuò)誤的波特率。在為 12MHz時(shí)鐘頻率而設(shè)計(jì)的的例子程序中,其總采樣時(shí)間大約為 65mS,大約可以在 RS-232 通訊中以300bps的速度發(fā)送兩個(gè)字符。 假如使用了奇偶校驗(yàn),當(dāng)4 個(gè)MSB以及所接收字節(jié)的奇偶校驗(yàn)位均這同一值時(shí),就可能會(huì)發(fā)生錯(cuò)誤。這類錯(cuò)誤的發(fā)生取決于系統(tǒng)是使用了奇校驗(yàn)或偶校驗(yàn),可能發(fā)生于小寫的字母“p”到“z”,還有花括號(hào)({})、垂直條(|)、波紋線(~),以及刪除鍵“delete”。值得注意的是,慣常的提示符按鍵(如,空格鍵、回車鍵、及返回鍵),是沒有這些限制的(奇數(shù)還是偶數(shù)的限制?)。 在以此方式運(yùn)行程序時(shí),如第一個(gè)字節(jié)已經(jīng)過去,但串行口(UART)的波特率未能正確設(shè)置,那將造成用于檢測(cè)波特率的第一個(gè)字符丟失。同樣,如果在正常通訊中檢測(cè)到串行口的通訊“幀”錯(cuò)誤,絕大部分“實(shí)時(shí)”程序必須重復(fù)這一檢測(cè)波特率的過程。 如需采用另外設(shè)定的晶體振蕩頻率、波特率,請(qǐng)使用下列公式計(jì)算 CmpTable的表項(xiàng)目: 記住,表項(xiàng)目是兩個(gè)字節(jié)的數(shù)值,所以上述公式的結(jié)果一定要分成高位字節(jié)及低位字節(jié)(如果采用十六進(jìn)制,則容易得出高位、低位字節(jié))。當(dāng)然,也可以用匯編程序來完成所有的運(yùn)算。 上述的公式是由以下得來的:
備注:在 8-N-1 格式的數(shù)據(jù)通訊中,‘#-of-bits’(“可見”位數(shù))是 9,以及‘bits-to-recognize’(最小認(rèn)可位數(shù))是5。
;***************************************************************************** ;自動(dòng)的波特率檢測(cè)程序 ;***************************************************************************** $ Title(Automatic Baud Rate Detection Test) $ Date(12–16–91) $ MOD552 ;***************************************************************************** ; Definitions ;***************************************************************************** RX BIT P3.0 ;串行口的接收管腳 CharH DATA 30h ;捕獲定時(shí)器T0的高位字節(jié) CharL DATA 31h ;捕獲定時(shí)器T0的低位字節(jié) BaudRate DATA 32h ;存貯最終確定的波特率 Display EQU P4 ;顯示結(jié)果的端口 ;***************************************************************************** ; Reset and Interrupt Vectors ;***************************************************************************** ORG 8000h Start: ACALL AutoBaud ;檢測(cè)波特率 MOV Display, BaudRate ;顯示波特率值 SJMP Start ;***************************************************************************** ; Subroutines ;***************************************************************************** ;AutoBaud Rate Detect Routine. ;通過測(cè)量接收第一個(gè)字符所需要的時(shí)間來確定波特率。部分接收字符可能會(huì)發(fā)生錯(cuò)誤, ;主要是那些以3(4?)位同樣數(shù)值結(jié)束的字符。波特率指針(檢測(cè)結(jié)果)保存在ACC中。 ;***************************************************************************** AutoBaud: MOV TMOD, #01h ;初始化T0(串行口波特率定時(shí)器) MOV TH0, #0 ;將T0 置于16位定時(shí)器模式 MOV TL0, #0 MOV TCON, #0 MOV CharH, #0 ;預(yù)置波特率檢測(cè)結(jié)果 MOV CharL, #0 AB0: JB RX, AB0 ;等待串行通訊起始 SETB TR0 ;起動(dòng)定時(shí)器 T0 AB1: JB TF0, AB3 ;檢查定時(shí)器是否溢出? JNB RX, AB1 ;檢測(cè)串行信號(hào)上升沿? MOV CharH, TH0 ;在串行信號(hào)上升沿捕獲定時(shí)器T0數(shù)值 MOV CharL, TL0 AB2: JB TF0, AB3 ;檢查定時(shí)器是否溢出? JB RX, AB2 ;檢查串行信號(hào)下降沿? SJMP AB1 ;返回,繼續(xù)采集 AB3: CLR TR0 ;最大的采集時(shí)間已經(jīng)超過,檢查結(jié)果 CLR TF0 ;清除定時(shí)器溢出標(biāo)志 MOV BaudRate, #19 ;設(shè)置波特率表指針 CmpLoop: MOV A, BaudRate MOV DPTR, #CmpTable MOVC A, @A+DPTR ;取一個(gè)表項(xiàng)目(高位字節(jié))以進(jìn)行比較 DEC BaudRate CJNE A, CharH, Cmp1 ;捕獲值與表項(xiàng)目的高位字節(jié)相等? SJMP CmpLow ;高位字節(jié)相等,檢查低位字節(jié) Cmp1: JC CmpMatch ;表項(xiàng)目小于定時(shí)值,則符合? DJNZ BaudRate, CmpLoop ;未至表項(xiàng)目的結(jié)尾,則繼續(xù)? SJMP CmpMatch ;至比較結(jié)束 CmpLow: MOV A, BaudRate MOVC A, @A+DPTR ;取一個(gè)表項(xiàng)目(低位字節(jié))以進(jìn)行比較 CJNE A, CharL, Cmp2 ;捕獲值與表項(xiàng)目的低位字節(jié)相等? SETB C ;結(jié)果相等 Cmp2: JC CmpMatch ;如果表項(xiàng)目<定時(shí)值,則置位C DJNZ BaudRate, CmpLoop ;未至表項(xiàng)目的結(jié)尾,則繼續(xù)? CmpMatch: MOV A, BaudRate ;數(shù)據(jù)比較完成 CLR C ;產(chǎn)生結(jié)果(波特率索引) RRC A MOV BaudRate, A ;保存結(jié)果 RET ;***************************************************************************** ; CmpTable 比較表 ;***************************************************************************** ;比較表所保持的定時(shí)值用于公認(rèn)的波特率轉(zhuǎn)換情況。表項(xiàng)目為低位(LSB)、高位(MSB)。 ;這些數(shù)據(jù)是以12MHz為基準(zhǔn)操作。 CmpTable: DB 40h,0 ;0 – 超出范圍,值太低 DB 80h,0 ;1 – 38400 baud. DB 0,01h ;2 – 19200 baud. DB 0,02h ;3 – 9600 baud. DB 0,04h ;4 – 4800 baud. DB 0,08h ;5 – 2400 baud. DB 0,10h ;6 – 1200 baud. DB 0,20h ;7 – 600 baud. DB 0,40h ;8 – 300 baud. DB 0,80h ;9 – 超出范圍,值太高 END
附: 波特率自動(dòng)檢測(cè)程序(通過驗(yàn)證) RX BIT P3.0 ;串行數(shù)據(jù)接收端 CharH EQU 30H ;計(jì)時(shí)數(shù)據(jù)高位 TH0 CharL EQU 31H ;計(jì)時(shí)數(shù)據(jù)低位 TL0 BaudRt EQU 32H ;波特率計(jì)算值 ;subroutine AutoBaud: MOV TMOD, #01H ;初始化“T0”為計(jì)時(shí)器 MOV TH0, #0 MOV TL0, #0 MOV TCON, #0 MOV CharH, #0 MOV CharL, #0 JB RX, $ ;等待通訊開始位 SETB TR0 CHK1: JBC TF0, CHK_END ;若溢出,則開始計(jì)算 JNB RX, $-2 ;檢測(cè)串行數(shù)據(jù)上升沿 MOV CharH, TH0 ;捕獲“T0”計(jì)時(shí)數(shù) MOV CharL, TL0 JBC TF0, CHK_END ;若溢出,則開始計(jì)算 JB RX, $-2 ;檢測(cè)串行數(shù)據(jù)下降沿 SJMP CHK1 CHK_END: CLR TR0 ;停止計(jì)數(shù)器 MOV DPTR, #baudtable MOV BaudRt, #19 LOOP: MOV A, BaudRt ; MOVC A, @A+DPTR ;取表格數(shù)據(jù)(高位) DEC BaudRt ;索引地址減 1 CJNE A, CharH, CMP_1 ;檢查結(jié)果范圍 SJMP CMP_LOW CMP_1: JC MATCH ;若表中值 < 計(jì)時(shí)值,則匹配 DJNZ BaudRt, LOOP SJMP MATCH ;表查完,至結(jié)束查表程序 CMP_LOW: MOV A, BaudRt ;高位相等,比較低位 MOVC A, @A+DPTR CJNE A, CharL, CMP_2 SETB C ;相等則匹配 CMP_2: JC MATCH ;若低位字節(jié) < 計(jì)時(shí)值,則匹配 DJNZ BaudRt, LOOP MATCH: MOV A, BaudRt ;轉(zhuǎn)換為波特率索引值 CLR C RRC A MOV BaudRt, A ;保存 RET ;波特率索引表(LSB 在前,MSB 在后,晶振為11.0592MHz) baudtable: DB 03CH,00H ;0-越限,值太小 DB 078H,00H ;1-波特率 38400 DB 0F0H,00H ;2-波特率 19200 DB 0E0H,01H ;3-波特率 9600 DB 0C0H,03H ;4-波特率 4800 DB 080H,07H ;5-波特率 2400 DB 00H,00FH ;6-波特率 1200 DB 00H,01EH ;7-波特率 600 DB 00H,03CH ;8-波特率 300 DB 00H,078H ;9-越限,值太大
|