1
C語言輸入與輸出
Chih-Hu Wang
Chung-Hua University
C語言輸入與輸出
• 在C語言裡並沒有輸入/輸出指令
• 輸入/輸出是由函式模組來完成
– 例如:printf()就是由stdio.h程式庫中提供的模組
之一 。
– 通常在編譯時編譯器並不會去編譯printf(),而
是在連結時由連結器(linker)處理
• Keil-C系統中則是用建構器(Builder)直接經
編譯與連結轉換成可執行的機械碼。
2
沒有輸入/輸出優點
• 沒有輸入/輸出指令並不是缺點,反而是優點,因
為它不會受限於硬體的架構,
• 輸入/輸出改用函式模組方式則可攜性較佳。
• Keil-C昰用於51系列開發的工具組
• Keil Software公司又在原來的基礎上開發了ARM
系列的開發工具軟體
• 因此當您以C語言設計程式時還是盡可能排除受
限於輸入/輸出的指令,
• 或是將牽涉到輸入/輸出的部分以函式歸納,日後
若有機會改用其他微控制器時,只要更改輸入/輸
出部分的函式即可轉移使用。
C51語言輸入輸出庫
• C51中除了包含C語言標準輸入輸出庫的
stdio.h輸入/輸出函式外,還包括51特有的一
些暫存器資源庫reg51.h之類所包含的硬體介
面。
• 提供了幾個輸出與輸入的函式庫:
– stdio.h中計有:輸出類的函式如printf()、putchar()、
puts(),及輸入類的函式如scanf()、getchar()、
gets()等等。
– 51特有的: reg51.h之類的特殊暫存器SFR資源庫
• 51中之輸入輸出埠(P0、P1、P2、P3 …)、計時計數器
(T0、T1、T2)、串列傳輸(Serial Port)。
3
標準的輸入/輸出:stdio.h
• stdio.h中的函式如
– printf()、putchar()、puts(),
– scanf()、getchar()、gets()
– 我們必需透過串列傳輸與終端機(Terminal)做資料的輸
入與輸出,
– 這是因為51不是一個大系統,沒有鍵盤與螢幕的裝
置,
– 所以當您使用這類函式時應該先設定51的串列傳輸與
終端機相同的通訊協定,
• 如:速率(Baud Rate)、
• 訊號框(Signal Frame)中的資料長度(Data Length)、
• 奇偶位元測試(Prity Check)、
• 停止位元(Stop Bit)等等。
1. #include
2. #include
3. main() /*定義名稱叫做main的函數,沒有傳入/傳回數值*/
4. { /*程式將由此左大括弧後開始撰寫*/
5. /* 底下使用8051Timer1來定義傳輸率之設定*/
6. TMOD=0x20; /*使用Timer1的模式2,作為傳輸率控制用*/
7. PCON |=0x80; /*傳輸率= Fosc*2^SMOD/[384*(256-TH1)]
8. ,SMOD在PCON的bit-7*/
9. TL1= 256-6; /*如果Fosc=11.0592MHz,則傳輸率=9600*/
10. TH1= 256-6; /*TL0及TH0必須是250,*/
11. TR1=1; /*啟動計時器1*/
12. SCON=0x50; /*串列傳輸採模式1,及可接收*/
13. /*--------底下可以開始使用stdio.h中的函式---------*/
14. printf(“Hi, everybody!”); /*印出Hi, everybody! */
15. }
程式範例1:印出字串
4
作業1:仿照以上工作設計一個程式
印出你的學號與姓名於同一行
• 作業請準時交出
• 作業應包含:
– 題目名稱:
– 需求:
– 需求
分析
定性数据统计分析pdf销售业绩分析模板建筑结构震害分析销售进度分析表京东商城竞争战略分析
:
– 流程圖:
– 程式:程式需加註解
– 執行結果:
– 結論:
– 參考書籍與文件
• 操作過程影音檔
print函式
• 印出一字串在終端機的螢幕上
– printf函式主要的功能是將資料印出在終端機(Terminal)的螢幕
上,印出的格式控制具彈性與簡單。
• 格式如下:
printf(“format string”,- ,
- ,….);
• 格式化字串:
– 必須在雙引號中,例如: “Hi, everybody!”。
– printf 函式的字串中可以加入
• 格式命令(Format Command)
• 跳出順序(Escape Sequence),
• 例如:printf(“總值=%d\n”,sum); /*印出總值=數值sum,同時換行*/
• 其中%d就是指引印出sum數值以十進制格式印在”總值=”後印出sum
值。
• 字串後加上\n
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
示讓游標(Cursor)在印出所有資料之後會移到下一行
的最前端。
5
格式控制
十六進制整數%x
字串%s
字元%c
指數型浮點數%e
浮點數%f
指標值%p
十進制長整數%ld
不帶正負號十進制整數%d
印出順序控制字元
0D游標回頭CR\r
0C換頁FF\f
0B垂直定位VT\v
0A換行LF\n
09水平定位跳8個字元
(tab)
HT\t
08退回一格BS\b
07響聲BEL\a
0空字元NULL\0
ASCII碼功能說明字符控制符
號
6
印出順序控制字元
插入一個ASCII值ooo為8進制的字元\ooo
插入一個ASCII值hhh為16進制的字元\xhhh
5C反斜線\\\
3F問號?\?
2C單引號‘\’
22雙引號“\”
ASCII碼功能說明字符控制符
號
1. #include
2. #include
3. main() /*定義名稱叫做main的函數,沒有傳入/傳回數值*/
4. { /*程式將由此左大括弧後開始撰寫*/
5. /* 底下使用8051Timer1來定義傳輸率之設定*/
6. TMOD=0x20; /*使用Timer1的模式2,作為傳輸率控制用*/
7. PCON |=0x80; /*傳輸率= Fosc*2^SMOD/[384*(256-TH1)]
8. ,SMOD在PCON的bit-7*/
9. TL1= 256-6; /*如果Fosc=11.0592MHz,則傳輸率=9600*/
10. TH1= 256-6; /*TL0及TH0必須是250,*/
11. TR1=1; /*啟動計時器1*/
12. SCON=0x50; /*串列傳輸採模式1,及可接收*/
13. /*--------底下可以開始使用stdio.h中的函式---------*/
14. printf(“Hi, everybody! \n”); /*印出Hi, everybody! */
15. }
程式範例2:印出字串
7
作業2:仿照以上工作設計一個程式
第一行印出你的學號,第二行印出姓名
• 作業請準時交出
• 作業應包含:
– 題目名稱:
– 需求:
– 需求分析:
– 流程圖:
– 程式:程式需加註解
– 執行結果:
– 結論:
– 參考書籍與文件
• 操作過程影音檔
puts()
• 印出一字串在終端機的螢幕上,同時自動換行
• 將一個字串顯示在螢幕上且會自動加上跳脫字元\ n 。
– 例如 :
1. #include
2. #include
3. main(){
4. /* 底下使用8051Timer1來定義傳輸率之設定*/
5. TMOD=0x20; /*使用Timer1的模式2,作為傳輸率控制用*/
6. PCON |=0x80; /*傳輸率= Fosc*2^SMOD/[384*(256-TH1)]*/
7. TL1= 256-6; /*如果Fosc=11.0592MHz,則傳輸率=9600*/
8. TH1= 256-6; /*TL0及TH0必須是250,*/
9. TR1=1; /*啟動計時器1*/
10. SCON=0x50; /*串列傳輸採模式1,及可接收*/
11. /*--------底下可以開始使用stdio.h中的函式---------*/
12. puts(“Hi, everybody!\n”); /*使用puts()函式印出Hi, everybody! */
13. }
8
作業3:仿照以上工作設計一個程式
第一行印出你的學號,第二行印出姓名
• 作業請準時交出
• 作業應包含:
– 題目名稱:
– 需求:
– 需求分析:
– 流程圖:
– 程式:程式需加註解
– 執行結果:
– 結論:
– 參考書籍與文件
• 操作過程影音檔
putchar()
1. 將一個單一個字元顯示在螢幕上 , 後面沒有加入
\n換行,所以它和 printf("%C", 字元 ) 是一樣
的。
2. 有些地方可以使用 puts() 函式或 putchar() 函式
取代 printf() 函式
3. 因為使用printf() 函式可以印出如數字、字元、
字串或特殊格式
• 當字串的尾如需換行,則須加入\n時,如此便何使用
puts()直接取代。
• 而印出單一字元的printf("%C", 字元 )則可用putchar()
取代。
9
程式範例5:印出ASCII碼0x65~0x7F
之字元
1. #include
2. void uartinit(void);
3. void main (void) {
4. char i;
5. for (i = 0x65; i < 0x7F; i++)
6. putchar (i);
7. }
8. void uartinit(void){
9. /* 底下使用8051Timer1來定義傳輸率之設定*/
10. TMOD=0x20; /*使用Timer1的模式2,作為傳輸率控制用*/
11. PCON |=0x80; /*傳輸率= Fosc*2^SMOD/[384*(256-TH1)]
12. ,SMOD在PCON的bit-7*/
13. TL1= 256-6; /*如果Fosc=11.0592MHz,則傳輸率=9600*/
14. TH1= 256-6; /*TL0及TH0必須是250,*/
15. TR1=1; /*啟動計時器1*/
16. SCON=0x50; /*串列傳輸採模式1,及可接收*/
17. }
作業4:印出ASCII碼0x20~0x7F之字
元
• 作業請準時交出
• 作業應包含:
– 題目名稱:
– 需求:
– 需求分析:
– 流程圖:
– 程式:程式需加註解
– 執行結果:
– 結論:
– 參考書籍與文件
• 操作過程影音檔
10
標準輸入 (Input)
• stdio.h函式庫提供了
– scanf()、
– getchar(),
– 及gets()等幾個輸入函式
• 由鍵盤讀進資料。
標準輸入 (Input)
• 為了能得到交談式的輸入 , 大部份你所使用是
scanf() 函式。
• scanf()函式的格式如下:
– scanf( 〈”格式化字串”〉 , 〈變數位址〉 , 〈變數位
址〉 ,...)
– scanf()函式中可以如printf()函式中使用%格式字元,
• 如%d 是指引僅能輸入十進制整數型態、
• %f 是浮點型態、
• %s 是字串 ...等等。
– 然而 , 使用 scanf() 函式時有 一點非常重要 , 那就是跟
隨在格式化字串後的必須是位址而不是數目值。
11
使用scanf()函式之程式範例:
求輸入兩數之和
1. #include
2. #include
3. main(){
4. int a, b;
5. /* 底下使用8051Timer1來定義傳輸率之設定*/
6. TMOD=0x20; /*使用Timer1的模式2,作為傳輸率控制用*/
7. PCON |=0x80; /*傳輸率= Fosc*2^SMOD/[384*(256-TH1)]*/
8. TL1= 256-6; /*如果Fosc=11.0592MHz,則傳輸率=9600*/
9. TH1= 256-6; /*TL0及TH0必須是250,*/
10. TR1=1; /*啟動計時器1*/
11. SCON=0x50; /*串列傳輸採模式1,及可接收*/
12. /*--------底下可以開始使用stdio.h中的函式---------*/
13. while(1){
14. printf(“請輸入一十進制整數值A:”); /*印出輸入指示*/
15. scanf(“%d”, &a); /*輸入一數值,並存入變數a的位址中*/
16. printf(“\n請輸入一十進制整數值B:”); /*印出輸入指示*/
17. scanf(“%d”, &b); /*輸入一數值,並存入變數b的位址中*/
18. printf(“\n %d + %d =%d \n”, a, b, a+b); /*印出結果*/
19. }
20. }
12
作業5:仿照以上工作使用scanf()函式設計一個
程式解歐姆定律,第一行指示輸入電壓
值,第二行輸入電阻值,第三行印出電
流值
• 作業請準時交出
• 作業應包含:
– 題目名稱:
– 需求:
– 需求分析:
– 流程圖:
– 程式:程式需加註解
– 執行結果:
– 結論:
– 參考書籍與文件
• 操作過程影音檔
作業6:仿照以上工作使用scanf()函式設計一個
程式解歐姆定律,第一行指示輸入電壓
值,第二行輸入電流值,第三行印出電
阻值
• 作業請準時交出
• 作業應包含:
– 題目名稱:
– 需求:
– 需求分析:
– 流程圖:
– 程式:程式需加註解
– 執行結果:
– 結論:
– 參考書籍與文件
• 操作過程影音檔
13
作業7:仿照以上工作使用scanf()函式設計一個
程式解歐姆定律,第一行指示輸入電
流值,第二行輸入電阻值,第三行印
出電壓值
• 作業請準時交出
• 作業應包含:
– 題目名稱:
– 需求:
– 需求分析:
– 流程圖:
– 程式:程式需加註解
– 執行結果:
– 結論:
– 參考書籍與文件
• 操作過程影音檔
使用scanf()函式之程式範例:
求輸入你的名字及印出你的名字
1. #include 〈stdio.h〉
2. void uartinit(void);
3. main(){
4. char name[150];
5. uartinit();
6. printf("What is your name:");
7. scanf(" %s ", &name);
8. printf("Hello, %s \ n", name);
9. }
10. void uartinit(void){
11. /* 底下使用8051Timer1來定義傳輸率之設定*/
12. TMOD=0x20; /*使用Timer1的模式2,作為傳輸率控制用*/
13. PCON |=0x80; /*傳輸率= Fosc*2^SMOD/[384*(256-TH1)]
14. ,SMOD在PCON的bit-7*/
15. TL1= 256-6; /*如果Fosc=11.0592MHz,則傳輸率=9600*/
16. TH1= 256-6; /*TL0及TH0必須是250,*/
17. TR1=1; /*啟動計時器1*/
18. SCON=0x50; /*串列傳輸採模式1,及可接收*/
19. }
14
作業8:你發現了什麼問題?
• 提示: 輸入你的全名,看中間有空白鍵,看輸出有
何變化,做成報告
• 報告請準時交出
• 報告應包含:
– 題目名稱:
– 程式:程式需加註解
– 執行結果:
– 結論:
– 你發現了什麼問題?為什麼?如何解決?
– 參考書籍與文件
• 操作過程影音檔
使用 gets() 函式
• gets()函式會讀進按Enter鍵之前的所有資
料 ;讀進的資料不含 Enter ,
• Enter鍵之前資料中若有空白鍵資料會自動
加上,
• 沒有scanf()的問題
15
使用 gets() 函式之程式範例:
求輸入你的名字及印出你的名字
1. #include 〈stdio.h 〉
2. void uartinit(void) ;
3. main() {
4. char name[150];
5. void uartinit(void);
6. printf("What is your name:");
7. gets(name);
8. printf(',Hello, %s \n",name);
9. }
10. void uartinit(void) {
11. /* 底下使用8051Timer1來定義傳輸率之設定*/
12. TMOD=0x20; /*使用Timer1的模式2,作為傳輸率控制用*/
13. PCON |=0x80; /*傳輸率= Fosc*2^SMOD/[384*(256-TH1)]
14. ,SMOD在PCON的bit-7*/
15. TL1= 256-6; /*如果Fosc=11.0592MHz,則傳輸率=9600*/
16. TH1= 256-6; /*TL0及TH0必須是250,*/
17. TR1=1; /*啟動計時器1*/
18. SCON=0x50; /*串列傳輸採模式1,及可接收*/
19. }
作業9:你發現了什麼?
• 提示: 輸入你的全名,看中間有空白鍵,看輸出有
何變化,做成報告
• 報告請準時交出
• 報告應包含:
– 題目名稱:
– 程式:程式需加註解
– 執行結果:
– 結論:
– 你發現了什麼?它解決了什麼問題?為什麼?
– 參考書籍與文件
• 操作過程影音檔
16
getchar()函式
• 它會從鍵盤內讀進一個字元,但字元不會
反應在螢幕上
• scanf() 和 gets()會反應、在螢幕上 。
• getchar()並不需要一個字元參數%s
• 因 getchch()本身是個字元函式 , 它會直接
指定字元。
使用 getchar()函式之程式範例:
求印出輸入字元及其ASCII碼
1. #include
2. #include
3. void uartinit(void);
4. void main(void) {
5. char c;
6. uartinit(); /* init. UART */
7. while ((c = getchar ()) != EOF) { /*取出一字元,同時不為結束碼則進行下行的印出工作*/
8. printf ("character = %c %u %x\n", c, c, c);
9. }
10. }
11. void uartinit(void){
12. /* 底下使用8051Timer1來定義傳輸率之設定*/
13. TMOD=0x20; /*使用Timer1的模式2,作為傳輸率控制用*/
14. PCON |=0x80; /*傳輸率= Fosc*2^SMOD/[384*(256-TH1)]
15. ,SMOD在PCON的bit-7*/
16. TL1= 256-6; /*如果Fosc=11.0592MHz,則傳輸率=9600*/
17. TH1= 256-6; /*TL0及TH0必須是250,*/
18. TR1=1; /*啟動計時器1*/
19. SCON=0x50; /*串列傳輸採模式1,及可接收*/
20. }
17
作業10:仿照以上所學及用getchar()與字元陣列設計一個程式
輸入你的學號到該字元陣列,並且用printf()印出該字元陣列
• 作業請準時交出
• 作業應包含:
– 題目名稱:
– 需求:
– 需求分析:
– 流程圖:
– 程式:程式需加註解
– 執行結果:
– 結論:
– 參考書籍與文件
• 操作過程影音檔
51暫存器函式所提供的IO
• 8位元寬度的並聯IO埠P0、P1、P2、P3
• 16位元計時計數器T0、T1、T2
• 一個串列傳輸埠。
• 各種不同51的暫存器函式庫檔案位置在
c:\keil\C51\INC\內
• 標準51的暫存器函式庫如reg51.h
• 標準52的暫存器函式庫如reg52.h
• 其他51相容的暫存器函式庫...
18
使用51的IO裝置
• 經宣告引用如上內容的函式庫之後,我們
就可以在程式區塊中使用51的IO裝置
• 使用的方式極為簡單
– 如設定一組數值給變數一樣。當輸出時可以撰
寫如下:
• P2=0x18; /*設定P2輸出一組數值0x18*/
• P1=LED; ; /*將LED內容輸出到P2*/….
– 當輸入時則可以撰寫如下:
• a=P2; /*由P2輸入一組數值到變數a*/。
使用51並聯埠輸出範例:
求由P1構成霹靂燈顯示
1. #include
2. void delay(int);
3. void main(void) {
4. unsigned char c;
5. while(1){
6. c=0x080;
7. while (c != 0){
8. P1= ~ c; /*0驅動*/
9. delay(10000);/*呼叫延時功能*/
10. c >>=1;
11. }
12. }
13. }
14. void delay(int i){
15. while (i-- > 0);
16. }
19
作業11:仿照以上工作使用51並列埠設計一個
程式完成向左顯示之霹靂燈,每燈亮一
秒,到最左後再向右顯示到最右邊
• 作業請準時交出
• 作業應包含:
– 題目名稱:
– 需求:
– 需求分析:
– 流程圖:
– 程式:程式需加註解
– 執行結果:
– 結論:
– 參考書籍與文件
• 操作過程影音檔
使用51並聯埠輸入範例:
P1輸入數值,然後求該值之階乘數,並在P2顯示出來
• 本程式將使用遞迴(Recursive)方式完成,在C51
中必須在函式中宣告reentrant才可使用遞迴方式
• 我們可以使用演算法(Algorithm)來取代流程圖來
規劃流程圖
• An algorithm is finite set of precise instructions
for performing a computation or for solving a
problem
20
使用51並聯埠輸入範例:
P1輸入數值,然後求該值之階乘數,並在P2顯示出來
Algorithm:
procedure main()
while (1)
begin
i:=P1
P2:= factorial (i)
end
Procedure factorial (x: integer)
if x<2 then return 1
else return x * factorial( x-1)
1. #include "reg51.h"
2. #include
3. int fac(int) reentrant;
4. main(){
5. int h,i;
6. while (1){
7. i=P1;
8. h=fac(i);
9. P2=h;
10. }
11. return 0;
12. }
13. int fac(int x) reentrant
14. {
15. if (x<2) return 1;
16. return x*fac(x-1);
17. }
作業12:仿照以上工作使用51並列埠設計一個程式完成P1輸
入數值,然後求該值到0的總和,並在P2顯示出來
• 作業請準時交出
• 作業應包含:
– 題目名稱:
– 需求:
– 需求分析:
– 流程圖或演算法:
– 程式:程式需加註解
– 執行結果:
– 結論:
– 參考書籍與文件
• 操作過程影音檔
21