久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6154|回復: 0
打印 上一主題 下一主題
收起左側

單片機原理與應用實驗報告下載,歡迎參考

[復制鏈接]
跳轉到指定樓層
樓主
ID:421903 發表于 2018-11-6 18:23 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式

單片機原理與應用實驗報告

姓名xxx

學號xxxxxxxx

實驗時間5月28日~6月11日

2.2 匯編程序實驗2

一、實驗要求

片內RAM 30H開始的32個單元中分布著隨機的有符號8位二進制數,按從小到大的順序進行排序,排序后的數據仍然保存到30H開始的32個單元中(低地址存放小數據)

  • 實驗過程及結果記錄

步驟:

  • 編寫匯編語言并加上相應注釋(注意擴展名為“*.asm”),將其保存。
  • 運行Keil u Vision2,建立工程“simlab2.uV2,CPUAT89C51,不用包含啟動文件“STARTUP.A51”。
  • 將編寫好的程序加入工程“simlab2.uV2,并設置工程“simlab2.uV2”的屬性,將其晶振頻率設置為12MHz,選擇輸出的可執行文件,仿真方式為“Use Simulator”。
  • 構造(Build)工程“simlab2.uV2”。如果輸入有誤,則進行修改,直至構造正確,生成可執行程序“simlab2.hex”為止。
  • 運行程序,并用存儲器觀察窗口觀察內部RAM30H~4FH單元排序前后的數值。

結果:

由上圖可知,32個數從30H開始由小到大排列

三、實驗源程序


  1. ORG 0000H
  2. AJMP MAIN
  3. ORG 0030H
  4. MAIN:
  5.    MOV R0,#20H         ;R0用于存放數據時計數
  6.    MOV R1,#30H         ;R1指向30H地址單元
  7.    MOV DPTR,#TABLE     ;使DPTR指向表首
  8.    MOV R2,#00H        
  9.    MOV A,R2            ;給偏移地址賦初值,為0
  10. LOOP1:
  11.    MOVC A,@A+DPTR      ;取出表中的數據
  12.    MOV @R1,A           ;將表中的數據存入30H單元
  13.    INC R1              ;R1自增1,指向下一個單元
  14.    INC R2            
  15.    MOV A,R2            ;R2自增1,從而使偏移量增1
  16.    DJNZ R0,LOOP1       ;R0=R0-1,如果R0不為0,則再次從LOOP1處執行,將表中數據存入對應的單元;如果R0=0,則表示表中數據已經全部存入30H~4FH單元中
  17.    MOV R7,#1FH         ;將遍歷次數31送入R7中
  18. LOOP2:
  19.    MOV A,R7           
  20.    MOV R6,A          ;將比較次數寄存器R6的值設定為R7的值
  21.    ADD A,#30H
  22.    MOV R0,A      ;將最大值為位置寄存器R0的值設定為#30H+R7
  23.    MOV R1,#30H         ;將R1指向30H單元
  24.    MOV B,@R1          ;取R1指向的單元的值到最大值寄存器B
  25. LOOP3:
  26.    CLR C              ;將C清零
  27.    INC R1             ;R1自增1        
  28.    MOV A,@R1         ;將R1所指向單元中的值賦給A
  29.    MOV R5,A          ;將A中的值賦給R5,作為備份
  30.    SUBB A,B           ;A=A-B
  31.    JC LOOP4         ;如果存在借位,即A<B,則跳轉至LOOP4
  32.    MOV A,R1
  33.    MOV R0,A          ;如果A>B,將R1中的值賦給R0,使其始終保持最大值
  34.    MOV A,R5          ;恢復A的值
  35.    MOV B,A          ;使最大值寄存器B的值為A中的值
  36. LOOP4:
  37.    DJNZ R6,LOOP3     ;R6=R6-1,如果R6為0,表示這一輪的比較已經完成,否則再次執行LOOP3,繼續進行比較
  38.    MOV A,B            ;如果這一輪比較完成,則將最大值寄存器B的值賦給A
  39.    XCH A,@R1        ;交換A和R1中的值,即將最大值存放到這一輪比較的最后的位置
  40.    MOV @R0,A       ;將A中的值賦給R0所指的單元,以上兩步完成將最大值存到最后一位,最后一位的值存到原本最大值所在的位置
  41.    DJNZ R7,LOOP2    ;判斷外循環是否完成,若未完成跳轉至LOOP2,繼續執行外循環      
  42. TABLE:
  43.    DB 1,3,9,2,17,4,11,6
  44.    DB 5,20,100,64,21,14,79,35
  45.    DB 92,7,91,23,65,16,13,18
  46.    DB 18,73,65,101,27,19,62,69
  47. SJMP $
  48. END
復制代碼

2.3 C語言程序實驗

一、實驗要求

片內RAM 30H開始的32個單元中分布著隨機的有符號8位二進制數,按從小到大的順序進行排序,排序后的數據仍然保存到30H開始的32個單元中(低地址存放小數據)

  • 實驗過程及結果記錄

步驟:

(1)編寫C語言源程序,并加上相應注釋(注意擴展名為“*.c”),將其保存。

(2)運行Keil u Vision2,建立工程“simlab3.uV2”,CPU為AT89C51,包含啟動文件“STARTUP.A51”。

(3)將編寫好的程序加入工程“simlab3.uV2”,并設置工程“simlab3.uV2”的屬性,將其晶振頻率設置為12MHz,選擇輸出的可執行文件,仿真方式為“Use Simulator”。

(4)構造(Build)工程“simlab3.uV2”。如果輸入有誤,則進行修改,直至構造正確,生成可執行程序“simlab3.hex”為止。

(5)運行程序,并用存儲器觀察窗口觀察內部RAM30H~4FH單元排序前后的數值。

結果:

由上圖可知,32個數從30H到4FH由小到大排列

三、實驗源程序


  1. <font color="rgb(0, 0, 0)"><font face="Calibri"><font style="font-size: 14pt">#include <reg51.h>
  2. #include<stdio.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int   //頭文件
  5. uchar data a[32] _at_ 0x30;  //設定數組a的起始地址為30H
  6. uint i _at_ 0x55;
  7. uint j _at_ 0x56;
  8. uint t _at_ 0x57;           //以上三句表示將變量i,j,t分別放入地址55H,56H,57H
  9. void main()
  10. {
  11. char i,j,t;                //定義變量i,j,t
  12. char b[]={1,3,9,2,17,4,11,6,5,20,100,64,21,14,79,35,92,7,91,23,65,16,13,18,18,73,65,101,27,19,62,69};        //定義數組,并對其賦值
  13. for(i=0;i<32;i++)
  14. {a[i]=b[i];                //將數組b中的值賦給數組a,即將要比較的32個數,存放到相應的地址
  15. }
  16. for(i=0;i<32;i++)
  17. {for(j=0;j<31-i;j++)
  18. {if(a[j]>a[j+1])
  19.   {t=a[j];
  20.    a[j]=a[j+1];
  21.    a[j+1]=t;             //先讓a[0]與a[1]比較,然后將較大的數存到a[1]中,接著讓a[1]與a[2]比較,較大的存到a[2]中,以此類推,比較結束,將32個數中最大的存到地址最高位,完成第一輪的比較,相似地,比較其余31個數,將其中最大的放到地址的第二高位
  22. }
  23. }
  24. }
  25. while(1);
  26. }</font></font></font>
復制代碼


3.1基本并行I/O口實驗

  • 實驗要求

當按鍵SW1被按下后,D1~D8輪流點亮,點亮的時間為100ms;當按鍵停下后,停止輪換;再次按下后繼續輪換

  • 實驗過程及結果記錄

步驟:

  • Proteus環境下建立如圖的原理圖,并將其保存為“basicIO_self.DSN”文件。
  • 編寫控制源程序,將其保存為“basicIO_self.asm”。
  • 將源程序添加到U1中,并構造該程序。
  • 執行仿真過程,觀察的D1~D8的指示,查看程序功能是否正確。
  • 修改延時程序延時參數,重新執行該程序。

結果:

三、實驗源程序


  1. ORG 0000H
  2. SJMP MAIN
  3. ORG 0030H
  4. MAIN:
  5. MOV SP,#60H        ;使SP指向地址單元60H
  6. MOV P2,#0FFH       ;將P2口所有位設置為1,使P2口所接發光二極管全部熄滅
  7. MOV 20H,#0FEH      ;使顯示緩沖單元的值為11111110
  8. LOOP1:
  9. MOV A,P1           ;將P1的值存到寄存器A中
  10. RRC A              ;A的帶進位循環右移,即將A的最低位放入進位標志位中,標志位中的值放入A的最高位,實現查看P1.0位的功能
  11. JC LOOP1             ;如果進位不為0,則跳轉至LOOP1
  12. MOV P2,20H         ;如果進位不為0,則將顯示緩沖單元20H中的值送給P2
  13. LOOP2:MOV R7,#200   ;令R7中的值為200
  14. LOOP3:MOV R6,#250  ;令R6中的值為250
  15. DJNZ R6,[        DISCUZ_CODE_9        ]nbsp;           ;R6=R6-1,如果R6不為0,則執行$(原地踏步),如果為0,則順序執行,以上兩步維持時間為250*2*1us+1us
  16. DJNZ R7,LOOP3      ;R7=R7-1,如果R7不為0,則執行LOOP3,否則順序執行,以上四步一共維持時間為(1us+250*2*1us+1us+2us)*200,約為100ms
  17. MOV A,20H          ;將顯示緩沖單元中的值存到寄存器A中
  18. RL A                ;將A進行循環左移,即實現顯示緩沖單元的值循環左移1位,
  19. MOV 20H,A          ;將A中的值再送回至顯示緩沖單元中
  20. JMP LOOP1           ;無條件跳轉至LOOP1
  21. END
復制代碼

3.2 擴展并行I/O口實驗

一、實驗要求

仿真實現交通信號燈控制功能。控制順序如下:南北綠燈亮,同時東西紅燈亮10s;南北黃燈亮,同時東西紅燈亮2s;南北紅燈亮,同時東西綠燈亮10s;東西黃燈亮,同時南北紅燈亮2s;重復上述四種狀態。

  • 實驗過程及結果記錄

步驟:

(1)在Proteus環境下建立如圖的原理圖,并將其保存為“expandIO_self.DSN”文件。

(2)編寫控制源程序,將其保存為“expandIO_self.asm”。

(3)將源程序添加到U1中,并構造該程序。

(4)執行仿真過程,觀察各個方向上的交通信號燈指示,查看程序功能是否正確。

結果:

三、實驗源程序


  1. <font style="font-size: 14pt">ORG 0000H
  2. SJMP MAIN
  3. ORG 0030H
  4. MAIN:
  5. MOV SP,#60H ;讓SP指向地址單元60H
  6. MOV P0,#0FFH;令P0為11111111
  7. MOV P3,#40H;令P3為01000000
  8. MOV P2,#03H;令P2為00000011,以上三步使兩個74LS373的輸出端口所有位均為1,使所有發光二極管全部熄滅
  9. STAT1:
  10. MOV P3,#00H ; 令P3為00000000   
  11. MOV P2,#02H ;   令P2為0000010,使U4工作,U5不工作
  12. MOV P0,#0F3H;  令P0為11110011 ,使東西紅燈亮  
  13. MOV P2,#01H ; 令P1為00000001 ,使U4不工作,U5工作
  14. MOV P0,#0CH ;  令P0為00001100 ,使南北綠燈亮  
  15. MOV P2,#03H ;  令P2為00000011   
  16. MOV P3,#40H ; 令P3為01000000 ,以上兩步實現所有的發光二極管均熄滅 的功能 ,變為初始狀態
  17. MOV R4,#10  ;  令R4的值為10     
  18. DELAY1:MOV R7,#10;令R7的值為10
  19. LOOP11:MOV R6,#200;令R6的值為200
  20. LOOP12:MOV R5,#250;令R5的值為250
  21. DJNZ R5,$;R5=R5-1,如果R5不為0,則執行$即原地踏步,否則執行下面的程序
  22. DJNZ R6,LOOP12;R6=R6-1,如果R6不為0,則執行LOOP12,否則執行下面的程序
  23. DJNZ R7,LOOP11;R7=R7-1,如果R7不為0,則執行LOOP11,否則執行下面的程序
  24. DJNZ R4,DELAY1;R4=R4-1,如果R4不為0,則執行DELAY1,否則執行下面的程序,以上八步完成延時,(((1+250*2+2)*200+2)*10+2)*10,大約為10s
  25. STAT2:
  26. MOV P3,#00H; 令P3為00000000
  27. MOV P2,#02H;令P2為0000010,使U4工作,U5不工作
  28. MOV P0,#0C3H;令P0為11000011 ,使東西紅燈亮 ,南北黃燈亮
  29. MOV P2,#01H;令P1為00000001 ,使U4不工作,U5工作
  30. MOV P0,#0FH;令P0為00001111 ,使東西南北綠燈滅
  31. MOV P2,#03H;令P2為00000011
  32. MOV P3,#40H;令P3為01000000 ,以上兩步實現所有的發光二極管均熄滅 的功能 ,變為初始狀態
  33. MOV R4,#2; 令R4的值為2
  34. DELAY2:MOV R7,#10;令R7的值為10
  35. LOOP21:MOV R6,#200;令R6的值為200
  36. LOOP22:MOV R5,#250;令R5的值為250
  37. DJNZ R5,$;R5=R5-1,如果R5不為0,則執行$即原地踏步,否則執行下面的程序
  38. DJNZ R6,LOOP22;R6=R6-1,如果R6不為0,則執行LOOP22,否則執行下面的程序
  39. DJNZ R7,LOOP21;R7=R7-1,如果R7不為0,則執行LOOP21,否則執行下面的程序
  40. DJNZ R4,DELAY2;R4=R4-1,如果R4不為0,則執行DELAY2,否則執行下面的程序,以上八步完成延時,(((1+250*2+2)*200+2)*10+2)*2,大約為2s
  41. STAT3:
  42. MOV P3,#00H;令P3為00000000
  43. MOV P2,#02H;令P2為0000010,使U4工作,U5不工作
  44. MOV P0,#0FCH;令P0為11111100 ,使南北紅燈亮
  45. MOV P2,#01H;令P1為00000001 ,使U4不工作,U5工作
  46. MOV P0,#03H;令P0為00000011 ,使東西綠燈亮
  47. MOV P2,#03H;令P2為00000011
  48. MOV P3,#40H;令P3為01000000 ,以上兩步實現所有的發光二極管均熄滅 的功能 ,變為初始狀態
  49. MOV R4,#10;令R4的值為10
  50. DELAY3:MOV R7,#10;令R7的值為10
  51. LOOP31:MOV R6,#200;令R6的值為200
  52. LOOP32:MOV R5,#250;令R5的值為250
  53. DJNZ R5,$;R5=R5-1,如果R5不為0,則執行$即原地踏步,否則執行下面的程序
  54. DJNZ R6,LOOP32;R6=R6-1,如果R6不為0,則執行LOOP32,否則執行下面的程序
  55. DJNZ R7,LOOP31;R7=R7-1,如果R7不為0,則執行LOOP31,否則執行下面的程序
  56. DJNZ R4,DELAY3;R4=R4-1,如果R4不為0,則執行DELAY3,否則執行下面的程序,以上八步完成延時,(((1+250*2+2)*200+2)*10+2)*10,大約為10s
  57. STAT4:
  58. MOV P3,#00H;令P3為00000000
  59. MOV P2,#02H;令P2為0000010,使U4工作,U5不工作
  60. MOV P0,#3CH;令P0為00111100 ,使東西黃燈亮,南北紅燈亮
  61. MOV P2,#01H;令P1為00000001 ,使U4不工作,U5工作
  62. MOV P0,#0FH;令P0為00001111 ,使東西綠燈滅
  63. MOV P2,#03H;令P2為00000011
  64. MOV P3,#40H;令P3為01000000 ,以上兩步實現所有的發光二極管均熄滅 的功能 ,變為初始狀態
  65. MOV R4,#2;令R4的值為2
  66. DELAY4:MOV R7,#10;令R7的值為10
  67. LOOP41:MOV R6,#200;令R6的值為200
  68. LOOP42:MOV R5,#250;令R5的值為250
  69. DJNZ R5,$;R5=R5-1,如果R5不為0,則執行$即原地踏步,否則執行下面的程序
  70. DJNZ R6,LOOP42;R6=R6-1,如果R6不為0,則執行LOOP42,否則執行下面的程序
  71. DJNZ R7,LOOP41;R7=R7-1,如果R7不為0,則執行LOOP41,否則執行下面的程序
  72. DJNZ R4,DELAY4;R4=R4-1,如果R4不為0,則執行DELAY4,否則執行下面的程序,以上八步完成延時,(((1+250*2+2)*200+2)*10+2)*2,大約為2s
  73. JMP STAT1;無條件跳轉至STAT1
  74. END</font>
復制代碼


3.3靜態LED顯示實驗

  • 實驗要求

7SEG2為十位顯示數碼管,7SEG1為個位顯示數碼管,KEY_LOAD為“倒計時初值”按鈕,KEY_START為“倒計時啟動”按鈕。要實現的功能:當KEY_LOAD按鈕被按下時,加載倒計時初值(如10s);當按下KEY_START按鈕時,開始倒計時,每過1s,計時減1,直到減到“00”為止。減到“00”時,時P3.0引腳上的LED按10Hz頻率閃爍,直到再次按下KEY_LOAD按鈕,才重新加載初值,并熄滅LED。再次按下KEY_START按鈕又一次開始倒計時,如此反復。

  • 實驗過程及結果記錄

步驟:

(1)在Proteus環境下建立如圖的原理圖,并將其保存為“staticLED_self.DSN”文件。

(2)編寫控制源程序,將其保存為“staticLED_self.asm”。

(3)將源程序添加到U1中,并構造該程序。

(4)執行仿真過程,觀察秒表程序功能是否正確。

結果:

(1)按下KEY_LOAD加載倒計時初值。

  • 再按下KEY_START開始倒計時

三、實驗源程序


  1. <font style="font-size: 14pt">ORG 0000H
  2. AJMP MAIN
  3. ORG 0030H
  4. MAIN:
  5. MOV SP,#60H; 堆棧初始化
  6. MOV R0,#0    ;將0賦給R0,即表示初始值的個位  
  7. MOV R1,#1; 將1賦給R1,即表示初始值的十位  
  8. SETB P3.0; 關掉 LED1
  9. CLR F0 ;對標志位清零
  10. LOOP:
  11. JB P1.1,LOOP2; 如果 P1.1=1, 跳轉到 LOOP2 ,
  12. LOOP1:
  13. CLR F0 ;對標志位清零
  14. MOV 30H,R0 ;將個位放在地址單元30H中  
  15. MOV 31H,R1; 將十位放在地址單元31H中,以上兩步實現裝載初值的功能  
  16. SETB P3.0; 關閉 LED1   
  17. LCALL DISPLAY; 顯示
  18. LOOP2:   
  19. JB P1.0,LOOP; 如果 P1.0=1 ,跳回 LOOP ,否則繼續執行
  20. LOOP3:   
  21. LCALL DISPLAY; 刷新顯示,顯示就是將數字呈現在數碼管上  
  22. LCALL DELAY1S; 延時 1s   
  23. LCALL ADJUST2; 調整計時器寄存器
  24. JB F0,LOOP4 ;計時器寄存器如果為1,則跳轉至LOOP4
  25. LJMP LOOP3 ;否則長跳轉至LOOP3
  26. LOOP4:    ;LED閃爍子程序
  27. CLR P3.0 ;將P3.0清零,即LED 亮
  28. LCALL DELAY100MS;調用子程序DELAY100MS
  29. SETB P3.0; 關掉LED
  30. LCALL DELAY100MS;調用子程序DELAY100MS
  31. JB P1.1,LOOP4;如果P1.1為1,則跳轉至LOOP4
  32. LJMP LOOP1      
  33. DISPLAY:     ; 顯示子程序
  34. MOV A,30H ;將個位送至A中
  35. MOV DPTR,#TABLE
  36. MOVC A,@A+DPTR ;通過查表獲得對應的數據
  37. MOV DPTR,#0FE00H ;將其數據送到U2的鎖存地址中
  38. MOVX @DPTR,A ;把A的內容送到DPTR所指的外部地址
  39. MOV A,31H
  40. MOV DPTR,#TABLE
  41. MOVC A,@A+DPTR
  42. MOV DPTR,#0FD00H
  43. MOVX @DPTR,A ;同上,將對應數據送到U3的鎖存地址中
  44. RET
  45. ADJUST2:
  46. DEC 30H ;將地址單元30H中的值自減1
  47. MOV A,30H ;將地址單元30H中的值送入寄存器A中
  48. CJNE A,#-1,GOTORET ;如果A中的值不為-1,則跳轉至GOTORET,即返回主程序
  49. MOV 30H,#9 ;將9送入地址單元30H中
  50. DEC 31H ;將地址單元31H中的值自減1
  51. MOV A,31H ;將地址單元31H中的值送入寄存器A中
  52. CJNE A,#-1,GOTORET ;如果A中的值不為-1,則跳轉至GOTORET,即返回主程序
  53. SETB F0; 將用戶標志位置1
  54. RET
  55. GOTORET:
  56. RET
  57. DELAY1S:MOV R7,#10
  58. DL2:MOV R6,#200
  59. DL1:MOV R5,#250
  60. DJNZ R5,$
  61. DJNZ R6,DL1
  62. DJNZ R7,DL2 ;實現延時,延時時間為((1+2*250+2)*200+2)*10,大約為1s
  63. RET
  64. DELAY100MS:MOV R7,#200
  65. DL:MOV R6,#250
  66. DJNZ R6,$
  67. DJNZ R7,DL;實現延時,延時時間為((1+250*2)+2)*200,大約為0.1s,即使P3.0引腳上的LED按10Hz頻率閃爍
  68. RET
  69. TABLE: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H   
  70. END</font>
復制代碼


3.4矩陣鍵盤掃描實驗

  • 實驗要求

D1~D8八個發光二極管構成彩色旋燈,D9~D13為擋位指示燈,1擋旋轉速度最慢(周期為1s,D13亮),2擋較快(周期為0.8s,D12亮),3擋更快(周期為0.6s,D11亮),4擋較快(周期為0.4s,D10亮)5擋較快(周期為0.2s,D9亮)。按鍵KEY_0~KEY1用于設定旋轉方向為順時針或者逆時針旋轉,KEY_2~KEY_3用于加快或者減慢旋轉速度。

  • 實驗過程及結果記錄

步驟:

(1)在Proteus環境下建立如圖的原理圖,并將其保存為“keyscan_self.DSN”文件。

(2)編寫控制源程序,將其保存為“keyscan_self.asm”。

(3)將源程序添加到U1中,并構造該程序。

(4)執行仿真過程,觀察程序功能是否正確。

結果:

按下按鍵KEY_0時,D1~D8順時針旋轉,按下按鍵KEY1時,D1~D8逆時針旋轉,按下按鍵KEY_2或KEY_3,分別是加速與減速。

三、實驗源程序


  1. <font style="font-size: 14pt">ORG 0000H
  2. AJMP MAIN
  3. ORG 0030H
  4. MAIN:
  5. MOV SP,#60H;使SP指向地址單元60H
  6. MOV P0,#0FFH;使P0為11111111,即所有的彩色旋轉燈都不亮
  7. MOV P1,#0FFH;使P1為11111111,即所有的擋位燈都不亮
  8. MOV R7,#10;令R7的值為10
  9. MOV R4,#0EFH;令R4的值為0EFH
  10. LCALL LOOP;調用子程序SCAN
  11. JMP MAIN;無條件跳轉至MAIN
  12. BUTTON0:
  13. MOV 30H,#0H;將0放入地址單元30H
  14. MOV P1,#0FEH;令P1為11111110,即讓D1亮
  15. JMP ZHUAN1;無條件跳轉至ZHUAN1,來實現彩色旋轉燈的順時針旋轉
  16. BUTTON1:
  17. MOV 30H,#1H;將1放入地址單元30H
  18. MOV P1,#0FEH;令P1為11111110,即讓D1亮
  19. JMP ZHUAN2;無條件跳轉至ZHUAN2,來實現彩色旋轉燈的逆時針旋轉
  20. BUTTON2:
  21. DEC R7;R7自減1
  22. DEC R7;R7自減1
  23. MOV A,R4;將R4的值存到寄存器A中
  24. RR A;將A中的值進行不帶進位的循環右移
  25. MOV R4,A;將A中的值送回R4中
  26. MOV A,30H;將地址單元30H中的值賦給A
  27. JZ ZHUAN1;如果ZF=1(即A中的值為0),則跳轉至ZHUAN1
  28. JMP ZHUAN2;否則跳轉至ZHUAN2
  29. BUTTON3:
  30. INC R7;R7自增1
  31. INC R7;R7自增1
  32. MOV A,R4;將R4中的值存到A中
  33. RL A;將A中的值進行不帶進位的循環左移
  34. MOV R4,A;將A中的值送回至R4中
  35. MOV A,30H;將地址單元30H中的值存到A中
  36. JZ ZHUAN1;如果ZF=1(即A中的值為0),則跳轉至ZHUAN1
  37. JMP ZHUAN2;否則跳轉至ZHUAN1
  38. ZHUAN1:
  39. MOV P0,R4;將R4中的值送到P0,用來變換擋位指示燈
  40. LCALL DLS;長調用DLS
  41. MOV A,P1;將P1中的值存到A中
  42. RL A;將A進行不帶進位的循環左移
  43. MOV P1,A;將A中的值送回至P1中
  44. LCALL SCAN;長調用子程序SCAN
  45. JMP ZHUAN1;無條件跳轉至ZHUAN1
  46. ZHUAN2:
  47. MOV P0,R4;將R4中的值送到P0,用來變換擋位指示燈
  48. LCALL DLS;長調用DLS
  49. MOV A,P1;將P1中的值存到A中
  50. RR A;將A進行不帶進位的循環左移
  51. MOV P1,A;將A中的值送回至P1中
  52. LCALL LOOP;長調用子程序SCAN
  53. JMP ZHUAN2;無條件跳轉至ZHUAN2
  54. DLS:
  55. MOV A,R7;將R7中的值存到寄存器A中
  56. DL2:MOV R6,#200;令R6的值為200
  57. DL1:MOV R5,#250;令R5的值為250
  58. DL0:
  59. DJNZ R5,DL0;R5=R5-1,如果R5不為0,則跳轉至DL0,否則順序執行
  60. DJNZ R6,DL1;R6=R6-1,如果R6不為0,則跳轉至DL1,否則順序執行
  61. DJNZ R7,DL2;R7=R7-1,如果R7不為0,則跳轉至DL2,否則順序執行,實現延時,延時時間為((1+250*2+2)*200+2)*R7
  62. MOV R7,A;將A中的值送回至R7
  63. RET;
  64. LOOP:
  65. MOV P3,#030H;令P3為00110000,使開關閉合時能實現對應的功能
  66. JNB P3.4,NEXT1;如果P3.4為低電平(KEY0或KEY2閉合),則跳轉至NEXT1,否則順序執行
  67. JNB P3.5,NEXT2;如果P3.5為低電平(KEY1或KEY3閉合),則跳轉至NEXT2,否則順序執行
  68. JMP TORET;無條件跳轉至TORET,即返回源程序
  69. NEXT1:
  70. MOV P3,#3H;令P3為00000011
  71. JNB P3.0,BUTTON0;如果P3.0為低電平(KEY0閉合),則跳轉至BUTTON0,否則順序執行
  72. JNB P3.1,BUTTON2;如果P3.1為低電平(KEY2閉合),則跳轉至BUTTON2,否則順序執行
  73. JMP TORET;無條件跳轉至TORET,即返回源程序
  74. NEXT2:
  75. MOV P3,#3H;令P3為00000011
  76. JNB P3.0,BUTTON1;如果P3.0為低電平(KEY1閉合),則跳轉至BUTTON1,否則順序執行
  77. JNB P3.1,BUTTON3;如果P3.1為低電平(KEY3閉合),則跳轉至BUTTON3,否則順序執行
  78. TORET:
  79. RET
  80. END</font>
復制代碼


3.7 LCD 1602顯示實驗

一、實驗要求

利用LCD 1602和16個按鍵實現簡單的十進制的加減乘除四則混合運算。其中按鍵KEY_0~KEY_9分別代表數字0~9;按鍵KEY_10~KEY_13分別代表運算符“+”“-”“*”“/”;按鍵KEY15代表“=”;按鍵KEY_14代表清楚命令,以便進行下一次的輸入和計算。不管什么時候按下“清除”按鍵,計算過程均將停止,兩個輸入變量都將清0,屏幕將清屏。LCD 1602的第一行用于顯示所輸入的兩個計算數以及計算符,第二行用于顯示計算結果。結果允許為負數,但輸入的兩個輸入數都必須是雙字節正整數范圍內的數,即0~32767。除數必須保證不為0,否則將報錯。在有余數除法中,必須能同時顯示商與余數。

  • 實驗過程及結果記錄

步驟:

(1)在Proteus環境下建立如圖的原理圖,并將其保存為“LCD1602_self.DSN”文件。

(2)編寫控制源程序,將其保存為“LCD1602_self.c”。

(3)運行Keil u Vision2,建立工程“LCD1602_self.uV2”,CPU為AT89C51,包含啟動文件“STARTUP.A51”。

(4)將編寫好的程序加入工程“LCD1602_self.uV2”,并設置工程“LCD1602.uV2”的屬性,將其晶振頻率設置為12MHz,選擇輸出的可執行文件,仿真方式為“選擇硬仿真”,并選擇其中的“PROTEUS VSM MONITOR 51 DEIVER”仿真器。

(5)構造(Build)工程“LCD1602_self.uV2”。如果輸入有誤,則進行修改,直至構造正確,生成可執行程序“LCD1602_self.hex”為止。

  • AT89C51設置可執行程序“LCD1602_self.hex”。
  • 運行程序,單擊按鍵輸入數據與運算符,計算,觀察計算結果,并驗證其是否正確。
  • 輸入過程中,按“清除”按鍵觀察結果,重新輸入數據計算并驗證。

結果:

(1)加法

(2)減法

(3)乘法

(4)除法

(5)報錯

三、實驗源程序


  1. <font style="font-size: 14pt">#include<reg51.h>  
  2. #define uint unsigned int
  3. #define uchar unsigned char

  4. sbit lcden=P1^5;//使能信號  
  5. sbit rs=P1^7;//數據命令選擇
  6. sbit rw=P1^6;//讀寫選擇   
  7. sbit busy=P2^7;

  8. char i,j,temp,num;
  9. long a,b,c,d;   
  10. float a_c,b_c;
  11. uchar flag,fuhao;//flag

  12. uchar code table[]={
  13. 0,1,2,3,
  14. 4,5,6,7,
  15. 8,9,0,0,
  16. 0,0,0,0};
  17. uchar code table1[]={
  18. 0,1,2,3,
  19. 4,5,6,7,
  20. 8,9,0x2b-0x30,0x2d-0x30,
  21. 0x2a-0x30,0x2f-0x30,0x01-0x30,0x3d-0x30};//按鍵對應的符號
  22. uchar code table2[]="!rorrE";

  23. void delay(uchar z) // 延遲函數
  24. {
  25.               uchar i,t;
  26.               for(i=0;i<z;i++)
  27.                   for(t=0;t<120;t++);
  28. }

  29. void check() // 判斷忙或空閑
  30. {
  31.               do
  32.               {
  33.                   P2=0xFF;
  34.                   rs=0;     //指令     
  35.                   rw=1;     //讀   
  36.                   lcden=0;     //禁止讀寫n   
  37.                   delay(1); //等待,液晶顯示器處理數據     
  38.                   lcden=1;     //允許讀寫  
  39.               }
  40.               while(busy==1); //判斷是否為空閑,1為忙,0為空閑
  41. }

  42. void write_com(uchar com) // 寫指令函數   
  43. {
  44.               P2=com;    //com指令付給P0口   
  45.               rs=0;
  46.               rw=0;
  47.               lcden=0;
  48.               check();
  49.               lcden=1;
  50. }

  51. void write_date(uchar date) // 寫數據函數     
  52. {
  53.     P2=date;
  54.               rs=1;
  55.               rw=0;
  56.               lcden=0;
  57.               check();
  58.               lcden=1;
  59. }

  60. void init() //初始化   
  61. {
  62.     num=-1;
  63.               lcden=1; //使能信號為高電平  
  64.               write_com(0x38); //8位,2行  
  65.               write_com(0x0c); //顯示開,光標關,不閃爍*/   
  66.               write_com(0x06); //增量方式不移位      
  67.               write_com(0x80); //檢測忙信號      
  68.               write_com(0x01); //清屏指令
  69.               i=0;
  70.               j=0;
  71.               a=0;     //第一個參與運算的數        
  72.               b=0;     //第二個參與運算的數      
  73.               c=0;
  74.     d=0;
  75.               flag=0; //flag表示是否有符號鍵按下,  
  76.               fuhao=0; // fuhao表征按下的是哪個符號   
  77. }

  78. void keyscan() // 鍵盤掃描程序   
  79. {
  80.               P3=0xfe;
  81.               if(P3!=0xfe)
  82.               {
  83.                                delay(20);
  84.                                if(P3!=0xfe)
  85.                                {
  86.                                 temp=P3&0xf0;
  87.                                 switch(temp)
  88.                                 {
  89.                                               case 0xe0:num=0;
  90.                                                  break;
  91.                                                case 0xd0:num=1;
  92.                                                  break;
  93.                                                case 0xb0:num=2;
  94.                                                 break;
  95.                                                 case 0x70:num=3;
  96.                                                 break;
  97.                                 }
  98.                                }
  99.                                while(P3!=0xfe);
  100.                                if(flag==0)//沒有按過符號鍵
  101.                                {
  102.                                              a=a*10+table[num];
  103.                             }
  104.                             else//如果按過符號鍵
  105.                             {
  106.                                           b=b*10+table[num];
  107.                             }
  108.                                           i=table1[num];
  109.                                           write_date(0x30+i);//寫入按鍵對應的 符號  
  110.               }

  111.               P3=0xfd;
  112.               if(P3!=0xfd)
  113.               {
  114.                  delay(5);
  115.                  if(P3!=0xfd)
  116.                  {
  117.                   temp=P3&0xf0;
  118.                   switch(temp)
  119.                   {
  120.                    case 0xe0:num=4;
  121.                        break;
  122.                   
  123.                    case 0xd0:num=5;
  124.                        break;
  125.                   
  126.                    case 0xb0:num=6;
  127.                        break;
  128.                   
  129.                    case 0x70:num=7;     
  130.                        break;
  131.                   }
  132.                  }
  133.                  while(P3!=0xfd);
  134.                  if(flag==0)//沒有按過符號鍵
  135.                   {
  136.                    a=a*10+table[num];
  137.                   }
  138.                   else//如果按過符號鍵
  139.                   {
  140.                    b=b*10+table[num];
  141.                   }
  142.                  i=table1[num];
  143.                  write_date(0x30+i);
  144.               }
  145.             
  146.               P3=0xfb;
  147.               if(P3!=0xfb)
  148.               {
  149.                  delay(5);
  150.                  if(P3!=0xfb)
  151.                  {
  152.                   temp=P3&0xf0;
  153.                   switch(temp)
  154.                   {
  155.                    case 0xe0:num=8;
  156.                        break;
  157.                   
  158.                    case 0xd0:num=9;
  159.                        break;
  160.                   
  161.                    case 0xb0:num=10;
  162.                        break;
  163.                   
  164.                    case 0x70:num=11;
  165.                        break;
  166.                   }
  167.                  }
  168.                  while(P3!=0xfb);
  169.                  if(num==8||num==9)//如果按下的是'8','9'
  170.                  {
  171.                     if(flag==0)//沒有按過符號鍵
  172.                   {
  173.                    a=a*10+table[num];
  174.                   }
  175.                   else//如果按過符號鍵
  176.                   {
  177.                    b=b*10+table[num];
  178.                   }
  179.                  }
  180.                  else if(num==10)//如果按下的是'+'
  181.                  {
  182.                   flag=1;
  183.                   fuhao=1;//1表示加號已按     
  184.                  }
  185.                  else if(num==11)//如果按下的是'-'
  186.                  {
  187.                   flag=1;
  188.                   fuhao=2;//2表示減號已按6
  189.                  }
  190.                  i=table1[num];
  191.                  write_date(0x30+i);
  192.               }
  193.             
  194.               P3=0xf7;
  195.               if(P3!=0xf7)
  196.               {
  197.                  delay(5);
  198.                  if(P3!=0xf7)
  199.                  {
  200.                   temp=P3&0xf0;
  201.                   switch(temp)
  202.                   {
  203.                    case 0xe0:num=12;
  204.                        break;
  205.                   
  206.                    case 0xd0:num=13;
  207.                        break;
  208.                   
  209.                    case 0xb0:num=14;
  210.                        break;
  211.                   
  212.                    case 0x70:num=15;
  213.                        break;
  214.                   }
  215.                  }
  216.                  while(P3!=0xf7);
  217.                  switch(num)
  218.                  {
  219.                   case 12:{write_date(0x30+table1[num]); flag=1;fuhao=3;}
  220.                    break;
  221.                   case 13:{write_date(0x30+table1[num]); flag=1;fuhao=4;}              
  222.                    break;
  223.                   case 14:{write_com(0x01);i=0;j=0;a=0;b=0;c=0;d=0;flag=0;fuhao=0;}//按下的是"清零"   
  224.                    break;
  225.                   case 15:{
  226.                                              j=1;

  227.                          if(fuhao==1){write_com(0x80+0x4f);//按下等于鍵,光標前進至第二行最后一個顯示處        
  228.                          write_com(0x04);     //寫入數據后地址加1 ,從右向左寫入數據      
  229.                          c=a+b;
  230.                          while(c!=0)
  231.                          {
  232.                            write_date(0x30+c%10);
  233.                            c=c/10;
  234.                          }
  235.                          write_date(0x3d);     //再寫"="
  236.                          a=0;b=0;flag=0;fuhao=0;
  237.                          }

  238.                     else if(fuhao==2){write_com(0x80+0x4f);//光標前進至第二行最后一個顯示處      
  239.                           write_com(0x04);     //設置從后住前寫數據,每寫完一個數據,光標后退一格)
  240.                          if(a-b>0)
  241.                            c=a-b;
  242.                          else
  243.                            c=b-a;
  244.                          while(c!=0)
  245.                          {
  246.                            write_date(0x30+c%10);
  247.                            c=c/10;
  248.                          }
  249.                          if(a-b<0)
  250.                          write_date(0x2d);    //寫’-‘
  251.                          write_date(0x3d);     //再寫"="         
  252.                          a=0;b=0;flag=0;fuhao=0;
  253.                         }

  254.                     else if(fuhao==3)
  255.                               {
  256.                                                         write_com(0x80+0x4f);
  257.                           write_com(0x04);
  258.                           c=a*b;
  259.                           while(c!=0)
  260.                           {
  261.                                          write_date(0x30+c%10);
  262.                                          c=c/10;
  263.                           }
  264.                            write_date(0x3d);   
  265.                                       a=0;b=0;flag=0;fuhao=0;
  266.                            }

  267.                     else if(fuhao==4)
  268.                                                {
  269.                                                         write_com(0x80+0x4f);
  270.                           write_com(0x04);
  271.                                                         if(b==0)
  272.                                                         {
  273.                                                                       i=0;
  274.                                                                       while(table2[i]!='\0')
  275.                                                                       {
  276.                                                                                     write_date(table2[i]);
  277.                                                                                     i++;
  278.                                                                       }//若除數為0,輸出Error!
  279.                                                                       a=0;b=0;flag=0;fuhao=0;
  280.                                                         }
  281.                                                         else if((a%b==0)&&(b!=0))
  282.                                                         {
  283.                                         c=a/b;
  284.                                         while(c!=0)
  285.                                          {
  286.                                                          write_date(0x30+c%10);
  287.                                                         c=c/10;
  288.                                          }
  289.                                                                       if(a/b<=0)
  290.                                          write_date(0x30);
  291.                                         write_date(0x3d);                             
  292.                                         a=0;b=0;flag=0;fuhao=0;
  293.                                                         }
  294.                                                         else if((a%b!=0)&&(b!=0))
  295.                                                         {
  296.                                                                       d=a%b;
  297.                                                             while(d!=0)
  298.                                          {
  299.                                                          write_date(0x30+d%10);
  300.                                                         d=d/10;
  301.                                          }//若不能整除,輸出余數  
  302.                                            write_date(0x2e);
  303.                                                                       write_date(0x2e);
  304.                                                                       write_date(0x2e);//輸出“...“
  305.                                                                       c=a/b;//輸出整除結果
  306.                                                             while(c!=0)
  307.                                          {
  308.                                                          write_date(0x30+c%10);
  309.                                                         c=c/10;
  310.                                          }
  311.                                                                       if(a/b<=0)
  312.                                         write_date(0x30);
  313.                                         write_date(0x3d);                             
  314.                                         a=0;b=0;flag=0;fuhao=0;
  315.                                                         }
  316.                        }
  317.                     }
  318.                    break;
  319.                  }
  320.               }
  321. }

  322. main()
  323. {
  324.               init();//初始化
  325.               while(1)
  326.               {
  327.                                keyscan();//鍵盤掃描
  328.               }
  329. }</font>
復制代碼



3.8 ADC0808/9信號采集實驗

一、實驗要求

利用LCD1602和AD0808實現簡單的交流信號過零檢測與頻率分析。要求信號幅度變化時,比影響檢測結果。頻率檢測的結果通過LCD1602的第1行顯示出來,信號過零時,能夠通過P2.6輸出一個脈沖寬度為5us的脈沖信號。電位器RV1用于改變交流信號的幅值。交流信號通過單擊窗口左側繪圖工具窗口中的“虛擬信號發生器”按鈕,然后在器件窗口中選擇正弦信號(SINE)實現。

二、實驗過程及結果記錄

步驟:

(1)在Proteus環境下建立如圖的原理圖,并將其保存為“ADC0808_self.DSN”文件。

(2)編寫控制源程序,將其保存為“ADC0808_self.c”。

(3)運行Keil u Vision2,建立工程“ADC0808_self.uV2”,CPU為AT89C51,包含啟動文件“STARTUP.A51”。

(4)將編寫好的程序加入工程“ADC0808_self.uV2”,并設置工程“ADC0808.uV2”的屬性,將其晶振頻率設置為12MHz,選擇輸出的可執行文件,仿真方式為“選擇硬仿真”,并選擇其中的“PROTEUS VSM MONITOR 51 DEIVER”仿真器。

(5)構造(Build)工程“ADC0808_self.uV2”。如果輸入有誤,則進行修改,直至構造正確,生成可執行程序“ADC0808_self.hex”為止。

(6)為AT89C51設置可執行程序“ADC0808_self.hex”。

(7)運行程序,觀察計算結果,并驗證其是否正確。

(8)改變RV1的抽頭位置,從而改變輸入信號的幅值,觀察計算結果是否正確。

(9)更改信號發射器的頻率,再次驗證其功能是否正確。

結果:

三、實驗源程序

  1. <font style="font-size: 16pt"><b>#include<reg51.h>   
  2. #include<intrins.h>
  3. sbit RS=P2^0;   
  4. sbit RW=P2^1;   
  5. sbit E=P2^2;   
  6. sbit BF=P1^7;   
  7. sbit CLK=P2^3;
  8. sbit start=P2^4;
  9. sbit oe=P2^5;
  10. sbit eoc=P2^7;
  11. sbit out_pulse=P2^6;//5us脈沖  
  12. sbit p30=P3^0;
  13. #define uchar unsigned char
  14. #define uint unsigned int
  15. uchar n=0;
  16. uchar flag=0;//1s標志位  
  17. void delay1ms()
  18. {
  19. unsigned char i,j;            
  20. for(i=0;i<10;i++)
  21. for(j=0;j<33;j++)
  22.                  ;                           
  23. }
  24. void delay(unsigned int n)
  25. {
  26.                  unsigned int i;
  27.               for(i=0;i<n;i++)
  28.               delay1ms();
  29. }
  30. bit BusyTest(void)
  31.   {
  32.                   bit result;
  33.                             RS=0;       //根據規定,RS為低電平,RW為高電平時,可以讀狀態     
  34.                   RW=1;
  35.                   E=1;        //E=1,才允許讀寫  
  36.                   _nop_();   //空操作     
  37.                   _nop_();
  38.                   _nop_();
  39.                                _nop_();   //空操作四個機器周期,給硬件反應時間                    
  40.                   result=BF;  //將忙碌標志電平賦給result   
  41.                             E=0;//關掉使能端  
  42.                   return result;
  43.   }
  44. void Write_com (unsigned char dictate)//將模式設置指令或顯示地址寫入液晶顯示模塊      
  45. {  
  46.     while(BusyTest()==1); //如果忙就等待
  47.               RS=0;                  //根據規定,RS和R/W同時為低電平時,可以寫入指令      
  48.               RW=0;  
  49.               E=0; //寫入指令或顯示地址               

  50.               _nop_();
  51.               _nop_();            
  52.               P1=dictate;         
  53.               _nop_();
  54.               _nop_();
  55.               _nop_();
  56.               _nop_();            
  57.               E=1;                  
  58.               _nop_();
  59.               _nop_();
  60.               _nop_();
  61.               _nop_();              
  62.                 E=0;                 
  63. }
  64. void WriteAddress(unsigned char x)
  65. {
  66.      Write_com(x|0x80); //顯示位置的確定方法規定為"80H+地址碼x"            
  67. }
  68. void WriteData(unsigned char y)
  69. {
  70.     while(BusyTest()==1);
  71.                 RS=1;         
  72.                 RW=0;
  73.                 E=0;//寫入數據                        
  74.                 P1=y;         
  75.                 _nop_();
  76.                 _nop_();
  77.                 _nop_();
  78.       _nop_();      
  79.                 E=1;        
  80.                 _nop_();
  81.                 _nop_();
  82.                 _nop_();
  83.                 _nop_();      
  84.                 E=0;           
  85. }
  86. void LcdInt(void)
  87. {
  88.                  delay(15);            
  89.                  Write_com(0x38);  //數據總線為8位 ,顯示兩行  
  90.               delay(5);  
  91.               Write_com(0x0c); //顯示功能開,無光標,光標不閃爍   
  92.               delay(5);
  93.               Write_com(0x06);  //寫入數據后  地址寄存器     AC的內容減一      
  94.               delay(5);                                                                                                                                                           
  95.               Write_com(0x01); //清屏
  96.               delay(5);
  97. }
  98. void sysinit()
  99. {
  100.                                              
  101.               TMOD = 0x21;//T1,T0同時使用,就設置  T1方式2,T0方式1    ,即TMOD=0x21   
  102.               TH1=0xff;
  103.               TL1=0xEC;//50khz
  104.               EA = 1; //開總中斷
  105.               ET1=1;
  106.               TR1=1; //啟動定時器T1  
  107.               TH0=0x3c;
  108.               TL0=0xb0;//50MS定時  
  109.               ET0=1;
  110.               TR0=1;
  111.               start=0;    // START: A/D轉換啟動信號,輸入,高電平有效。
  112.               oe=0;  
  113. }
  114. void t0(void) interrupt 1
  115. {
  116.               ET0=0;
  117.               TH0=0X45;                       
  118.               TL0=0X00;//50MS定時
  119.               n++;
  120.               if(n==20) {flag=1;n=0;}//實現一秒的定時,來計算果過零次數出一
  121.               ET0=1;
  122. }
  123. void t1(void) interrupt 3
  124. {
  125.               ET1=0;
  126.               CLK=~CLK;//代表取反   
  127.               ET1=1;//T1中斷允許  
  128. }
  129. //0808數據采集   
  130. unsigned char adc()
  131. {
  132.    unsigned  char  Temp;
  133.    start=1;
  134. //              delay(1);//do not delay  
  135.               start=0;  //啟動信號 ,下降沿有效     
  136.    while (!eoc);// A/D轉換結束信號  
  137.               P0=0xff;
  138. //              delay(1);
  139.    oe=1;//數據輸出允許信號   
  140.    Temp=P0;//讀取采集數據   
  141.    oe=0;
  142. //  delay(4);
  143.    return(Temp);//返回采集數據   
  144. }
  145. void display(uint a)//顯示子函數  
  146. {
  147.               uint bai,shi,ge;
  148.               bai=a/100;
  149.               shi=(a-bai*100)/10;
  150.               ge=a%10;
  151.               WriteAddress(2);
  152.               WriteData(0x30+bai);//顯示百位  
  153.               WriteData(0x30+shi);//顯示十位  
  154.               WriteData(0x30+ge);//顯示個位  
  155.             
  156. }
  157. void main()
  158. {
  159.               uint temp1,temp2;
  160.               uchar f=0;
  161.               LcdInt();
  162.               delay(5);
  163.               sysinit();
  164.               CLK=0;
  165.               WriteAddress(0);
  166.               WriteData('f');
  167.               WriteData(':');
  168.               WriteAddress(5);
  169.               WriteData('H');            
  170.               WriteData('z');
  171.               while(1)
  172.               {                           
  173.                             temp2=temp1;
  174.                             temp1=adc();//ad采集                               if(((temp1>=128)&&(temp2<=128))||((temp1<=128)&&(temp2>=128)))
  175.                             {
  176.                                           f++;//f是存放過零次數的  
  177.                                           out_pulse=1;
  178.                                           _nop_();
  179.                                           _nop_();
  180.                                           _nop_();
  181.                                           _nop_();
  182.                                           _nop_();
  183.                                           out_pulse=0;//產生5us的脈沖信號   
  184.                             }
  185.                             if(flag==1)//到達1s后計算頻率   
  186.                             {
  187.                                           flag=0;
  188.                                           f=f/2;//信號頻率為過零次數出除以二     
  189.                                           display(f);//顯示頻率
  190.                                           f=0;
  191.                             }            
  192.               }
  193. }</b></font>
復制代碼

4.1 按鍵聲光報警實驗

一、實驗要求

利用外部硬件中斷,按下一次按鍵產生一次外部中斷,在中斷服務程序中計數器加1,同時通過發光二極管的閃爍和蜂鳴器響的次數,指示計數器的當前值。當計數到10時,再次按鍵將重新從1開始計。

二、實驗過程及結果記錄

步驟:

  • 關掉實驗箱電源,將MCU板插接在母版上,將硬件連接好
  • 在仿真器斷電情況下將仿真器的仿真頭插在MCU板的CPU插座上。將仿真器與PC機的通信口連接好,打開實驗箱及仿真器的電源。

(3)運行Keil u Vision2,建立工程“int0_c.uV2”,CPU為AT89C51,包含啟動文件“STARTUP.A51”。

(4)將編寫好的程序加入工程“int0_c.uV2”,并設置工程“int0_c.uV2”的屬性,將其晶振頻率設置為11.0592MHz,選擇輸出的可執行文件,仿真方式為“選擇硬仿真”,并選擇其中的“PROTEUS VSM MONITOR 51 DEIVER”仿真器。

(5)構造(Build)工程“int0_c.uV2”。如果輸入有誤,則進行修改,直至構造正確。

(6)運行程序,按下MCU板上的KEY0按鍵,觀察每次按鍵按下時主板上的發光二極管的閃爍和蜂鳴器響的次數,是否符合程序要求,分析出錯原因,繼續執行(4)(5),直至結果正確。

結果:

老師實驗室驗證

三、實驗源程序


  1. <font style="font-size: 14pt">#include<reg52.h>
  2. #define uint unsigned int
  3. #define uchar unsigned char
  4. sbit bell=P3^1; // 用 p3.1 口控制 bell
  5. sbit led=P3^0; // 用 P3^0 來控制 led
  6. sbit key0=P3^2; // 報警的鍵
  7. uint count; // 定義一個無符號整形數 ,
  8. 用來計數
  9. /******************************************************************/
  10. void delay(uint count) // 延時 1ms
  11. {
  12. uint x,y;
  13. for(x=count;x>0;x--)
  14. for(y=110;y>0;y--);
  15. }
  16. /******************************************************************/
  17. void show(uint count) // 使鈴鐺響,使燈亮的
  18. 函數
  19. { uint i;
  20. for(i=0;i<=count;i++) // 函數循環 i 次
  21. led=0;bell=0; // 燈亮,鈴響
  22. delay(500); // 延時 0.5s
  23. led=1;bell=1; // 燈滅,鈴停
  24. delay(500); // 延時 500ms
  25. }
  26. }
  27. /***********************************************************/
  28. Void s_timer0() interrupt 0 using 0 // 中斷 0
  29. {
  30. EA=0; // 屏蔽其他中斷請求
  31. show(count); // 調用子程序
  32. count++;
  33. delay(50);
  34. if(count>=10) // 若 count 為十則結

  35. count=0;
  36. EA=1; // 開放中斷
  37. }
  38. /************************** 主程序 **********************************/
  39. void main()
  40. { EA=1; // 開放中斷
  41. EX0=1; // 允許外部中斷 0 中斷
  42. IT0=0; // 外部中斷 0 為電平觸發方式
  43. while(1); // 循環執行,等待循環
  44. }</font>
復制代碼


4.5 8255并行I/O擴展及交通信號燈控制實驗

一、實驗要求

利用8255實現可編程的并行I/O擴展功能,并完成交通燈控制。實驗要求每個方向紅燈亮30s,然后綠燈亮25s,再閃爍綠燈5s。使用靜態數碼管顯示綠燈亮倒計時。

二、實驗過程及結果記錄

步驟:

(1)關掉實驗箱電源,將MCU板、PIO板、KEY&LED板插接在母版上,將硬件連接好

(2)在仿真器斷電情況下將仿真器的仿真頭插在MCU板的CPU插座上。將仿真器與PC機的通信口連接好,打開實驗箱及仿真器的電源。

(3)運行Keil u Vision2,建立工程“PIO8255_traffic_c.uV2”,CPU為AT89C51,包含啟動文件“STARTUP.A51”。

(4)將編寫好的程序加入工程“PIO8255_traffic_c.uV2”,并設置工程“PIO8255_traffic_c.uV2”的屬性,將其晶振頻率設置為11.0592MHz,選擇輸出的可執行文件,仿真方式為“選擇硬仿真”,并選擇其中的“PROTEUS VSM MONITOR 51 DEIVER”仿真器。

(5)構造(Build)工程“PIO8255_traffic_c.uV2”。如果輸入有誤,則進行修改,直至構造正確。

(6)運行程序,觀察交通燈的狀態轉換以及倒計時器的顯示是否符合程序要求。若不符合,分析出錯原因,繼續執行(4)(5),直至結果正確。

結果:

老師實驗室驗證

三、實驗源程序


  1. <font style="font-size: 14pt">#include <reg52.h>
  2. #include <absacc.h>
  3. #define PA XBYTE[0x7FFC] //CS--A15
  4. #define COM XBYTE[0x7FFF]
  5. /***************************************************************************/
  6. void init_8255(void)
  7. {
  8. COM=0x80; // c = out, a = out,b = out
  9. }
  10. /***************************************************************************/
  11. void Uart_Init(void)
  12. {
  13. SCON = 0x10; //SCON:工作模式 0
  14. PCON = 0x00;
  15. TI = RI = 0;
  16. IE = 0x90;
  17. EA = 0;
  18. }
  19. ***********************************************************
  20. void Uart_Out(unsigned char DA T) //74LS164 的串轉并
  21. {
  22. TI = 0;
  23. SBUF = ~DAT; }
  24. ***************************************************************************
  25. void delay_ms(unsigned int ms) //延時 1ms 程序
  26. {
  27. int j;
  28. for(;ms!=0; ms--)
  29. for (j=0;j<125;j++)
  30. {
  31. }
  32. }
  33. ********************************************************
  34. int main(void)
  35. {
  36. signed char i;
  37. init_8255();
  38. Uart_Init();
  39. while(1)
  40. {
  41. PA = 0x96; //東西綠燈亮
  42. for(i = 25;i >= 0;i--) // 延時 25s
  43. {
  44. Uart_Out(~(((i/10)<<4) | (i%10)));
  45. delay_ms(1000);
  46. }
  47. for(i = 5;i > 0;i--) //5s
  48. {
  49. PA = 0xBE;
  50. delay_ms(500);
  51. PA = 0x96;
  52. delay_ms(500);
  53. }
  54. PA = 0x69; //南北綠燈亮
  55. for(i = 25;i >= 0;i--) // 延時 25s
  56. {
  57. Uart_Out(~(((i/10)<<4) | (i%10)));
  58. delay_ms(1000);
  59. }
  60. for(i = 5;i > 0;i--) //5s
  61. {
  62. PA = 0xEB;
  63. delay_ms(500);
  64. PA = 0x69;
  65. delay_ms(500);
  66. }
  67. }
  68. }</font>
復制代碼


4.7 7279鍵盤/動態LED顯示實驗

一、實驗要求

利用7279進行鍵盤掃描及動態LED數碼管的顯示控制。當按下某個鍵時,所按按鍵對應的字符顯示在最右端LED數碼管上;再次按下一個按鍵,則原來顯示的內容往左移1位,新按下的字符顯示在最右端;當6位LED均顯示已滿時,再次按下新的按鍵,則原來顯示的內容同樣都左移1位,最后1位顯示新按按鍵的字符。

二、實驗過程及結果記錄

步驟:

(1)關掉實驗箱電源,將MCU板、KEY&LED板插接在母版上,將硬件連接好

(2)在仿真器斷電情況下將仿真器的仿真頭插在MCU板的CPU插座上。將仿真器與PC機的通信口連接好,打開實驗箱及仿真器的電源。

(3)運行Keil u Vision2,建立工程“HD7279_c.uV2”,CPU為AT89C51,包含啟動文件“STARTUP.A51”。

(4)將編寫好的程序加入工程“HD7279_c.uV2”,并設置工程“HD7279_c.uV2”的屬性,將其晶振頻率設置為11.0592MHz,選擇輸出的可執行文件,仿真方式為“選擇硬仿真”,并選擇其中的“PROTEUS VSM MONITOR 51 DEIVER”仿真器。

(5)構造(Build)工程“HD7279_c.uV2”。如果輸入有誤,則進行修改,直至構造正確。

(6)運行程序,觀察結果是否符合程序要求。若不符合,分析出錯原因,繼續執行(4)(5),直至結果正確。

結果:

老師實驗室驗證

三、實驗源程序


  1. <font style="font-size: 14pt">#include <reg51.h>
  2. //*** 函數定義 ***
  3. void long_delay(void); // 長延時
  4. void short_delay(void); // 短暫延時
  5. void delay10ms(unsigned char); // 延時 10MS
  6. void write7279(unsigned char, unsigned char); // 寫入到 HD7279
  7. unsigned char read7279(unsigned char); // 從 HD7279 讀出
  8. void send_byte(unsigned char); // 發送一個字節
  9. #define uchar unsigned char
  10. #define uint unsigned int
  11. uchar
  12. bianma[]={0x1b,0x13,0x0b,0x03,0x1a,0x12,0x0a,0x02,0x19,0x11,0x09,0x01,0x18,0x10,0x08,0x00};
  13. unsigned char receive_byte(void); // 接收一個字節
  14. //*** 變量及 I/O 口定義 ***
  15. unsigned char digit[5];
  16. unsigned char key_number, j, k,mk; //mk 為按鍵次數計數值
  17. unsigned int tmr;
  18. unsigned long wait_cnter;
  19. sbit cs=P1^0; // cs at P1.0
  20. sbit clk=P1^1; // clk 連接于 P1.1
  21. sbit dat=P1^2; // dat 連接于 P1.2
  22. sbit key=P1^3; // key 連接于 P1.3
  23. void write7279(unsigned char cmd, unsigned char dta)
  24. {
  25. send_byte (cmd);
  26. send_byte (dta);
  27. }
  28. unsigned char read7279(unsigned char command)
  29. {
  30. send_byte(command);
  31. return(receive_byte());
  32. }
  33. void send_byte( unsigned char out_byte)
  34. {
  35. unsigned char i;
  36. cs=0;//芯片使能
  37. long_delay();
  38. for (i=0;i<8;i++) // 分 8 次移入數據
  39. {
  40. if (out_byte&0x80)// 先傳高位
  41. {
  42. dat=1;
  43. }
  44. else
  45. {
  46. dat=0;
  47. }
  48. clk=1;
  49. short_delay();
  50. clk=0;
  51. short_delay();
  52. out_byte=out_byte*2;// 數據左移
  53. }
  54. dat=0;
  55. }
  56. unsigned char receive_byte(void)
  57. {
  58. unsigned char i, in_byte;
  59. dat=1; // set to input mode
  60. long_delay();
  61. for (i=0;i<8;i++)// 分 8 次讀入數據高位在前
  62. {
  63. clk=1;
  64. short_delay();
  65. in_byte=in_byte*2; // 數據左移
  66. if (dat)
  67. {
  68. in_byte=in_byte|0x01;
  69. }
  70. clk=0;
  71. short_delay();
  72. }
  73. dat=0;
  74. return (in_byte);
  75. 12
  76. }
  77. void long_delay(void)
  78. {
  79. unsigned char i;
  80. for (i=0;i<0x30;i++);
  81. }
  82. void short_delay(void)
  83. {
  84. unsigned char i;
  85. for (i=0;i<8;i++);
  86. }
  87. void main(){
  88. uchar jianpan,i,num;
  89. send_byte(0xa4); //全部復位指令
  90. while(1){
  91. if(key==0){ //如果按鍵按下
  92. send_byte(0x15); //讀鍵盤指令
  93. jianpan=receive_byte(); //接收鍵盤數據
  94. // P0=num;
  95. for(i=0;i<16;i++){
  96. if(jianpan==bianma[i]){ // 等于判斷一定是雙等于號
  97. num=i;
  98. break;
  99. }
  100. }
  101. send_byte(0xa1);
  102. write7279(0xc8,num);
  103. while(key==0);
  104. }
  105. } }</font>
復制代碼


完整的Word格式文檔51黑下載地址:

單片機實驗報告.docx (325.27 KB, 下載次數: 9)




分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 成人免费视屏 | 国产一区二区不卡 | 搞av.com | 久久久久久亚洲精品 | 国产aa| 中文字幕国产视频 | a级黄色毛片免费播放视频 国产精品视频在线观看 | 男人天堂网址 | 国产精品亚洲精品日韩已方 | 欧美一区二区三区电影 | 99久久国产| 亚洲一区二区三区免费在线观看 | 中文字幕一区二区三区四区 | 欧美精产国品一二三区 | 国内毛片毛片毛片毛片 | 久久99精品久久久久久国产越南 | 在线视频99 | 日韩在线中文字幕 | 欧美精品成人影院 | 亚洲成人一区 | 欧洲精品一区 | 亚洲欧美精 | 精品粉嫩超白一线天av | 欧美不卡一区二区三区 | 999免费视频 | 欧美在线观看一区 | 亚洲综合在线视频 | 永久av | 91原创视频在线观看 | 国产精品1区2区3区 一区中文字幕 | 免费网站在线 | 精品一区二区三区日本 | 亚洲九九 | 四虎影院在线观看av | 国产一区二区三区四区 | 国产精品一区在线观看 | 日本福利一区 | 成人国产精品色哟哟 | 亚洲三区在线观看 | 国产精品欧美一区二区三区不卡 | 欧美日韩最新 |