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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2533|回復: 2
打印 上一主題 下一主題
收起左側(cè)

基于51單片機的多功能計算機程序與Proteus仿真圖設計

[復制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:398204 發(fā)表于 2022-5-9 19:40 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
資料包括:
1.Proteus仿真文件,Proteus軟件版本為8.9
2.程序源代碼,C語言編譯器為keilv4
3.實現(xiàn)的功能:
   主要是計算器的基本功能和科學計算器許多功能,用最少的按鍵實現(xiàn)最多的計算功能,包括三角函數(shù)、指數(shù)、開根號以及天文數(shù)字、角度轉(zhuǎn)換的運算,此外還帶有記憶功能。
   系統(tǒng)用20個按鍵實現(xiàn)這些功能。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)



單片機源程序如下:
  1. #include<reg52.h>
  2. #include<stdlib.h>//包含atof(),字符串->實數(shù)
  3. #include<stdio.h>
  4. #include<string.h>
  5. #include<math.h>
  6. #define uchar unsigned char
  7. #define uint unsigned int
  8. uchar num;
  9. /**********LCD*********/
  10. sbit lcdrs=P3^7;   //LCD控制腳
  11. sbit lcdrw=P3^6;
  12. sbit lcden=P3^5;
  13. sbit beep=P0^7;

  14. bit form;  //LCD切換方式
  15. uchar idata state;
  16. /********計算器*******/
  17. sbit reset=P3^0;
  18. sbit back=P3^1;
  19. sbit save=P3^2;
  20. sbit sfyong=P3^3;
  21. bit eqsign;
  22. bit press;
  23. bit savesign;
  24. bit sc;

  25. uchar idata process[30],proc;
  26. uchar idata continu=0;
  27. uchar idata pai[2][2];
  28. uchar idata ferror;
  29. uchar idata ywei;
  30. uchar idata count=0;
  31. uchar idata count_num=0;//組號計數(shù)
  32. uchar idata result[15];//計算結(jié)果立存,save
  33. uchar idata saveresult[15];//存儲結(jié)果數(shù)組,sc+save
  34. uchar idata jieguo[15];//結(jié)果字符串
  35. uchar idata bdate[2][14];//待計算字符串二維組
  36. uchar idata on_symbol; //運算符號
  37. uchar idata fsym[2];     //函數(shù)前符號
  38. uchar idata ssym[2];  //存儲組前符號
  39. uchar idata bfun[2];   //計算值調(diào)用函數(shù)選擇
  40. uchar idata futojiao[2];  //幅度?to?角度變換
  41. double idata date[2];    //計算值雙精度變量組
  42. double idata resultdate;    //雙精度結(jié)果值
  43. /*******************函數(shù)聲明******************/

  44. /****************延時******************/
  45. void delay(uchar z);
  46. /*************lcd寫命令***************/  
  47. void write_com(uchar com);
  48. /*************lcd寫數(shù)據(jù)***************/  
  49. void write_date(uchar date);
  50. /*************lcd讀狀態(tài)***************/  
  51. void read_date(void);
  52. /*************lcd寫字符串*************/  
  53. void write_str(uchar *str);
  54. /************液晶初始化***************/  
  55. void init(void );   
  56. /**********移屏*******************/  
  57. void write();
  58. /**********復用提示開關(guān)***************/  
  59. void shift(void);
  60. /**************鍵盤掃描***************/  
  61. uchar keyscan(void);
  62. /*************計算器復位**************/  
  63. void fuwei();
  64. /************error處理****************/  
  65. void callerror(void);
  66. /***************撤銷鍵入**************/  
  67. void huifu(void);
  68. /**********函數(shù)組前符號處理***********/  
  69. uchar funqian(void);
  70. /************運算符預處理*************/  
  71. void  cullars(uchar);
  72. /***********輸出存儲數(shù)據(jù)預處理********/  
  73. char  memory(void);
  74. /***********按鍵功能主處理************/  
  75. void process_date(uchar press_date);
  76. /***********按鍵功能子處理************/  
  77. void calculator(uchar press_date);  
  78. /************************************************/  
  79. void write()  
  80. {     
  81.      for(num=0;num<16;num++)        
  82.         {         
  83.             write_com(0x18);         
  84.             delay(200);        
  85.         }  
  86. }
  87. /*************LCD程序****************/

  88. /**************延時******************/  
  89. void delay(uchar z)        
  90. {        
  91.     uchar  x,y;        
  92.     for(x=z;x>0;x--)        
  93.     for(y=100;y>0;y--);  
  94. }   

  95. /**************寫命令*****************/  
  96. void write_com(uchar com)  
  97. {        
  98.     lcdrs=0;        
  99.     lcdrw=0;        
  100.     lcden=0;        
  101.     P1=com;        
  102.     delay(5);        
  103.     lcden=1;        
  104.     delay(5);        
  105.     lcden=0;  
  106. }
  107.    
  108. /*************寫數(shù)據(jù)******************/  
  109. void write_date(uchar date)  
  110. {        
  111.     lcdrs=1;        
  112.     lcdrw=0;        
  113.     lcden=0;        
  114.     P1=date;        
  115.     delay(5);        
  116.     lcden=1;        
  117.     delay(5);        
  118.     lcden=0;  
  119. }
  120. /*************讀AC 地址*****************/  
  121. void read_date(void)  
  122. {        
  123.     lcdrs=0;        
  124.     lcdrw=1;     
  125.     delay(5);     
  126.     P1=0xff;        
  127.     lcden=1;        
  128.     delay(5);        
  129.     state=P1;        
  130.     delay(5);        
  131.     lcden=0;delay(5);     
  132.     state=state&127;  
  133. }

  134. /*************寫字符串******************/  
  135. void write_str(uchar *str)  
  136. {        
  137.     uchar idata i;        
  138.     for(i=0;str[i]!='\0';i++)           
  139.     write_date(str[i]);  
  140. }
  141. /***********液晶初始化***************/  
  142. void init(void )  
  143. {
  144.     write_com(0x38);  //模式:8位數(shù)據(jù),兩行,5*7字體
  145.     write_com(0x0c); //開顯示,無光標
  146.     write_com(0x06);//向左增量移動
  147.     write_com(0x01);       //清屏  
  148. }   
  149. /**********復用提示開關(guān)***************/  
  150. void shift(void)  
  151. {     
  152.     if(sc==1)     
  153.     {        
  154.         read_date();   //讀狀態(tài)        
  155.         write_com(0xc0); //顯示復用提示,左下角's'     
  156.         write_date('s');     
  157.         write_com(state+0x80);//光標還回原來位置
  158.     }   
  159.     else   
  160.     {        
  161.     read_date();        
  162.     write_com(0xc0);    //關(guān)閉復用提示     
  163.     write_date(' ');     
  164.     write_com(state+0x80);   
  165.     }   
  166.     return;  
  167. }   
  168. /**************鍵盤掃描*************/

  169. //  s1~s4   .    0    =    +
  170. //  s5~8    1    2    3    -
  171. //    s9~s12  4    5    6    *
  172. //  s13~s16 7    8    9    /
  173. //    k1~k4   C    DEL  M=   FS&S
  174. //
  175. uchar keyscan(void)          //按行掃描,有鍵按下則返回鍵符號,否則返回null  
  176. {     
  177.     uchar idata key0,key1,keyment=0;        
  178.     P2=0XFe;        //行1        
  179.     key0=P2;        
  180.     key0=key0&0xf0;        
  181.     key1=key0;        
  182.     if(key0!=0xf0)        
  183.     {
  184.         delay(5);               //鍵抖動處理
  185.         P2=0XFe;            
  186.         key0=P2;            
  187.         key0=key0&0xf0;            
  188.         if(key0==key1)            
  189.         {
  190.             beep=1;
  191.             delay(200);
  192.             beep=0;                  
  193.             switch(key0)                  
  194.             {                    
  195.                 case 0xe0:keyment='7';break;
  196.                 case 0xd0:keyment='8';break;
  197.                 case 0xb0:keyment='9';break;
  198.                 case 0x70:keyment=0xfd;break;  //0xfd除號在1602液晶中的代碼                  
  199.             }
  200.             while(key0!=0xf0)  //鍵釋放處理  
  201.             {                    
  202.             key0=P2;                    
  203.             key0=key0&0xf0;                  
  204.             }                  
  205.             press=1;     //鍵按標志置1   
  206.             return(keyment);            
  207.         }        
  208.     }        
  209.     P2=0XFd;       //行2        
  210.     key0=P2;        
  211.     key0=key0&0xf0;        
  212.     key1=key0;        
  213.     if(key0!=0xf0)        
  214.     {            
  215.         delay(5);            
  216.         P2=0XFd;            
  217.         key0=P2;            
  218.         key0=key0&0xf0;            
  219.         if(key0==key1)            
  220.         {   
  221.             beep=1;
  222.             delay(200);
  223.             beep=0;              
  224.             switch(key0)                 
  225.             {                    
  226.                 case 0xe0:keyment='4';break;
  227.                 case 0xd0:keyment='5';break;
  228.                 case 0xb0:keyment='6';break;  
  229.                 case 0x70:keyment='*';break;
  230.             }                 
  231.             while(key0!=0xf0)              
  232.             {                    
  233.             key0=P2;                    
  234.             key0=key0&0xf0;
  235.             }
  236.             press=1;                 
  237.             return(keyment);            
  238.         }        
  239.     }        
  240.     P2=0XFb;       //行3        
  241.     key0=P2;        
  242.     key0=key0&0xf0;        
  243.     key1=key0;        
  244.     if(key0!=0xf0)        
  245.     {            
  246.         delay(5);            
  247.         P2=0XFb;            
  248.         key0=P2;            
  249.         key0=key0&0xf0;            
  250.         if(key0==key1)            
  251.         {   
  252.             beep=1;
  253.             delay(200);
  254.             beep=0;              
  255.             switch(key0)                 
  256.             {                    
  257.                 case 0xe0:keyment='1';break;
  258.                 case 0xd0:keyment='2';break;  
  259.                 case 0xb0:keyment='3';break;
  260.                 case 0x70:keyment='-';break;
  261.             }                 
  262.             while(key0!=0xf0)               
  263.             {                     
  264.             key0=P2;                     
  265.             key0=key0&0xf0;                 
  266.             }                 
  267.             press=1;                 
  268.             return(keyment) ;            
  269.         }        
  270.     }        
  271.     P2=0XF7;       //行4        
  272.     key0=P2;        
  273.     key0=key0&0xf0;        
  274.     key1=key0;        
  275.     if(key0!=0xf0)        
  276.     {   
  277.         beep=1;
  278.         delay(200);
  279.         beep=0;           
  280.         delay(5);            
  281.         P2=0XF7;            
  282.         key0=P2;            
  283.         key0=key0&0xf0;            
  284.         if(key0==key1)            
  285.         {   
  286.             switch(key0)                 
  287.             {                  
  288.                 case 0xe0:keyment='.';break;   
  289.                 case 0xd0:keyment='0';break;                  
  290.                 case 0xb0:keyment='=';break;                  
  291.                 case 0x70:keyment='+';break;                 
  292.             }                 
  293.             while(key0!=0xf0)                 
  294.             {                  
  295.             key0=P2;                  
  296.             key0=key0&0xf0;                 
  297.             }                 
  298.             press=1;                 
  299.             return(keyment);            
  300.         }      
  301.     }
  302.     if(reset==0)          //復位鍵         
  303.         {   
  304.             beep=1;
  305.             delay(200);
  306.             beep=0;               
  307.             keyment=' ';            
  308.             press=1;
  309.             while(reset==0);//鍵釋放            
  310.             return(keyment);   
  311.         }      
  312.     else if(back==0)        //撤銷前次輸入
  313.         {   
  314.             beep=1;
  315.             delay(200);
  316.             beep=0;   
  317.             keyment='c';            
  318.             press=1;            
  319.             while(back==0);            
  320.             shift();            
  321.             return(keyment);   
  322.         }      
  323.     else  if(save==0)     //儲存數(shù)據(jù)鍵           
  324.         {      
  325.             delay(5);      
  326.             if(save==0)      
  327.             {
  328.                 beep=1;
  329.                 delay(200);
  330.                 beep=0;
  331.                 if(sc==0)    //輸出前次計算結(jié)果鍵   
  332.                 {         
  333.                     keyment='m';               
  334.                     press=1;               
  335.                     while(save==0);               
  336.                     return(keyment);      
  337.                 }      
  338.                 else      //更新存儲的數(shù)據(jù)或輸出存儲的數(shù)據(jù)
  339.                 {               
  340.                     keyment='n';               
  341.                     press=1;
  342.                     sc=0;      
  343.                     shift();               
  344.                     while(save==0);         
  345.                     return(keyment);      
  346.                 }   
  347.             }      
  348.         }
  349.         else if(sfyong==0)     //計算器時為復用功能鍵      
  350.         {               
  351.             delay(5);      
  352.             if(sfyong==0)      
  353.             {  
  354.                 beep=1;
  355.                 delay(200);
  356.                 beep=0;
  357.                 keyment='h';              
  358.                 press=1;              
  359.                 while(sfyong==0);         
  360.                 return(keyment);     
  361.             }return(0);      
  362.         }else return(0);    //無鍵按下返回null
  363.         return(0);
  364. }

  365.    
  366. /**************計算器復位****************/  
  367. void fuwei()  
  368. {   
  369.     uchar idata j,i;      
  370.     write_com(0x0f);     //lcd設置      
  371.     write_com(0x01);      
  372.     write_com(0x80);      
  373.     resultdate=0;      
  374.     for(i=0;i<2;i++)   
  375.     {
  376.         date[i]=0;bfun[i]=0;pai[0][i]=0;pai[1][i]=0;fsym[i]=0;futojiao[i]=0; //各標志置 0     
  377.         for(j=0;j<14;j++)  //字符數(shù)組初始化  
  378.         {         
  379.             bdate[i][j]='\0';        
  380.         }   
  381.     }      
  382.     count=0;    //各標志置0      
  383.     count_num=0;   
  384.     proc=0;      
  385.     ferror=0;      
  386.     eqsign=0;   
  387.     sc=0;   
  388.     savesign=0;   
  389.     ywei=0;   
  390.     press=0;   
  391.     on_symbol=0;  
  392. }

  393.   
  394. /**************error處理******************/
  395. void callerror(void)  
  396. {   
  397.     uchar idata i;      
  398.     write_com(0x01);      
  399.     write_com(0x80);      
  400.     write_str("     error!     ");
  401.     for(i=0;i<200;i++)
  402.     delay(25); //持續(xù)顯示 1s  
  403. }
  404. /*************函數(shù)組前符號處理************/
  405. uchar funqian(void)    //輸入函數(shù)前檢查是否錯誤  
  406. {  
  407.     if((bdate[ferror][0]=='+'||bdate[ferror][0]=='-')&&count==1)     
  408.     {      
  409.         fsym[ferror]=bdate[ferror][0];      
  410.         bdate[ferror][0]='\0';   
  411.         bdate[ferror][1]='\0';   
  412.         count=0;     
  413.     }
  414.     if(bdate[ferror][0]!='\0'||bfun[ferror]!=0)//錯誤輸入方式處理     
  415.     {
  416.         callerror();         
  417.         huifu();   
  418.         return(1);     
  419.     }     
  420.     return(0);  
  421. }
  422. /****************撤銷上次輸入****************/
  423. void huifu(void)  
  424. {      
  425.     uchar j,pro;    //pro變量用于恢復proc
  426.     if(proc!=0)proc--;   
  427.     pro=proc;   
  428.     fuwei();   
  429.     proc=pro;   
  430.     for(j=0;j<proc;j++)calculator(process[j]); //依次恢復之前的操作   
  431.     return;  
  432. }
  433. /*****************運算符預處理*****************/  
  434. void  cullars(uchar csym)  
  435. {
  436.     read_date();     //看第二組是否有輸入   
  437.     ferror++;              //檢錯標志+1   
  438.     continu=csym;     //存儲運算符號   
  439.     if(ferror==2&&state<0x43){callerror();huifu();return;}// 第二組無輸入且ferror=2,錯誤   
  440.     if(ferror==2&&state>0x42) //第二組有輸入且ferror=2,則進行連續(xù)計算   
  441.     {      
  442.         press=1;     //模擬按鍵'='和'M+';將本次的計算結(jié)果作為下一次計算的第一組
  443.         process_date('=');      
  444.         press=1;      
  445.         process_date('m');      
  446.         ferror=1;    //恢復現(xiàn)場,避免變化      
  447.         if(continu=='^'||continu=='%'){process[proc]='h';
  448.                proc++;process[proc]=continu;proc++;}
  449.         else{process[proc]=continu;proc++;}   //恢復連續(xù)計算過程   
  450.     }   
  451.     if(continu=='%'){write_str(" f");}else write_date(' ');
  452.     write_date(continu);//將用與連續(xù)計算的運算符號取出   
  453.     ywei=0;   
  454.     savesign=0;   
  455.     count_num=1;     //組標志加1   
  456.     count=0;   //輸入計數(shù)清零   
  457.     on_symbol=continu;  //運算符號調(diào)用   
  458.     write_com(0xc2);   
  459.     return;  
  460. }
  461. /*************輸出存儲數(shù)據(jù)預處理************/
  462. char  memory(void)  
  463. {
  464.     if((bdate[count_num][0]=='+'||bdate[count_num][0]=='-')&&count==1)//符號處理      
  465.     {
  466.          ssym[count_num]=bdate[count_num][0];
  467.          bdate[count_num][0]='\0';   
  468.          bdate[count_num][1]='\0';   
  469.          count=0;
  470.     }      
  471.     if(bdate[count_num][0]!='\0'){callerror();huifu();return(1);} //錯誤輸入方式處理   
  472.     return(0);  
  473. }
  474. /**************按鍵功能主處理****************/
  475. void process_date(uchar press_date)  
  476. {
  477.     if(form==0){write_com(0x0f);form=1;}   //顯示方式切換 光標閃爍      
  478.     if(eqsign==1&&press==1)fuwei();  //復位再次計算,記憶過程清零   
  479.     press=0;   
  480.     if(press_date=='c'){huifu();press_date=0;}   
  481.     if(press_date==0)return;          //無按鍵   
  482.     process[proc]=press_date;   
  483.     proc++;   
  484.     calculator(press_date);   
  485.     return;  
  486. }
  487. /***************按鍵功能子處理***************/
  488. void calculator(uchar press_date)  
  489. {
  490.     uchar idata j=0;   
  491.     /*************************************/   
  492.     if(press_date==('h'))    //復用鍵   
  493.     {        
  494.         sc=~sc;     //按鍵功能切換,sc為1時調(diào)用函數(shù)     
  495.         shift();     //顯示與關(guān)閉復用提示   
  496.     }      
  497.     /*************************************/
  498.     else if((press_date<='9'&&press_date>='0')||(press_date=='.')) //數(shù)字鍵處理      
  499.     {
  500.         savesign=0;     //不可更新存儲數(shù)據(jù)         
  501.         if(sc==0)     //是否為復用sc為0,是數(shù)字         
  502.         {
  503.             if(count<14-ywei)  //未調(diào)用函數(shù)時最多輸入14位數(shù),包括小數(shù)點            
  504.             {            
  505.                 write_date(press_date);
  506.                 bdate[count_num][count]=press_date; //儲存鍵值                     
  507.                 count++;            
  508.             }
  509.             else {callerror();huifu();}  //超出14位出錯,恢復
  510.         }
  511.         else switch(press_date)   //復用時         
  512.         {             //     排錯   置函數(shù)標志符號 復用清零  移位,此時數(shù)據(jù)只能(14-ywei)位            
  513.             case '7':  j=funqian();if(j==1)return;bfun[ferror]='s';sc=0;shift();ywei=4;write_str("sin ");break; //函數(shù)sin            
  514.             case '8':  j=funqian();if(j==1)return;bfun[ferror]='c';sc=0;shift();ywei=4;write_str("cos ");break; //函數(shù)cos            
  515.             case '9':  j=funqian();if(j==1)return;bfun[ferror]='t';sc=0;shift();ywei=4;write_str("tan ");break; //函數(shù)tan      
  516.             case '4':  j=funqian();if(j==1)return;bfun[ferror]='e';sc=0;shift();ywei=4;write_str("exp ");break; //函數(shù)exp      
  517.             case '5':  j=funqian();if(j==1)return;bfun[ferror]='l';sc=0;shift();ywei=3;write_str("ln ");break;  //函數(shù)ln      
  518.             case '6':  j=funqian();if(j==1)return;bfun[ferror]='g';sc=0;shift();ywei=3;write_str("Lg ");break;  //函數(shù)Lg      
  519.             case '1':  j=funqian();if(j==1)return;bfun[ferror]='q';sc=0;shift();ywei=5;write_str("sqrt ");break;//函數(shù)sqrt      
  520.             case '0':  j=funqian();if(j==1)return;bfun[ferror]='d';sc=0;shift();ywei=4;write_str("dao ");break; //函數(shù)dao(倒數(shù))
  521.             case '.': if(count==0){ pai[count_num][0]=1;count=14-ywei;     }   //圓周率 pai處理    π前面無加權(quán)        
  522.             else{ pai[count_num][1]=1;count=14;}   //  π前面可以有加權(quán),后面不能跟數(shù)據(jù)        
  523.             write_date(247);sc=0;shift();break;      
  524.     /************************2和3是雙參數(shù)函數(shù) 當運算符使用 *************************/      
  525.             case '2':  //x^y x的y次方        
  526.             cullars('^');   //調(diào)用運算符號處理程序        
  527.             sc=0;shift();        
  528.             break;      
  529.             case '3': //A/B的余數(shù)(雙精度)        
  530.             cullars('%');   //調(diào)用運算符號處理程序        
  531.             sc=0;shift();        
  532.             break;           
復制代碼

Keil5代碼與Proteus8.8仿真下載: 仿真代碼.7z (141.67 KB, 下載次數(shù): 29)



評分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

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

使用道具 舉報

沙發(fā)
ID:262 發(fā)表于 2022-5-10 23:55 | 只看該作者
好資料,51黑有你更精彩!!!
回復

使用道具 舉報

板凳
ID:398204 發(fā)表于 2022-5-15 01:34 | 只看該作者
heicad 發(fā)表于 2022-5-10 23:55
好資料,51黑有你更精彩!!!

近期會分享很多本科時做的各種仿真,希望和大家一起學習
回復

使用道具 舉報

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

本版積分規(guī)則

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

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲成av人片在线观看 | 国产目拍亚洲精品99久久精品 | 成年人免费看的视频 | 毛片视频网址 | 久久99精品国产自在现线小黄鸭 | 久久精品中文字幕 | 欧美日韩中文在线 | 久久久性色精品国产免费观看 | 国产专区视频 | 黄色国产在线视频 | 狠狠色综合欧美激情 | 国产精品五区 | 欧美片网站免费 | 色综合久久88色综合天天 | 国产精品国产a级 | 精品免费国产一区二区三区四区介绍 | 五月天激情综合网 | 欧美激情亚洲 | 国产午夜精品一区二区三区 | 精品三级在线观看 | 亚洲精品在线看 | 精品中文字幕久久 | 天堂中文在线播放 | 亚洲乱码国产乱码精品精98午夜 | 一区二区不卡视频 | 午夜视频在线免费观看 | 免费国产精品久久久久久 | 色综合国产 | 成人在线视频免费观看 | 最新中文字幕在线 | 超碰在线亚洲 | 欧美日韩精品一区二区三区四区 | 亚洲一区视频在线播放 | 欧美日韩精品一区二区三区四区 | 国产日韩精品久久 | 天天操天天天干 | 久久人人爽人人爽人人片av免费 | 国产精品成人在线观看 | 成人久久久 | 一本综合久久 | 日韩激情视频一区 |