11.2字符數組和字符指針11.2.1常量和符號常量在程序運行過程中,其值不能被改變的量稱之為常量。常量分為不同的類型,有整型常量如1、2、3、100;浮點型常量3.14、0.56、-4.8;字符型常量‘a’、‘b’、‘0’;字符串常量“a”、 “abc”、“1234”、“1234abcd”等。 整型和浮點型常量直接寫的數字,字符型常量用單引號來表示一個字符,用雙引號來表示一個字符串,尤其要注意‘a’和“a”是不一樣的,后邊會詳細介紹。 常量一般有兩種表現形式。 直接常量:直接以值的形式表示的常量稱之為直接常量。上述舉例都是直接常量。 符號常量:用標識符命名的常量稱之為符號常量,就是為上面的直接常量再取一個名字。使用符號常量一是方便理解,提高程序可讀性,更重要的是方便程序的后續維護,習慣上符號常量用大寫字母和下劃線來命名。 比如,可以把3.14取名為PI(即π)。再比如,前邊的串口程序采用的波特率是9600,如果用符號常量來進行提前聲明的話,那要修改成其它速率的話,就不用在程序中找9600修改了,直接修改聲明處就可以了,兩種方法舉例說明。 1.用const聲明。比如在程序開始位置定義一個符號常量BAUD。 定義形式是:const 類型 符號常量名字=常量值; 如const unsigned int BAUD = 9600; /*注意結尾有個分號*/ 就可以在程序中直接把9600全部采用BAUD替換,這樣如果要改波特率的話,直接在程序開頭位置改一下這個值就可以了。 2.用預處理命令#define來完成。 定義形式是:#define 符號常量名 常量值 如#define BAUD 9600 /*注意結尾沒有分號*/ 這樣定義以后,只要在程序中出現BAUD的話,意思就是完全替代了后邊的9600這個數字。之前定義數碼管真值表的時候,用了一個code關鍵字。 unsigned char code LedChar[] = { //數碼管顯示字符轉換表 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E }; 當時說加了code之后,這個真值表的數據只能被使用,不能被改變,如果直接寫LedChar[0] = 1;這樣就錯了。實際上code這個關鍵字是51單片機特有的,如果是其它類型的單片機需要寫成const unsigned char LedChar[]={},自動保存到FLASH里,而51單片機只用const而不加code的話,這個數組會保存到RAM中,而不會保存到FLAHS中。 整型常量和浮點型常量比較簡單,整型直接寫數字,十進制如128,前邊0x開頭的表示是十六進制0x80,浮點型直接寫帶小數點的數據就可以了。 字符型常量是由一對單引號括起來的單個字符。它分為兩種形式,一種是普通字符,一種是轉義字符。 普通字符就是那些可以直接書寫直接看到的有形的字符,比如阿拉伯數字0~9,英文字符A~z,以及標點符號等。它們都是ASCII碼表中的字符,而它們在單片機中都占用一個字節的空間,其值就是對應的ASCII碼值。比如‘a’的值是97,‘A’的值是65,‘0’的值是48,如果定義一個變量unsigned char a = ‘a’,那么變量a的值就是97。 除了上述這些字符之外,還有一些特殊字符,它們一些是無形的,像回車符、換行符這些都是看不到的,還有一些像’\’這類字符它們已經有特殊用途了。針對這些特殊符號,為了可以讓它們正常進入到程序代碼中,C語言就規定了轉義字符,它是以反斜杠(\)開頭的特定字符序列,讓它們來表示這些特殊字符,比如用\n來代表換行。用一個簡單表格來說明一下常用的轉義字符的意思,如表11-1所示。 表11-1 常用轉義字符及含義 字符串常量是用雙引號括起來的字符序列,一般稱之字符串。如“a”、“1234”、 “welcome to www.qdkingst.com”等都是字符串常量。字符串常量在內存中按順序逐個存儲字符串中的字符的ASCII碼值,并且特別注意,最后還有一個字符‘\0’,‘\0’字符的ASCII碼值是0,它是字符串結束標志,在寫字符串的時候,這個‘\0’是隱藏的,雖然看不到,但是實際卻是存在的。所以“a”就比‘a’多了一個 ‘\0’,“a”的就占了2個字節,而 ‘a’只占一個字節。 還有就是字符串中的空格,也是一個字符,比如“welcome to www.qdkingst.com”一共占了28個字節的空間。其中23個字母,2個‘.’,2個 ‘ ’(空格字符)以及一個‘\0’。 11.2.2字符和字符串數組實例定義4個數組,通過演示程序對比字符串、字符數組、常量數組的區別。 unsigned char array1[] = "1-Hello!\r\n"; unsigned char array2[] = {'2', '-', 'H', 'e', 'l', 'l', 'o', '!', '\r', '\n'}; unsigned char array3[] = {51, 45, 72, 101, 108, 108, 111, 33, 13, 10}; unsigned char array4[] = "4-Hello!\r\n"; 在串口調試助手下,發送十六進制的1、2、3、4,使用字符形式顯示,分別往電腦上送這4個數組中對應的那個數組。程序只在起始位置做了區分,其它均沒有區別。一方面通過串口調試助手觀察,另外通過邏輯分析儀進行對比。 此外還要說明一點,數組1和數組4,數組1發完整的字符串,而數組4僅僅發送數組中的字符,沒有發結束符號。串口調試助手用字符形式顯示是沒有區別的,但是如果改用十六進制顯示,會發現數組1比數組4多了一個字節‘\0’的ASCII值00。 #include <reg52.h> bit cmdArrived = 0; //命令到達標志,即接收到上位機下發的命令 unsigned char cmdIndex = 0; //命令索引,即與上位機約定好的數組編號 unsigned char cntTxd = 0; //串口發送計數器 unsigned char *ptrTxd; //串口發送指針 unsigned char array1[] = "1-Hello!\r\n"; unsigned char array2[] = {'2', '-', 'H', 'e', 'l', 'l', 'o', '!', '\r', '\n'}; unsigned char array3[] = {51, 45, 72, 101, 108, 108, 111, 33, 13, 10}; unsigned char array4[] = "4-Hello!\r\n"; void ConfigUART(unsigned int baud); void main() { EA = 1; //開總中斷 ConfigUART(9600); //配置波特率為9600 while (1) { if (cmdArrived) { cmdArrived = 0; switch (cmdIndex) { case 1: ptrTxd = array1; //數組1的首地址賦值給發送指針 cntTxd = sizeof(array1); //數組1的長度賦值給發送計數器 TI = 1; //手動方式啟動發送中斷,處理數據發送 break; case 2: ptrTxd = array2; cntTxd = sizeof(array2); TI = 1; break; case 3: ptrTxd = array3; cntTxd = sizeof(array3); TI = 1; break; case 4: ptrTxd = array4; cntTxd = sizeof(array4) - 1; //字符串實際長度為數組長度減1 TI = 1; break; default: break; } } } } /* 串口配置函數,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 } /* UART中斷服務函數 */ void InterruptUART() interrupt 4 { if (RI) //接收到字節 { RI = 0; //清零接收中斷標志位 cmdIndex = SBUF; //接收到的數據保存到命令索引中 cmdArrived = 1; //設置命令到達標志 } if (TI) //字節發送完畢 { TI = 0; //清零發送中斷標志位 if (cntTxd > 0) //有待發送數據時,繼續發送后續字節 { SBUF = *ptrTxd; //發出指針指向的數據 cntTxd--; //發送計數器遞減 ptrTxd++; //發送指針遞增 } } } 采用邏輯分析儀將4次收發數據全部抓出來,其中串口助手下發用HEX模式,而接收用文本模式,也就是ASCII碼格式顯示,邏輯分析儀也是這樣配置,如圖11-2所示。
11-2.png (83.54 KB, 下載次數: 0)
下載附件
2026-4-24 09:55 上傳
圖11-2 邏輯分析儀抓取串口字符和字符串信息 從圖11-2可以看出,1比2、3、4多了一個結束符,其他內容4組數據是完全一致的。(CR就是\r,LF就是\n)
|