單片機通訊實例與ASCII碼

我們進修串口通訊次要是要完成單片機和電腦之間的信息交互,可以用電腦掌握單片機的一些信息,可以把單片機的一些信息情況發給電腦上的軟件。下面我們就做一個複雜的例程,完成單片機串口調試助手發送的數據,在我們開闢板上的數碼管上顯示出來。

			#include <reg52.h> sbit ADDR3 = P1^3; sbit ENLED = P1^4; unsigned char code LedChar[] = { //數碼管顯示字符轉換表 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E }; unsigned char LedBuff[7] = { //數碼管+自力 LED 顯示緩衝區 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; unsigned char T0RH = 0; //T0 重載值的高字節 unsigned char T0RL = 0; //T0 重載值的低字節 unsigned char RxdByte = 0; //串口接納到的字節 void ConfigTimer0(unsigned int ms); void ConfigUART(unsigned int baud); void main(){ EA = 1; //使能總中綴 ENLED = 0; //選擇數碼管和自力 LED ADDR3 = 1; ConfigTimer0(1); //設置裝備擺設 T0 準時 1ms ConfigUART(9600); //設置裝備擺設波特率爲 9600 while (1){ //將接納字節在數碼管上以十六進制方式顯示出來 LedBuff[0] = LedChar[RxdByte & 0x0F]; LedBuff[1] = LedChar[RxdByte >> 4]; } } /* 設置裝備擺設並啓動 T0,ms-T0 準時工夫 */ void ConfigTimer0(unsigned int ms){ unsigned long tmp; //暫時變量 tmp = 11059200 / 12; //準時器計數頻率 tmp = (tmp * ms) / 1000; //盤算所需的計數值 tmp = 65536 - tmp; //盤算準時重視載值 tmp = tmp + 13; //賠償中綴呼應延時形成的誤差 T0RH = (unsigned char)(tmp>>8); //準時重視載值拆分爲上下字節 T0RL = (unsigned char)tmp; TMOD &= 0xF0; //清零 T0 的掌握位 TMOD |= 0x01; //設置裝備擺設 T0 爲形式 1 TH0 = T0RH; //加載 T0 重載值 TL0 = T0RL; ET0 = 1; //使能 T0 中綴 TR0 = 1; //啓動 T0 } /* 串口設置裝備擺設函數,baud-通訊波特率 */ void ConfigUART(unsigned int baud){ SCON = 0x50; //設置裝備擺設串口爲形式 1 TMOD &= 0x0F; //清零 T1 的掌握位 TMOD |= 0x20; //設置裝備擺設 T1 爲形式 2 TH1 = 256 - (11059200/12/32)/baud; //盤算 T1 重載值 TL1 = TH1; //初值等於重載值 ET1 = 0; //制止 T1 中綴 ES = 1; //使能串口中綴 TR1 = 1; //啓動 T1 } /* LED 靜態掃描刷新函數,需在準時中綴中挪用 */ void LedScan(){ static unsigned char i = 0; //靜態掃描索引 P0 = 0xFF; //封閉一切段選位,顯示消隱 P1 = (P1 & 0xF8) | i; //位選索引值賦值到 P1 口低 3 位 P0 = LedBuff[i]; //緩衝區中索引地位的數據送到 P0 口 if (i < 6){ //索引遞增輪迴,遍歷全部緩衝區 i++; }else{ i = 0; } } /* T0 中綴效勞函數,完成 LED 掃描 */ void InterruptTimer0() interrupt 1{ TH0 = T0RH; //從新加載重載值 TL0 = T0RL; LedScan(); //LED 掃描顯示 } /* UART 中綴效勞函數 */ void InterruptUART() interrupt 4{ if (RI){ //接納到字節 RI = 0; //手動清零接納中綴標記位 RxdByte = SBUF; //接納到的數據保管到接納字節變量中 //接納到的數據又直接發還,叫作-"echo", //用以提醒用戶輸出的信息能否已準確接納 SBUF = RxdByte; } if (TI){ //字節發送終了 TI = 0; //手動清零發送中綴標記位 } }

人人在做這個試驗的時分,有個小成績要留意一下。由於 STC89C52 下載程序是運用了UART 串口下載,下載完程序後,程序運轉起來了,可是下載軟件最初還會經過串口發送一些額定的數據,所以程序剛下載出來不是顯示 00,而能夠是其他數據。人人只需把電源開關封閉,從新翻開一次就好了。
仔細的同窗能夠會發現,在串口調試助手發送選項和接納選項處,還有個“字符格局發送”和“字符格局顯示”,這是什麼意思呢?

先拋開我們運用的漢字不談,那麼我們常用的字符就包括了 0~9 的數字、A~Z/a~z 的字母、還有各類標點符號等。那麼在單片機零碎外面我們怎樣來表現它們呢? ASCII 碼(American Standard Code for Information Interchange,即美國信息交換規範代碼)可以完成這個任務:我們曉得,在單片機中一個字節的數據可以有 0~255 共 256 個值,我們取箇中的 0~127 共 128 個值付與了它別的一層涵義,即讓它們辨別來代表一個常用字符,其詳細的對應關係如表 11-3 所示。
表 11-3 ASCII 碼字符表

ASC掌握ASCII字符ASCII字符ASCII字符
000
NUL
字符
032
(space)064
@096
001SOH033!065A097a
002STX034"066B098b
003ETX035#067C099c
004EOT036$068D100d
005END037%069E101e
006ACK038&070F102f
007BEL039'071G103g
008BS040(072H104h
009HT041)073I105i
010LF042*074J106j
011VT043+075K107k
012FF044076L108l
013CR045-077M109m
014SO046078N110n
015SI047/079O111o
016DLE0480080P112p
017DC10491081Q113q
018DC20502082R114r
019DC30513083S115s
020DC40524084T116t
021NAK0535085U117u
022SYN0546086V118v
023ETB0557087W119w
024CAN0568088X120x
025EM0579089Y121y
026SUB058:090Z122z
027ESC059;091[123{
028FS060<092\124|
029GS061=093]125}
030RS062>094^126~
031US063?095_127DEL


如許我們就在常用字符和字節數據之間樹立了逐個對應的關係,那麼如今一個字節就既可以代表一個整數又可以代表一個字符了,但它實質上只是一個字節的數據,而我們付與了它分歧的涵義,什麼時分付與它哪一種涵義就看編程者的意圖了。ASCII 碼在單片機零碎中使用十分普遍,我們後續的課程也會常常運用到它,下面我們來對它做一個直不雅的看法,同窗們必定要深入瞭解其實質。
對比上述表格,我們就可以完成字符和數字之間的轉換了,比方照樣這個程序,我們發送的時分改成字符格局發送,接納照樣用十六進制接納,如許接納和數碼管好做一下比照。
我們用字符格局發送一個小寫的 a,前往一個十六進制的 0x61,數碼管上顯示的也是 61,ASCII 碼內外字符 a 對應十進制是 97,等於十六進制的 0x61;我們再用字符格局發送一個數字 1,前往一個十六進制的 0x31,數碼管上顯示的也是 31,ASCII 內外字符 1 對應的十進制是 49,等於十六進制的 0x31。這下人人就該清晰了:所謂的十六進制發送和十六進制接納,多是按字節數據的真實值停止的;而字符格局發送和字符格局接納,是按 ASCII 碼錶中字符方式停止的,但它實踐上最終傳輸的照樣一個字節數據。這個表格,當然不需求人人去記住,瞭解它,用的時分過去查就行了。
通訊的進修,不像前邊掌握局部那麼直不雅了,通訊局部我們的程序只能取得一個後果,而其進程我們卻無法直接看到,所以漸漸的能夠人人就會曉得有示波器和邏輯剖析儀這類丈量儀器。假如黌舍試驗室或許公司裏有示波器或許邏輯剖析儀這類儀器,可以拿過去抓一下串口波形,直不雅的理解一下。假如臨時還沒有這些儀器,先曉得這麼回事,有前提再說。由於工具類裝備有的比擬昂貴,有前提可以儘量運用黌舍或許公司的。在這裏我用一款簡略單純的邏輯剖析儀把串口通訊的波形抓出來給人人看一下,人人理解一下即可,如圖 11-7 所示。

圖 11-7 邏輯剖析儀串口數據表示圖
圖 11-7  邏輯剖析儀串口數據表示圖


剖析儀和示波器的感化,就是把通訊進程的波形抓出來停止剖析。先大約說一下波形的意思。波形右邊是低位,左邊是高位,上邊這個波形是電腦發送給單片機的,下邊這個波形是單片機回發給電腦的。以上邊的波形爲例,右邊第一位是肇端位 0,從低位到高位順次是10001100,次序倒一下,就是數據 0x31,也就是 ASCII 碼內外的‘1’。人人可以留意到剖析儀在每一個數據位都給標了一個白色的點,表現是數據,肇端位和有數據的時分都沒有這個白點。工夫標 T1 和 T2 的差值在左邊顯示出來是 0.102ms,大約是 9600 分之一,略微有點偏向,在允許規模內即可。經過圖 11-7,我們可以明晰的理解了串口通訊的收發的具體進程。
那我們這裏再來理解一下,假如我們運用串口調試助手,用字符格局直接發送一個“12”,我們在我們的數碼管上應當顯示什麼呢?串口調試助手應當前往什麼呢?經由實驗發現,我們數碼管顯示的是 32,而串口調試助手前往十六進制顯示的是 31、32 兩個數據,如圖 11-8所示。

圖 11-8 串口調試助手數據顯示
圖 11-8  串口調試助手數據顯示


我們再用邏輯剖析儀把這個數據抓出來看一下,如圖 11-9 所示。

圖 11-9 邏輯剖析儀抓取數據
圖 11-9  邏輯剖析儀抓取數據


關於 ASCII 碼錶來說,數字自身是字符而非數據,所以假如發送“12”的話,實踐上是是辨別發送了“1”和“2”兩個字符,單片機呢,先收到第一個字符“1”,在數碼管上會顯示出 31 這個對應數字,然則立時就又收到了“2”這個字符,數碼管霎時從 31 釀成了 32,而我們視覺上呢,是沒有方法發現這種疾速變更的,所以我們覺得數碼管直接顯示的是 32。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章