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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

簡易單片機計算器的proteus仿真實現

[復制鏈接]
跳轉到指定樓層
樓主
一個簡單的加減乘除計算器/*注意上面頭文件"bsp_GOG1.h"包含一個可選宏定義  
        若需使用擴展板請增加全局宏定義 _GOG1Plus
        定義方式
        菜單 Project->Options for Target->C51->Define
        在此處填入   “_GOG1Plus”
在此代碼完全兼容,第三次課的矩陣按鍵程序,在此感謝魏同學的幫助 */
/*
計算器功能實現:4位數字的加,減,乘法,除法沒有做商的小數部分
1.對輸入運算數的有效性檢查,即超過9999時,顯示錯誤;
2,用LED--》D3來指示系統的正常運行狀態
3,運算的結果超過9999時,提示錯誤顯示;
4,當系統運行錯誤時,或者顯示亂碼時,按A鍵清除數碼管顯示;
5,除法運算時,的二個運算數為0時,提示錯誤顯示
6, 運算表達式不完整時,報錯:
                      (1)無數 * 第二個數 = 報錯
                      (2)第一個數 * 無數 = 報錯
                      (3)直接按等號,報錯
7,D3 LED燈實際是隔1ms 閃爍一次,
*/
/*矩陣按鍵 功能定義:
#define ADD        15          //'#':加法  S15
#define SUB        12          //'C':減法  S12
#define MUL        14          //'*':乘法  S13
#define DIV        11          //'B':除法  S8
#define EQU        13          //'D':等于  S16
#define CLE     10        //'A':清除  S4

仿真圖:


單片機源程序如下:
  1. #include <REG52.H>          //51單片機標準寄存器聲明頭文件
  2. #include "bsp_GOG1.h"   //這個頭文件用于映射GOG1學習板載硬件接口
  3. /*計算器的運算狀態定義:*/
  4. #define NoKey       0xaa  //沒有按鍵按下的狀態
  5. #define ErrKey      0xff  //錯誤的按鍵狀態/干擾
  6. #define DpyErr            0x0e  //錯誤顯示狀態(碼表數組第14個元素:'E')
  7. #define DpyCle      0x10  //清屏(碼表數組第16個元素:0xff 關閉數碼管)
  8. #define InCount         0xf0  //有運算符輸入狀態
  9. #define InErrEqu          0x0f  //有等號輸入狀態
  10. #define NoCountFlag 0xa5  //沒有運算符的狀態
  11. /*矩陣按鍵 功能定義: */
  12. #define ADD        15          //'#':加法  S15
  13. #define SUB        12          //'C':減法  S12
  14. #define MUL        14          //'*':乘法  S13
  15. #define DIV        11          //'B':除法  S8
  16. #define EQU        13          //'D':等于  S16
  17. #define CLE 10    //'A':清除  S4
  18. /*相關子函數的聲明:*/
  19. void delayms(unsigned int ms);                          //延時函數
  20. void SegDisplay(unsigned char casebit);         //數碼管顯示函數
  21. unsigned char ReadKeyPad(void);          //讀取矩陣鍵盤函數
  22. void Timer0Init(void);                                         //定時器0初始化函數
  23. unsigned char CheckInput(void);                         //計算器檢查輸入狀態函數
  24. void DatUnpack(unsigned int dat);                 //計算器數據拆分函數
  25. bit CheckNum(unsigned int dat);                         //計算器數據有效性檢查函數
  26. void WarmDpy(unsigned char err);                 //計算器錯誤顯示函數
  27. void ComputeState(unsigned char dat);         //計算器計算過程函數

  28. //數碼管段碼表 共陽  17個元素: 0~F & 0xff
  29. unsigned char code SegCode[17]= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,
  30.                                  0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff};
  31. unsigned int Ans;              //運算結果

  32. bit AnsFlag=0;            //運算結果存在標志
  33. bit InFlag1=0;                      //輸入有效數字1標志
  34. bit InFlag2=0;                      //輸入有效數字2標志
  35. unsigned char CountFlag;  //運算符
  36. unsigned int  temp1=0,temp2=0;//輸入的2個運算的數字
  37. unsigned char DisBuff[4]={DpyCle,DpyCle,DpyCle,DpyCle};//數碼管顯示緩存
  38. /*******************************************************************************
  39.   * @brief  mian           (簡介)
  40.   * @param  無                   (參數)
  41.   * @retval 無                   (返回值)
  42.   ******************************************************************************/
  43. void main(void)                                    //程序從這里開始
  44. {
  45.     unsigned char in;                        //保存單個按鍵值的變量
  46.    
  47.     CountFlag=NoCountFlag;                //運算符初始狀態
  48.     Timer0Init();                                //定時器0初始化
  49.     while(1)
  50.     {
  51.         in=CheckInput();
  52.         while(in == NoKey) in=CheckInput(); //沒有按鍵按下,在此等待
  53.         if(in !=ErrKey)                //按鍵有效
  54.         {
  55.           ComputeState(in);  
  56.         }

  57.         else  WarmDpy(DpyErr); //按鍵無效,報錯 'E'

  58.     }
  59. }
  60. /*******************************************************************************
  61.   * @brief  ComputeState: 計算過程程序
  62.   * @param  unsigned char dat
  63.   * @retval 無
  64. *******************************************************************************/  
  65. void ComputeState(unsigned char dat)
  66. {
  67.     unsigned int num;         //保存運算操作數的變量
  68.     if(AnsFlag == 1)     //判斷上一次運算結果完成標志
  69.     {
  70.         WarmDpy(DpyCle); //清屏
  71.         AnsFlag=0;                 //清除有效運算完成標志
  72.     }
  73.     if((dat !=InCount)&(dat !=InErrEqu)&(dat <10)) //按下的鍵為數字
  74.     {

  75.         if(CountFlag == NoCountFlag) //沒有運算符存在,保存第一個數
  76.         {
  77.             num = temp1;
  78.             num *= 10;                                 //輸入的數字依次進高位
  79.             num += dat;
  80.             if( CheckNum(num)==1 )   //判斷數據有效性
  81.             {                                             //有效在數字范圍
  82.                 temp1 = num;                  //保存第一個數字
  83.                 InFlag1 = 1;         //輸入有效數字1標志
  84.                 DatUnpack(temp1);    //拆分數據,更新顯示緩存
  85.             }
  86.             else WarmDpy(DpyErr);    //超出范圍報錯
  87.         }
  88.         else              //運算符存在 ,保存第二個數
  89.         {
  90.             num = temp2;
  91.             num *= 10;
  92.             num += dat;
  93.             if(CheckNum(num)==1)
  94.             {
  95.                 temp2 = num;
  96.                 InFlag2 = 1;     //輸入有效數字2標志
  97.                 WarmDpy(DpyCle); //清除第一個數的顯示,消除'余暉'
  98.                 DatUnpack(temp2);//更新顯示緩存
  99.             }
  100.             else WarmDpy(DpyErr);
  101.         }
  102.     }
  103.     else    //按下的鍵為非數字(4則運算符被保存,這里考慮 清除鍵和 錯誤等號)
  104.     {
  105.         if(CLE == dat)                 //按下的為清除鍵
  106.         {
  107.             CountFlag = NoCountFlag; //清除運算符
  108.             InFlag1 =0;                                 //清除輸入有效數字1標志
  109.             InFlag2 =0;              //清除輸入有效數字2標志
  110.             AnsFlag=0;                                 //清除運算結果存在標志
  111.             temp1=0,temp2=0;         //清除輸入的2個運算數
  112.             WarmDpy(DpyCle);                 //清屏
  113.             Ans=0;                                         //清除上一次運算結果         
  114.         }
  115.         
  116.         if(InErrEqu == dat)                            //運算表達式不完整時,按下等號的情況
  117.             WarmDpy(DpyErr);         //報錯 'E'
  118.     }
  119. }

  120. /*******************************************************************************
  121.   * @brief  ReadKeyPad        用于讀取矩陣鍵盤鍵值
  122.   * @param  無
  123.   * @retval 矩陣鍵盤鍵值
  124.   * @note   鍵盤鍵值設置請修改case分支臨時變量b的賦值
  125.                                                 0xff 作為錯誤代碼,表示讀取出錯
  126. ******************************************************************************/
  127. unsigned char ReadKeyPad(void)
  128. {
  129.     unsigned char a,c,b=NoKey; //b 初始值為無按鍵的狀態
  130.     KeyPad = 0x0f;    //初始狀態,行號(P3^0~P3^3)高電平,列號(P3^4~P3^7)低電平
  131.     if(KeyPad != 0x0f)
  132.     {
  133.         delayms(20);                 //按鍵消抖動(延時實現)
  134.         if(KeyPad != 0x0f)         //按鍵被按下,初始狀態改變
  135.         {
  136.             a = KeyPad;                 //讀取矩陣鍵盤的行號
  137.         }
  138.         KeyPad = 0xf0;                 //初始狀態反轉
  139.         c = KeyPad;                         //讀取矩陣鍵盤的列號
  140.         a |= c;                                 //按位'或',通過行號,列號唯一確定矩陣按鍵值
  141.         switch (a) {
  142.         case 0xee:
  143.             b = 1;                          //S1
  144.             break;
  145.         case 0xed:
  146.             b = 4;                          //S5
  147.             break;
  148.         case 0xeb:
  149.             b = 7;                          //S9
  150.             break;
  151.         case 0xe7:
  152.             b = MUL;                  //S13'MUL'
  153.             break;
  154.         case 0xde:
  155.             b = 2;                          //S2
  156.             break;
  157.         case 0xdd:
  158.             b = 5;                          //S6
  159.             break;
  160.         case 0xdb:
  161.             b = 8;                          //S10
  162.             break;
  163.         case 0xd7:
  164.             b = 0;                          //S14
  165.             break;
  166.         case 0xbe:
  167.             b = 3;                         //S3
  168.             break;
  169.         case 0xbd:
  170.             b = 6;                         //S7
  171.             break;
  172.         case 0xbb:
  173.             b = 9;                         //S11
  174.             break;
  175.         case 0xb7:
  176.             b = ADD;                 //S15 'ADD'
  177.             break;
  178.         case 0x7e:
  179.             b = CLE;                 //S4 'CLE'
  180.             break;
  181.         case 0x7d:
  182.             b = DIV;                 //S8 'DIV'
  183.             break;
  184.         case 0x7b:
  185.             b = SUB;                 //S12 'SUB'
  186.             break;
  187.         case 0x77:
  188.             b = EQU;                 //S16 '='
  189.             break;
  190.         default :                         //沒有和 a 的匹配項
  191.             b = ErrKey;                 //錯誤的按鍵值
  192.             break;
  193.         }
  194.         KeyPad = 0xf0;                        //松手檢測
  195.         while (KeyPad != 0xf0);        //當沒有松手,將在此一直等待
  196.     }
  197.     return (b);                                //返回讀取的按鍵值
  198. }

  199. /******************************************************************************
  200.   * @brief  delayms        毫秒級延時函數
  201.   * @param  ms        延時的毫秒數 允許值 unsigned int范圍
  202.   * @retval 無
  203.   * @attention   這個函數只是用于12T 8051內核的單片機運行于12Mhz
  204.   *****************************************************************************/
  205. void delayms(unsigned int ms)         //延時子程序(晶振12Mhz)
  206. {
  207.     unsigned char i;
  208.     while(ms--)
  209.     {
  210.         for(i = 0; i < 120; i++);
  211.     }
  212. }

  213. /******************************************************************************
  214.   * @brief  SegDisplay 數碼管顯示&定時器中斷程序組成動態顯示
  215.   * @param  casebit        用于選擇數碼管的位 允許值 0~4
  216.   * @retval 無
  217.   * @attention   這個函數需配合定時器中斷服務程序
  218.   *****************************************************************************/
  219. void SegDisplay(unsigned char casebit)
  220. {
  221.     Seg7_Bits = 0xff;                             //關閉所有數碼管
  222.     Seg7_Data =SegCode[DisBuff[casebit]];//先把段碼值賦給P1(段選端口)
  223.     switch(casebit)
  224.     {
  225.     case 0:
  226.         Seg7_Bit1 = 0;
  227.         break;
  228.     case 1:
  229.         Seg7_Bit2 = 0;
  230.         break;
  231.     case 2:
  232.         Seg7_Bit3 = 0;
  233.         break;
  234.     case 3:
  235.         Seg7_Bit4 = 0;
  236.         break;
  237.     default :
  238.         Seg7_Bits = 0xff;        //關閉所有數碼管
  239.         Seg7_Data = 0xff;
  240.         break;
  241.     }
  242. }
  243. /************************************************************************************
  244.   * @brief  DatUnpack:數據拆分,同時把數據的千位,百位,十位,個位賦給顯示緩存數組DisBuff[]
  245.   * @param  unsigned int dat
  246.   * @retval 無
  247.   ***********************************************************************************/
  248. void DatUnpack(unsigned int dat)
  249. {

  250.     if((dat<10))                                     //1位數
  251.         DisBuff[0]=dat;
  252.     else if((dat<100)&&(dat>=10))         //2位數
  253.     {
  254.         DisBuff[1]=dat/10;
  255.         DisBuff[0]=dat%10;
  256.     }
  257.     else if((dat<1000)&&(dat>=100))         //3位數
  258.     {
  259.         DisBuff[2]=dat/100;
  260.         DisBuff[1]=dat%100/10;
  261.         DisBuff[0]=dat%100%10;
  262.     }
  263.     else if ((dat<10000)&&(dat>=1000))//4位數
  264.     {
  265.         DisBuff[3]=dat/1000;
  266.         DisBuff[2]=dat%1000/100;
  267.         DisBuff[1]=dat%1000%100/10;
  268.         DisBuff[0]=dat%1000%100%10;
  269.     }

  270. }
  271. /*******************************************************************************
  272.   * @brief  unsigned char CheckInput(): 檢查矩陣鍵盤輸入按鍵的類型(簡介)
  273.   * @param  無                                                                                                          (參數)
  274.   * @retval  數字,功能鍵(CLE,EQU,+,-,*,/),無按鍵的狀態                          (返回值)
  275.   ******************************************************************************/
  276. unsigned char CheckInput(void)
  277. {
  278.     unsigned char x;
  279.     x=ReadKeyPad();         //調用讀按鍵子程序
  280.     if(x != ErrKey)         //是否為錯誤按鍵值
  281.     {
  282.         if((x<10)|(x == NoKey)| (x == CLE))//按下的為數字,或沒有按鍵按下,或清除鍵
  283.         {
  284.             return (x);
  285.         }
  286.         else           //按下的為 運算符(四則運算 和 等號)
  287.         {
  288.             if(x == EQU) // 按下的為 等號"="
  289.             {                                                    
  290.                 switch (CountFlag)
  291.                 {
  292.                 case ADD:         Ans = temp1+temp2; break;
  293.                 case SUB:         Ans = temp1-temp2; break;
  294.                 case MUL:         Ans = temp1*temp2; break;
  295.                 case DIV:   if (temp2 == 0) //除法分母為0,報錯
  296.                     {
  297.                         WarmDpy(DpyErr);
  298.                         break;
  299.                     }
  300.                     else
  301.                     {
  302.                         Ans = temp1/temp2;//只計算除法商的整數,暫沒有考慮小數
  303.                         break;
  304.                     }
  305.                 }
  306.                 if( CheckNum(Ans)&&(InFlag1 ==1)&&(InFlag2 ==1))//檢測運算的有效性
  307.                                   {      
  308.                     DatUnpack(Ans);                //運算結果拆分,更新顯示緩存
  309.                     CountFlag = NoCountFlag;        //清除運算符
  310.                     temp1=0,temp2=0;                        //清除運算數字
  311.                     AnsFlag = 1;                                //運算結果存在標志
  312.                     InFlag1 =0;                                //清除有效數字輸入標志
  313.                     InFlag2 =0;
  314.                     Ans=0;                                        //清除運算結果
  315.                     return (NoKey);                        //此次運算完成,返回無按鍵狀態
  316.                   }
  317.                 else //WarmDpy(DpyErr) ;//運算表達式不完整或結果超出范圍,報錯
  318.                     return (InErrEqu);                 //返回有等號輸入的狀態
  319.                     }
  320.             else  //按下的為 4則 運算符(+ ,-,*, /)
  321.             {
  322.                 CountFlag = x;                 //保存運算符
  323.                 return (InCount);                 //返回有運算符輸入的狀態
  324.             }

  325.         }
  326.     }
  327.     else  return (ErrKey);                //返回錯誤按鍵值狀態
  328. }
  329. /*******************************************************************************
  330.   * @brief  CheckNum: 檢查計算器運算數的有效性
  331.   * @param  dat
  332.   * @retval bit 有效: 1,無效: 0
  333.   ******************************************************************************/
  334. bit CheckNum(unsigned int dat)
  335. {
  336.     if (dat < 10000)
  337.         return 1;          //數據有效
  338.     else
  339.         return 0;

  340. }
  341. /*******************************************************************************
  342.   * @brief  WarmDpy:數碼管錯誤顯示
  343.   * @param  err                實則:'E'的碼段值元素的下標
  344.   * @retval 無
  345.   ******************************************************************************/
  346. ……………………

  347. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼


所有資料51hei提供下載:
counter程序(V2.0).zip (122.64 KB, 下載次數: 165)


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

使用道具 舉報

沙發
ID:505898 發表于 2019-4-22 07:53 來自手機 | 只看該作者
下載試試
回復

使用道具 舉報

板凳
ID:620480 發表于 2019-10-8 13:57 | 只看該作者
謝謝樓主,辛苦啦,先下載下來看看
回復

使用道具 舉報

地板
ID:622546 發表于 2019-10-11 21:13 | 只看該作者
一共多少行啊.   看到后面舍不得花錢.

回復

使用道具 舉報

5#
ID:622546 發表于 2019-10-11 21:13 | 只看該作者
細致得一
回復

使用道具 舉報

6#
ID:779375 發表于 2020-6-15 10:45 | 只看該作者
樓主在嗎?
回復

使用道具 舉報

7#
ID:779375 發表于 2020-6-15 10:45 | 只看該作者
能不能加個好友私聊   我想下載這個
回復

使用道具 舉報

8#
ID:710460 發表于 2020-6-26 18:26 | 只看該作者
把矩陣鍵盤每一個按鍵都標記了
回復

使用道具 舉報

9#
ID:842963 發表于 2020-11-13 10:20 | 只看該作者
這是編譯之后的源程序嗎?有沒有沒編譯的
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 欧美一区二区免费视频 | 成人在线一区二区 | 久久大陆| 亚洲精品 在线播放 | 久久亚洲精品国产精品紫薇 | 97免费在线视频 | 成人一区二区在线 | 成人精品在线观看 | 亚洲一区二区免费看 | 国产视频久久久 | 国产欧美一级 | 日韩成人在线播放 | 九九九色 | 亚洲欧美在线一区 | 久久麻豆精品 | 亚洲二区在线 | 国产成人艳妇aa视频在线 | 国产精品婷婷 | 精品一二三区在线观看 | 欧洲尺码日本国产精品 | 欧美成人一级视频 | 亚洲aⅴ精品 | 亚洲福利一区二区 | 国内精品久久久久 | 99国产精品99久久久久久 | 成人一区二区在线 | 成人免费视屏 | 狠狠干狠狠操 | 成人精品一区二区三区中文字幕 | 国产精品揄拍一区二区 | av三级在线观看 | 亚洲三区视频 | 国产福利视频网站 | 人碰人操 | 精一区二区 | av黄色片在线观看 | 欧美成人在线影院 | 午夜视频在线观看视频 | 国产精品久久久亚洲 | 免费观看毛片 | 久久久久久久国产 |