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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

51單片機紅外遙控計算器設計文檔

[復制鏈接]
跳轉到指定樓層
樓主
ID:363782 發表于 2020-6-12 11:08 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
本設計是實現一個有四則運算功能計算器。它的硬件部分包括:一個STC89C52單片機,一塊LCD1602液晶顯示器,一個紅外遙控器。是一個以STC89C52單片機為核心控制電路,LCD1602負責顯示輸入輸出數據,利用紅外遙控器完成電路的鍵入操作部分,電路簡單,操作方便。
設計的目的
(1)計算器是我們生活中必不可少的工具,結合自身所學,設計一個基于51單片機的計算器,使其能實現加減乘除的功能。
(2)在電路設計中熟悉元器件選型,及Protues下單片機系統仿真與調試,不斷完善電路與程序。
(3)理解紅外解碼以及LCD1602顯示原理,將所學知識運用到計算器設計中。

(1)能實現多位數加減乘除四則運算。
(2)LCD1602液晶顯示按鍵值與計算結果。
(3)紅外遙控按鍵。
(4)利用proteus和keil進行仿真調試。
第2章 總體方案設計
計算器系統設計可采用兩種方案,方案一:以51單片機為核心配合相關硬件來實現。方案二:以FPGA芯片為核心配合相關硬件實現。
方案一:選用51單片機控制
單片機一個小而完善的微型計算機系統,它很容易和其他硬件配合實現各種各樣的功能。具有應用范圍廣泛、易于操作和使用、開支小等優點。完全滿足本次設計要求。
方案二:選用FPGA控制
在1985年,Xilinx公司研制出第一個FPGA芯片。因為其具有易于使用、較高的集成度、開發時間短等優點,FPGA在電子領域中得到快速發展和應用。用戶可對FPGA內部的邏輯模塊和I/O模塊重新配置,以實現用戶的邏輯。它還具有靜態可重復編程和動態在系統重構的特性,使得硬件的功能可以像軟件一樣通過編程來修改。作為專用集成電路領域中的一種半定制電路,FPGA既解決了定制電路的不足,又克服了原有可編程器件門電路數有限的缺點。
但是對于我來說,FPGA還是很陌生的。沒有專門學習過這個芯片,應用FPGA芯片很困難。另外,由于芯片還需外部存儲芯片,并且運行較麻煩,保密性不好,總之,采用FPGA設計計算器成本開支比較大,開發困難。
經過兩個方案的綜合比較,我們從價格、可操作性等角度來考慮,本次設計將采用以STC89C52單片機為核心構成計算器系統。
第3 章 硬件設計
3.1  整體硬件設計
本次設計設計的計算器由單片機最小系統、LCD1602液晶屏、紅外遙控器三個部分組成。將 STC89C52作為計算器系統核心,完成對紅外遙控或鍵盤的響應、LCD1602液晶顯示等功能的控制。利用C語言程序在KEIL軟件中進行編程,對STC89C52的 I/O 口進行充分的利用,使得STC89C52能夠正確讀取被使用者按下的相應功能鍵,然后通過單片機內部相關運算,控制LCD1602 液晶屏顯示相應鍵值與運算結果。


3.2  時鐘電路及復位電路

時鐘電路:時鐘電路的核心是個比較穩定的振蕩器(一般用晶體振蕩器),振蕩器所產生的是正弦波,頻率不一定是電路工作的時鐘頻率,因此就要把這正弦波進行分頻,處理,最后形成時鐘脈沖,然后分配到需要的地方。

本次設計采用內部時鐘模式,首先,需要在XTAL1和XTAL2兩端之間連接一個晶體振蕩器,然后,在兩端接兩個一樣大的電容,最后,再把兩個電容接到地上;電容器容量的大小對振蕩頻率有輕微調控的作用,電容值一般情況下大概是30pF,振蕩的頻率重點由石英晶振的頻率確定,振蕩電路的頻率也就是晶體的固有頻率。具體如圖2所示。



復位電路:復位是單片機的初始化操作,其功能是把系統初始化。
單片機的復位條件是:1、RST必須接上連續的兩個機器周期2、RST必須接高電平。電路將在RST的高電平后的第二個周期進行復位。復位電路有兩種,一種是通過按鍵復位即按鍵復位,另一種是通過上電進行復位即上電復位。本設計采用的是按鍵復位,因為比較方便,只要輕輕按下開關鍵,就能輕松的實現復位功能。具體如圖3所示。

3.3  紅外遙控模塊
紅外遙控是一種無線、非接觸控制技術,具有抗干擾能力強,信息傳輸可靠,功耗低,成本低,易實現等顯著優點。當紅外遙控器按下指令鍵時,指令編碼電路產生所需的指令編碼信號,指令編碼信號對載波進行調制,再由驅動電路進行功率放大后由發射電路向外發射經調制定的指令編碼信號。
紅外接收頭內部電路包括紅外監測二極管,放大器,限幅器,帶通濾波器,積分電路,比較器等。紅外接收頭將紅外遙控器發出的已調制的編碼指令信號接收下來,并進行放大和濾波后送解調電路,解調電路將已調制的指令編碼信號解調出來,即還原為編碼信號。之后將編碼信號進入單片機內部進行解碼,最后由驅動電路來驅動執行電路實現各種指令的操作控制。
由于設計的計算器僅有加減乘除四則運算,故紅外遙控設置的有效按鍵只需要數字鍵(0~9) 、符號鍵(+、-、*、/)、等號鍵、小數點鍵等16個按鍵即可。具體如圖4所示。


3.4  4*4鍵盤模塊
考慮到軟件Proteus中無法進行紅外遙控仿真,故在仿真環節將紅外遙控變為4*4鍵盤,實物環節采用紅外遙控。4*4鍵盤鍵位設置與紅外遙控一樣包括數字鍵(0~9)、符號鍵(+、-、*、/)、等號鍵、小數點鍵等16個按鍵。
如果采用獨立按鍵的方式,在這種情況下,編程會很簡單,但是會占用大量的I/O 口資源,為此,引入了矩陣鍵盤的應用,采用四條I/O 線作為行線,四條I/O 線作為列線組成鍵盤。在行線和列線的每個交叉點上設置一個按鍵。這樣鍵盤上按鍵的個數就為4×4個。這種行列式鍵盤結構能有效地提高單片機系統中I/O 口的利用率,如圖5所示。具體如圖5所示。


3.5  LCD1602液晶顯示模塊
LCD是一種工業型字符液晶,它能夠顯示32個字符(16列×2行),工作電壓為3.3V或5V,對比度可自行調節,LCD的內部內部含有復位電路,用來提供各種控制命令,如:清屏、字符閃爍、光標閃爍、顯示移位等多種功能。由于LCD1602功耗低、體積小、顯示多樣,應用較為廣泛。本次設計采用LCD1602無背光14腳接口,具體如圖6所示。


LCD1602各個管腳說明如表1所示。

表1 LCD各管腳說明

編碼

引腳

引腳說明

1

2

3

4

5

6

7

8

9

10

11

12

13

14

VSS

VDD

VEE

RS

RW

E

D0

D1

D2

D3

D4

D5

D6

D7

接地

電源正極

對比度調整

數據/命令

讀/寫

使能信號

數據

數據

數據

數據

數據

數據

數據

數據

第1腳:VSS接地。
第2腳:VDD接3.3V或5V正電源。
第3腳:VEE端可以用來調整液晶對比度,接正電源時對比度最弱,接地時對比度最高。(對比度過高時會 產生“鬼影”,通常接一個10K的電位器調整對比度)。
第4腳:RS端為寄存器選擇端口,高電平時為數據寄存器、低電平時則是指令寄存器。
第5腳:R/W為讀寫信號端口,高電平時進行讀操作,低電平時進行寫操作。當RS和R/W共同為低電平時可以寫入指令或者顯示地址,當RS為低電平R/W為高電平時可以讀忙信號,當RS為高電平R/W為低電平時可以寫入數據。
第6腳:E端口為使能端,當E端由高電平跳變成低電平時,液晶模塊執行命令。
第7~14腳:D0~D7為8位雙向數據線。
3.6  整體電路圖
由于紅外遙控器在電路中無法模擬,因此在整體電路圖中采用了4*4鍵盤模擬。
采用4*4鍵盤時計算器系統運行過程:使用者按下任意按鍵后,STC89C52檢測、識別出被使用者按下的相應功能鍵,然后通過單片機內部相關邏輯運算,控制LCD1602 液晶屏顯示相應鍵值。
采用紅外遙控時計算器系統運行過程:使用者按下任意鍵后,紅外接收頭收到信號,然后將信號還原為編碼信號后送入STC89C52,STC89C52解碼后,通過單片機內部相關運算,控制LCD1602 液晶屏顯示相應鍵值。具體如圖7所示。


3.7  系統所用元器件

本系統所用的元器件清單如表2所示。

表2  本系統所用的元器件

元器件名稱
數量
30pf電容
1uf電解電容
2
1
100Ω電阻
1

STC89C52
1

LCD1602
1
排阻
1
滑動變阻器
紅外接收頭
1
1

第4章 程序設計
4.1  整體程序設計
程序實現的具體功能為:任意整數(最大14位)或小數加減乘除運算。
主程序流程圖如圖8所示。

如圖8所示,系統主要主要由主程序、紅外遙控輸入子程序、LCD顯示子程序、運算部分組成。主程序主要完成初始化功能;紅外遙控器主要負責鍵入數據,STC89C52進行數據運算。LCD液晶主要負責顯示輸入數據和輸出結果的工作;系統進入工作時首先進行初始化工作,之后系統將在循環以下這一過程:顯示,紅外信號接收,解碼處理,檢測輸入數據是否能夠正確進行運算處理,如果數據正確則進行數據運算,反之,報錯后返回到按鍵,重新輸入。
4.2  接收紅外信號解碼子程序設計
紅外信號接收子程序流程圖見圖9。
當我們按下遙控器后,遙控器發出一幀數據。這一幀數據由前導碼、用戶碼高8位、用戶碼低8位、數據碼、數據反碼組成。其中前導碼為9ms高電平接著4.5ms低電平,標志數據幀的開始;用戶碼(共16位)為紅外接收器識別遙控器的身份的標志,不同的遙控器一般用戶碼不同,以防止不同電器設備之間遙控碼的干擾;數據碼為紅外接收器識別遙控器上不同的按鍵的標志,對同一遙控器來說,按不同的鍵所發出的二進制編碼具有相同的用戶碼,不同的數據碼。當紅外接收頭在遙控有效距離內,接收到紅外遙控脈沖信號后,由內部轉換成電壓信號并經放大、長時控制、干擾抑制、帶通濾波并整形后輸出遙控代碼脈沖并送往單片機解碼。
單片機解碼就是將紅外接收頭輸出的脈沖還原為二進制的“0”和“1”,得到二進制“0”,“1”序列,進而分析所含的用戶碼和數據碼。接收的用戶碼與設定的用戶碼正反碼相比較              ,接收的數據碼與設定的數據碼正反碼相比較,正反碼一樣后執行后續程序。



4.3  LCD1602液晶顯示子程序設計
LCD1602流程顯示如圖10所示。


由圖10可以看出LCD1602顯示的基本流程。顯示模塊程序首先要對顯示模塊進行初始化,然后控制光標的位置。然后設置清屏、顯示位置的首地址等等相關指令。
4.4  四則運算子程序設計
四則運算流程如圖11所示。


運算過程中,檢測到運算符號時,應判斷運算結果是否溢出,若是數據溢出,則LCD顯示錯誤指令,反之數值顯示。特別是檢測到除號時,應判斷除數是否為0,若除數為0,則LCD顯示錯誤指令,反之數值結果顯示。
第5章 仿真與調試
5.1  Proteus仿真
第三章已提到過紅外遙控無法進行仿真,所以在仿真中用4*4鍵盤代替紅外輸入。計算器系統仿真如圖12所示,圖中所舉例子運算結果正確。




5.1.1 加法功能的調試
     加法功能仿真如圖13所示。



加法功能能夠成功實現任意14位數以內的加法,若是數據溢出,則系統報錯。
5.1.2  減法功能的調試
減法功能仿真如圖14所示。



減法功能能夠成功實現任意14位數以內的減法,若是數據溢出,則系統報錯。
5.1.3  乘法功能的調試

乘法功能仿真如圖15所示



乘法功能能夠成功實現任意14位數以內的乘法,若是數據溢出,則系統報錯。
5.1.4  除法功能的調試
除法功能仿真如圖16所示



除法功能能夠成功實現任意14位數以內的除法,若是數據溢出或除數為0,則系統報錯。
5.2  實物電路調試
基于51單片機的紅外遙控計算器實物如圖17所示


實物調試過程中,遇到了LCD1602不顯示數據、按一次鍵出現好多個數據、紅外遙控按鍵與LCD1602顯示不對應、計算結果顯示時間過短等問題。不過,最終都一一解決,LCD1602不顯示是由于程序中引腳沒能與與單片機內部接線相一致,導致LCD1602無法正常運行,故沒有顯示數據。而第二個問題是由于沒有在程序中加入延時去抖動,導致系統對實際按鍵的錯誤識別。第三個問題是由于遙控器編碼與程序中沒有一一對應,導致按鍵沒有對應。最后一個問題同樣是由于延時程序問題,好在最后都一一解決。

單片機源程序如下:
  1. #include <reg52.h>
  2. #include <stdlib.h>        //包含atof(),字符串->實數
  3. #include <stdio.h>         //包含sprintf(),實數->字符串
  4. #include <string.h>        //包含strcpy(),字符串復制
  5. #include <math.h>                               //數學函數頭文件
  6. #define uchar unsigned char
  7. #define uint unsigned int
  8. /*************lcd****************/
  9. sbit lcdrs=P2^6;           //LCD控制腳
  10. sbit lcdrw=P2^5;
  11. sbit lcden=P2^7;
  12. bit idata form;            //lcd顯示方式切換
  13. uchar idata state;         //lcd狀態字存儲
  14. /************計算器*************/
  15. bit idata eqsign;          //按等號標志
  16. bit idata press;           //鍵按標志
  17. bit idata savesign;        //可存儲結果標志
  18. bit idata sc;                                             //復用標志
  19. uchar idata process[30],proc;
  20. uchar idata continu=0;        //連續計算運算符號存儲
  21. uchar idata ferror;        //計算檢錯標志
  22. uchar idata ywei;                               //屏幕移位
  23. uchar idata count=0;       //輸入計數
  24. uchar idata count_num=0;   //組號計數
  25. uchar idata result[15];    //計算結果立存,save
  26. uchar idata jieguo[15];    //結果字符串
  27. uchar idata bdate[2][14];  //待計算字符串二維組
  28. uchar idata on_symbol;     //運算符號
  29. uchar idata fsym[2];       //函數前符號
  30. uchar idata ssym[2];       //存儲組前符號
  31. uchar idata bfun[2];       //計算值調用函數選擇
  32. double idata date[2];      //計算值雙精度變量組
  33. double idata resultdate;   //雙精度結果值                                
  34. sbit IRIN=P3^2;
  35. uchar idata m=0;
  36. unsigned char IrValue[6];


  37. /******************函數聲明**********************/

  38. /***************延時******************/
  39. void delay(uchar z);            
  40. /*************lcd寫命令***************/
  41. void write_com(uchar com);
  42. /*************lcd寫數據***************/
  43. void write_date(uchar date);
  44. /*************lcd讀狀態***************/
  45. void read_date(void);
  46. /*************lcd寫字符串*************/
  47. void write_str(uchar *str);
  48. /************液晶初始化***************/
  49. void init(void );
  50. /**************鍵盤掃描***************/
  51. uchar keyscan(void);
  52. /*************計算器復位**************/
  53. void fuwei();         
  54. /************error處理****************/
  55. void callerror(void);
  56. /***************撤銷鍵入**************/
  57. void huifu(void);
  58. /**********函數組前符號處理***********/
  59. uchar funqian(void);
  60. /************運算符預處理*************/
  61. void  cullars(uchar);
  62. /***********按鍵功能主處理************/
  63. void process_date(uchar press_date);
  64. /***********按鍵功能子處理************/
  65. void calculator(uchar press_date);
  66. /************************************************/
  67. /*************LCD程序****************/
  68. /**************延時******************/
  69. void DelayMs(unsigned int x);
  70. void IrInit();
  71. void ReadIr();

  72. void delay(uchar z)                                         
  73. {
  74.       uchar  x,y;
  75.       for(x=z;x>0;x--)
  76.       for(y=115;y>0;y--);
  77. }

  78. void DelayMs(unsigned int x)  
  79. {
  80.               unsigned char i;
  81.               while(x--)
  82.               {
  83.                             for (i = 0; i<13; i++)
  84.                             {}
  85.               }
  86. }

  87. void IrInit()
  88. {
  89.               IT0=1;              //下降沿觸發
  90.               EX0=1;              //打開中斷0允許
  91.               EA=1;              //打開總中斷
  92.               IRIN=1;              //初始化端口
  93. }

  94. /**************寫命令*****************/
  95. void write_com(uchar com)
  96. {
  97.       lcdrs=0;
  98.       lcdrw=0;
  99.       lcden=0;
  100.       P0=com;
  101.       delay(5);
  102.       lcden=1;
  103.       delay(5);
  104.       lcden=0;
  105. }
  106. /*************寫數據******************/
  107. void write_date(uchar date)
  108. {
  109.       lcdrs=1;
  110.       lcdrw=0;
  111.       lcden=0;
  112.       P0=date;
  113.       delay(5);
  114.       lcden=1;
  115.       delay(5);
  116.       lcden=0;
  117. }
  118. /*************讀狀態*****************/
  119. void read_date(void)
  120. {
  121.       lcdrs=0;
  122.       lcdrw=1;
  123.                 delay(5);
  124.                 P0=0xff;
  125.       lcden=1;
  126.       delay(5);
  127.       state=P0;
  128.       delay(5);
  129.       lcden=0;delay(5);
  130.                 state=state&127;
  131. }
  132. /*************寫字符串******************/
  133. void write_str(uchar *str)
  134. {   
  135.       uchar idata i;
  136.       for(i=0;str[i]!='\0';i++)
  137.          write_date(str[i]);
  138. }
  139. /***********液晶初始化***************/
  140. void init(void )
  141. {
  142.       write_com(0x38);       //模式:8位數據,兩行,5*7字體
  143.       write_com(0x0c);       //開顯示,無光標
  144.       write_com(0x06);       //向左增量移動
  145.       write_com(0x01);       //清屏
  146. }


  147. /**************鍵盤掃描*************/
  148. uchar keyscan()
  149. {
  150.               uchar idata keyment=0;
  151.               if(IrValue[2]!=0)
  152.               {
  153.               switch (IrValue[2])
  154.                             {
  155.                                           case 0x42:{keyment='7';press=1;}break;
  156.                                           case 0X52:{keyment='8';press=1;}break;
  157.                                           case 0X4a:{keyment='9';press=1;}break;
  158.                                           case 0X40:{keyment=0xfd;press=1;}break; //0xfd除號在1602液晶中的代碼
  159.                                           case 0X08:{keyment='4';press=1;}break;
  160.                                           case 0X1c:{keyment='5';press=1;}break;
  161.                                           case 0X5a:{keyment='6';press=1;}break;
  162.                                           case 0X44:{keyment='*';press=1;}break;
  163.                                           case 0X0C:{keyment='1';press=1;}break;
  164.                                           case 0X18:{keyment='2';press=1;}break;
  165.                                           case 0X5E:{keyment='3';press=1;}break;
  166.                                           case 0X07:{keyment='-';press=1;}break;
  167.                                           case 0X16:{keyment='0';press=1;}break;
  168.                                           case 0X19:{keyment='.';press=1;}break;
  169.                                           case 0X43:{keyment='=';press=1;}break;
  170.                                           case 0X15:{keyment='+';press=1;}break;
  171.                                           default:break;
  172.                            
  173.                             }
  174.             
  175.               return(keyment);
  176.             
  177.               }            
  178. }


  179. /**************計算器復位****************/
  180. void fuwei()
  181. {   uchar idata j,i;
  182.     write_com(0x0f);                  //lcd設置
  183.     write_com(0x01);
  184.     write_com(0x81);
  185.     resultdate=0;
  186.     for(i=0;i<2;i++)
  187.               { date[i]=0;bfun[i]=0;fsym[i]=0;//各標志置0
  188.                 for(j=0;j<14;j++)                            //字符數組初始化
  189.       {            
  190.         bdate[i][j]='\0';
  191.       }
  192.               }
  193.     count=0;                                                        //各標志置0
  194.     count_num=0;
  195.               proc=0;
  196.     ferror=0;
  197.     eqsign=0;
  198.               sc=0;
  199.               savesign=0;
  200.               ywei=0;
  201.               press=0;
  202.               on_symbol=0;
  203. }
  204. /**************error處理******************/
  205. void callerror(void)
  206. {   uchar idata i;
  207.     write_com(0x01);
  208.     write_com(0x81);
  209.     write_str("     error!     ");
  210.     for(i=0;i<200;i++)delay(25); //持續顯示 1s
  211. }

  212. /*****************運算符預處理*****************/
  213. void  cullars(uchar csym)
  214. {              read_date();                               //看第二組是否有輸入
  215.               ferror++;              //檢錯標志+1
  216.               continu=csym;                               //存儲運算符號
  217.               write_date(continu);//將用與連續計算的運算符號取出
  218.               ywei=0;                                                         
  219.               savesign=0;
  220.               count_num=1;     //組標志加1
  221.               count=0;                            //輸入計數清零
  222.               on_symbol=continu;  //運算符號調用
  223.               write_com(0xc2);
  224.             
  225.               return;
  226. }

  227. /**************按鍵功能主處理****************/
  228. void process_date(uchar press_date)
  229. {   
  230.      if(form==0){write_com(0x0f);form=1;}   //顯示方式切換 光標閃爍            
  231.      if(eqsign==1&&press==1)fuwei();                            //復位再次計算
  232.               press=0;
  233.               if(press_date==0)return;                       //無按鍵
  234.               process[proc]=press_date;
  235.               proc++;
  236.               calculator(press_date);
  237.             
  238.               return;
  239. }
  240. /***************按鍵功能子處理***************/
  241. void calculator(uchar press_date)
  242. {            
  243.      uchar idata j=0;
  244.               /*************************************/
  245.               IrValue[2]=0xff;
  246.               if((press_date<='9'&&press_date>='0')||(press_date=='.')) //數字鍵處理
  247.      {              savesign=0;                                            //不可更新存儲數據
  248.         if(sc==0)                                            //是否為復用sc為0,是數字
  249.         {
  250.            if(count<14-ywei)  //未調用函數時最多輸入14位數,包括小數點
  251.            {            
  252.                                                  write_date(press_date);
  253.                    bdate[count_num][count]=press_date; //儲存鍵值
  254.                    count++;
  255.            }
  256.            else {callerror();huifu();}  //超出14位出錯,恢復

  257.         }
  258.       }

  259.       /****************'+','-'處理*****************/
  260.        else if((press_date=='+')||(press_date=='-'))
  261.        {   
  262.                                   if(count==0)      // 表示輸入數據的符號,此時默認數值為0
  263.               {                                                              
  264.                 write_date(press_date);
  265.                 bdate[count_num][0]=press_date;
  266.                                                         bdate[count_num][1]='0';
  267.                                                         read_date();                                          //讀狀態
  268.                           write_date('0');
  269.                           write_com(state+0x81);//光標還回原來位置
  270.                 count=1;
  271.               }
  272.               else                                             //為運算符號
  273.               {  
  274.                                               cullars(press_date);
  275.               }                                         
  276.        }                                         
  277.        /****************'*','/'處理*****************/
  278.        else if(press_date==0xfd) //0xfd除號在1602液晶中的代碼
  279.        {            
  280.                      if(sc==1)                 //幅度 to 角度
  281.                                {  if(count!=0)
  282.                                   {sc=0;write_date(0xDF);count=14;}
  283.                                             else {callerror();huifu();}
  284.                                }
  285.                       else cullars(press_date);
  286.        }
  287.                  else if(press_date=='*') //0xfd除號在1602液晶中的代碼
  288.        {                                 
  289.                        cullars(press_date);
  290.        }
  291.        /*******************'='號處理*****************/
  292.        else if(press_date=='=')
  293.        {
  294.             write_com(0x01);           //清屏
  295.             write_com(0x80+0x40+4);
  296.             write_date(press_date);    //顯示等號
  297.                                 for(j=0;j<2;j++)                               //兩運算組的函數處理
  298.                                           {
  299.                                                            date[j]=atof(bdate[j]);  //倆組數據,字符串->實數
  300.                                                         if(fsym[j]=='-')date[j]=-date[j];              //函數前的符號處理
  301.                                           }
  302.                                           if(ferror==0)                                                                                                  //僅僅函數計算
  303.                                              {  resultdate=date[0];}
  304.             else                                                                                                                              //運算符號計算
  305.                                           {
  306.                                              switch(on_symbol)
  307.                {
  308.                   case '+':resultdate=date[0]+date[1];break;
  309.                   case '-':resultdate=date[0]-date[1];break;
  310.                   case '*':resultdate=date[0]*date[1];break;
  311.                   case 0xfd:resultdate=date[0]/date[1];break;       //0xfd除號在1602液晶中的代碼
  312.                }
  313.                                           }                                         
  314.             sprintf(jieguo,"%g",resultdate);//結果實數->字符串,采用格式字符g,系統選擇%f或%e輸出格式,六位有效數字         
  315.                       if((jieguo[0]>'9'||jieguo[0]<'0')&&(jieguo[1]>'9'||jieguo[1]<'0')&&jieguo[1]!='\0'&&jieguo[1]!='.')
  316.                                           {   callerror();fuwei();return;  }              //錯誤處理,當組1或組2不合法時結果是幾個英文字母提示            
  317.                                           else strcpy(result,jieguo);   //沒錯誤,保存結果                                                                                                                              
  318.             for(j=0;jieguo[j]!='\0';j++)               //顯示結果
  319.                  write_date(jieguo[j]);
  320.                                           for(;j<15;j++)write_date(' ');              //讓光標出屏幕
  321.                                           eqsign=1;                                                                                    //按等號鍵標志置1
  322.                                          
  323.                  }
  324.                  return;
  325. }            
  326.                                                                                                                                           
  327. /*********************主程序**********************/
  328. void main()
  329. {  
  330.       fuwei();                            //計算器初始化
  331.       init();       //顯示初始化               
  332.                 form=1;                            //顯示方式初始化
  333.                 proc=0;                            //計算工程存儲初始化
  334.                 write_com(0x81);
  335.                 IrInit();
  336.       while(1)     
  337.       {
  338.                
  339.                  process_date(keyscan()); //計算器
  340.       }
  341. }

  342. void ReadIr() interrupt 0
  343. {
  344.               unsigned char j,k;
  345.               unsigned int err;
  346.               unsigned char Time;
  347.               Time=0;                                                                     
  348.               DelayMs(70);

  349.               if(IRIN==0)                            //確認是否真的接收到正確的信號
  350.               {            
  351.                            
  352.                             err=1000;                                                        //1000*10us=10ms,超過說明接收到錯誤的信號
  353.                             /*當兩個條件都為真是循環,如果有一個條件為假的時候跳出循環,免得程序出錯的時
  354.                             侯,程序死在這里*/            
  355.                             while((IRIN==0)&&(err>0))              //等待前面9ms的低電平過去                             
  356.                             {                                         
  357.                                           DelayMs(1);
  358.                                           err--;
  359.                             }
  360.                             if(IRIN==1)                                          //如果正確等到9ms低電平
  361.                             {
  362.                                           err=500;
  363.                                           while((IRIN==1)&&(err>0))                            //等待4.5ms的起始高電平過去
  364.                                           {
  365.                                                         DelayMs(1);
  366.                                                         err--;
  367.                                           }
  368.                                           for(k=0;k<4;k++)                            //共有4組數據
  369.                                           {                                                      
  370.                                                         for(j=0;j<8;j++)              //接收一組數據
  371.                                                         {

  372.                                                                       err=60;                           
  373.                                                                       while((IRIN==0)&&(err>0))//等待信號前面的560us低電平過去
  374.                                                                       {
  375.                                                                                     DelayMs(1);
  376.                                                                                     err--;
  377.                                                                       }
  378.                                                                       err=500;
  379.                                                                       while((IRIN==1)&&(err>0))              //計算高電平的時間長度。
  380.                                                                       {
  381.                                                                                     DelayMs(1);//0.14ms
  382.                                                                                     Time++;
  383.                                                                                     err--;
  384.                                                                                     if(Time>30)
  385.                                                                                     {
  386.                                                                                                   EX0=1;
  387.                                                                                                   return;
  388.                                                                                     }
  389.                                                                       }
  390.                                                                       IrValue[k]>>=1;              //k表示第幾組數據
  391.                                                                       if(Time>=8)                                          //如果高電平出現大于565us,那么是1
  392.                                                                       {
  393.                                                                                     IrValue[k]|=0x80;
  394.                                                                       }
  395.                                                                       Time=0;                            //用完時間要重新賦值                                                                                                
  396.                                                         }
  397.                                           }
  398.                             }
  399.                             if(IrValue[2]!=~IrValue[3])
  400.                             {
  401.                                           return;
  402.                             }
  403.               }                                         
  404. }





  405. 附錄二:仿真源程序
  406. #include "reg52.h"
  407. #include <stdlib.h>        //包含atof(),字符串->實數
  408. #include <stdio.h>         //包含sprintf(),實數->字符串
  409. #include <string.h>        //包含strcpy(),字符串復制
  410. #include <math.h>                               //數學函數頭文件
  411. #define uchar unsigned char
  412. #define uint unsigned int
  413. /*************lcd****************/
  414. sbit lcdrs=P2^7;           //LCD控制腳
  415. sbit lcdrw=P2^6;
  416. sbit lcden=P2^5;
  417. bit idata form;            //lcd顯示方式切換
  418. uchar idata state;         //lcd狀態字存儲
  419. /************計算器*************/
  420. bit idata eqsign;          //按等號標志
  421. bit idata press;           //鍵按標志
  422. bit idata savesign;        //可存儲結果標志
  423. bit idata sc;                                             
  424. uchar idata process[30],proc;
  425. uchar idata continu=0;        //連續計算運算符號存儲
  426. uchar idata ferror;        //計算檢錯標志
  427. uchar idata ywei;                               //屏幕移位
  428. uchar idata count=0;       //輸入計數
  429. uchar idata count_num=0;   //組號計數
  430. uchar idata result[15];    //計算結果立存
  431. //uchar idata saveresult[15];//存儲結果數組
  432. uchar idata jieguo[15];    //結果字符串
  433. uchar idata bdate[2][14];  //待計算字符串二維組
  434. uchar idata on_symbol;     //運算符號
  435. uchar idata fsym[2];       //函數前符號
  436. uchar idata ssym[2];       //存儲組前符號
  437. uchar idata bfun[2];       //計算值調用函數選擇
  438. double idata date[2];      //計算值雙精度變量組
  439. double idata resultdate;   //雙精度結果值
  440. /***************時鐘****************/

  441. /******************函數聲明**********************/

  442. /***************延時******************/
  443. void delay(uchar z);            
  444. /*************lcd寫命令***************/
  445. void write_com(uchar com);
  446. /*************lcd寫數據***************/
  447. void write_date(uchar date);
  448. /*************lcd讀狀態***************/
  449. void read_date(void);
  450. /*************lcd寫字符串*************/
  451. void write_str(uchar *str);
  452. /************液晶初始化***************/
  453. void init(void );
  454. /**************鍵盤掃描***************/
  455. uchar keyscan(void);
  456. /*************計算器復位**************/
  457. void fuwei();         
  458. /************error處理****************/
  459. void callerror(void);
  460. /***************撤銷鍵入**************/
  461. void huifu(void);
  462. /**********函數組前符號處理***********/
  463. uchar funqian(void);
  464. /************運算符預處理*************/
  465. void  cullars(uchar);
  466. /***********按鍵功能主處理************/
  467. void process_date(uchar press_date);
  468. /***********按鍵功能子處理************/
  469. void calculator(uchar press_date);
  470. /************************************************/
  471. /*************LCD程序****************/
  472. /**************延時******************/
  473. void delay(uchar z)                                             //0.2 ms
  474. {
  475.       uchar  x,y;
  476.       for(x=z;x>0;x--)
  477.       for(y=100;y>0;y--);
  478. }

  479. /**************寫命令*****************/
  480. void write_com(uchar com)
  481. {
  482.       lcdrs=0;
  483. ……………………
  484. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼

以上文檔51hei提供下載:
基于51單片機的紅外遙控計算器.doc (9.77 MB, 下載次數: 34)

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

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 精品国产成人 | 国产成人综合在线 | 欧美精品在线一区 | 懂色av一区二区三区在线播放 | 亚洲导航深夜福利涩涩屋 | 波多野结衣一区二区 | 激情黄色在线观看 | 九九精品网 | 成人蜜桃av | 久久精品中文 | 精品久久久久久亚洲精品 | 国产精品一区二区三区免费观看 | 亚州av | 中文在线视频观看 | xxxxx免费视频| 国产精品久久久久久av公交车 | 中文字幕 在线观看 | 中文在线观看视频 | 国产九九九九 | 2018国产精品 | 久久久久国产一区二区三区四区 | 国产午夜精品久久久 | 国产高清在线视频 | 免费精品在线视频 | 国产精品1区2区 | 在线观看深夜视频 | 亚洲成网 | 国产农村一级片 | 在线高清免费观看视频 | 日本粉嫩一区二区三区视频 | 亚洲精品久久 | 中文精品视频 | 国产高清在线精品 | 亚洲精品在线播放 | 涩爱av一区二区三区 | 日韩在线不卡 | 亚洲一区二区三区免费在线 | 99视频在线 | 日韩免费一区 | 成人在线中文 | 国产福利在线播放麻豆 |