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

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 5807|回復(fù): 8
打印 上一主題 下一主題
收起左側(cè)

單片機(jī)+LCD1602矩陣鍵盤(pán)的計(jì)算器程序

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
51的LCD1602+矩陣鍵盤(pán)的簡(jiǎn)易計(jì)算器

代碼有優(yōu)化


單片機(jī)源程序如下:
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #include <stdio.h>
  4. #include "lcd1602.h"

  5. typedef unsigned char uchar;
  6. typedef unsigned int uint;

  7. void Init_Time0(void);
  8. uchar Change(uchar x,uchar y);
  9. void KeyScan(void);
  10. uchar KeyDriver(void);

  11. sbit KEY_OUT_1 = P1^4;
  12. sbit KEY_OUT_2 = P1^5;
  13. sbit KEY_OUT_3 = P1^6;
  14. sbit KEY_OUT_4 = P1^7;

  15. sbit KEY_IN_1  = P1^0;
  16. sbit KEY_IN_2  = P1^1;
  17. sbit KEY_IN_3  = P1^2;
  18. sbit KEY_IN_4  = P1^3;

  19. uchar KeySta[4][4] = {  //全部按鍵狀態(tài)
  20.     {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1}
  21. };
  22. uchar backup[4][4] = {  //按鍵備份值,保存前一次的值
  23. {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1}
  24.                                 };

  25. void main()
  26. {
  27.         uchar num=0,i=0,sign=0;
  28.         uchar temp[16]={0};
  29.         bit first_flag=0;
  30.         float a=0,b=0;
  31.         uchar s=0;
  32.         
  33.         LCD_Init();        
  34.         LCD_Clear();
  35.         Init_Time0();
  36.         LCD_Write_String(0,0,"LCD Calculator");        
  37.         LCD_Write_String(0,1,"    Yanglizidi ");        
  38.                                 
  39.         while(1)
  40.         {
  41.                 num=KeyDriver();
  42.                 if(num!=0xff)   //如果掃描是按鍵有效值則進(jìn)行處理
  43.                 {
  44.                         if(i==0)   
  45.             LCD_Clear();
  46.   //輸入是第一個(gè)字符的時(shí)候需要把改行清空,方便觀看
  47.                         if( (num=='+')||(num=='-')||(num=='x')||(num=='/')||(num=='=')||(i==16))   //輸入數(shù)字最大值16,輸入符號(hào)表示輸入結(jié)束
  48.                         {
  49.                                 i=0;                //計(jì)算器復(fù)位
  50.                                 if(first_flag==0)   //如果是輸入的第一個(gè)數(shù)據(jù),賦值給a,并把標(biāo)志位置1,到下一個(gè)數(shù)據(jù)輸入時(shí)可以跳轉(zhuǎn)賦值給b
  51.                                 {
  52.                                         sscanf(temp,"%f",&a);
  53.                                         first_flag=1;
  54.                                 }
  55.                                 else
  56.                                         sscanf(temp,"%f",&b);
  57.                                 for(s=0;s<16;s++)  //賦值完成后把緩沖區(qū)清零,防止下次輸入影響結(jié)果
  58.                                  temp[s]=0;
  59.                                        
  60.                                 LCD_Write_Char(0,1,num);
  61.                                        
  62.                                 if(num!='=')
  63.                                         sign=num;                //如果不是等號(hào)記下標(biāo)志位
  64.                                 else
  65.                                 {
  66.                                         first_flag=0;                 //檢測(cè)到輸入=號(hào),判斷上次讀入的符合
  67.                                         switch (sign)
  68.                                                 {
  69.                                                         case '+':a=a+b;break;
  70.                                                         case '-':a=a-b;break;
  71.                                                         case 'x':a=a*b;break;
  72.                                                         case '/':a=a/b;break;
  73.                                                         default:break;
  74.                                                 }
  75.                                         sprintf(temp,"%g",a);    //輸出浮點(diǎn)型,無(wú)用的0不輸出
  76.                                         LCD_Write_String(1,1,temp);        //顯示
  77.                                         sign=0;
  78.                                         a=0;
  79.                                         b=0;
  80.                                         for(s=0;s<16;s++)
  81.                                          temp[s]=0;
  82.                                 }        
  83.                         }
  84.                 else if(i<16)
  85.                 {
  86.                          if((i==1)&&(temp[0]=='0'))  //如果第一個(gè)字符是0,判讀第二個(gè)字符
  87.                         {
  88.                                 if(num=='.')  //如果是小數(shù)點(diǎn)則正常輸入,光標(biāo)位置加1
  89.                                 {
  90.                                         temp[1]='.';
  91.                                         LCD_Write_Char(1,0,num);   //輸出數(shù)據(jù)
  92.                                         i++;
  93.                                 }
  94.                                 else
  95.                                 {
  96.                                         temp[0]=num;   //如果是1-9數(shù)字,說(shuō)明0沒(méi)有用,則直接替換第一位0
  97.                                         LCD_Write_Char(0,0,num);        //輸出數(shù)據(jù)
  98.                                 }
  99.                         }
  100.                         else
  101.                         {
  102.                                 temp[i]=num;
  103.                                 LCD_Write_Char(i,0,num);                //輸出數(shù)據(jù)
  104.                                 i++;    //輸入數(shù)值累加
  105.                         }
  106.                 }
  107.         }
  108. }        
  109. }

  110. void Init_Time0()
  111. {
  112.         TMOD |=0X01;                //使用模式1,16位定時(shí)器,使用"|"符號(hào)可以在使用多個(gè)定時(shí)器時(shí)不受影響
  113.         TH0=0XFC;               
  114.         TL0=0X66;                        //1ms
  115.         EA=1;
  116.         ET0=1;
  117.         TR0=1;
  118. }

  119. void Time0() interrupt 1
  120. {
  121.         TH0=0XFC;               
  122.         TL0=0X66;                        //1ms
  123.         KeyScan();
  124. }




  125. //   轉(zhuǎn)換成矩陣上的數(shù)
  126. uchar Change(uchar x,uchar y)
  127. {
  128.         switch(y*4+x)
  129.         {
  130.                 case 0:return '1';break;//0 按下相應(yīng)的鍵顯示相對(duì)應(yīng)的碼值
  131.                 case 1:return '2';break;//1
  132.                 case 2:return '3';break;//2
  133.                 case 3:return '+';break;//3

  134.                 case 4:return '4';break;//4
  135.                 case 5:return '5';break;//5
  136.                 case 6:return '6';break;//6
  137.                 case 7:return '-';break;//7

  138.                 case 8:return '7';break;//8
  139.                 case 9:return '8';break;//9
  140.                 case 10:return '9';break;//a
  141.                 case 11:return 'x';break;//b

  142.                 case 12:return '0';break;//c
  143.                 case 13:return '.';break;//d
  144.                 case 14:return '=';break;//e
  145.                 case 15:return '/';break;//f
  146.                 default:return 0xff;break;
  147.         }
  148. }
  149.         


  150. /*------------------------------------------------
  151.           按鍵值處理函數(shù),返回掃鍵值
  152.            可以根據(jù)需要改變返回值

  153.                           | 1 | 2 | 3 | + |  
  154.                           | 4 | 5 | 6 | - |  
  155.                           | 7 | 8 | 9 | * |  
  156.                           | 0 | . | = | / |
  157. ------------------------------------------------*/

  158. //  按鍵驅(qū)動(dòng),檢查按鍵動(dòng)作
  159. uchar KeyDriver()
  160. {
  161.         bit flag2=0;
  162.         uchar p,num2,q;
  163.         for(p=0;p<4;p++)
  164.                 {
  165.                         for(q=0;q<4;q++)
  166.                         {
  167.                                 if(backup[p][q] != KeySta[p][q])  //檢測(cè)按鍵動(dòng)作
  168.                                 {
  169.                                         if(backup[p][q] != 0)                //按鍵按下時(shí)執(zhí)行的操作
  170.                                         {
  171.                                                 num2 = Change(p,q);
  172.                                                 flag2=1;
  173.                                         }
  174.                                   backup[p][q] = KeySta[p][q];   //更新前一次的備份值
  175.                                 }
  176.                         }
  177.                 }
  178.                 if(flag2==1)
  179.                   return num2;
  180.                 else
  181.                         return (0xff);
  182. }

  183. //    按鍵掃描,間隔1ms
  184. void KeyScan()
  185. {
  186.         uchar i;
  187.         static uchar keyout=0;  //索引
  188.         static uchar keybuf[4][4] = {
  189.    {0xFF, 0xFF, 0xFF, 0xFF},  {0xFF, 0xFF, 0xFF, 0xFF},
  190.    {0xFF, 0xFF, 0xFF, 0xFF},  {0xFF, 0xFF, 0xFF, 0xFF}
  191.     };
  192.         
  193.         //緩存區(qū)
  194.   keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
  195.   keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;
  196.   keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;
  197.   keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;
  198.                
  199.         for(i=0;i<4;i++)
  200.         {
  201.                 if((keybuf[keyout][i] &0x0f) == 0x00)
  202.                 {
  203.                         //連續(xù)檢測(cè)4次,四次都為0,可認(rèn)為按鍵按下
  204.       KeySta[keyout][i] = 0;
  205.                 }
  206.                 else if((keybuf[keyout][i] &0x0f) ==0x0f)
  207.                 {
  208.                         //連續(xù)檢測(cè)4次,四次都為1,可認(rèn)為按鍵彈起
  209.       KeySta[keyout][i] = 1;
  210.                 }
  211.         }
  212.         keyout++;   //變更下一次掃描的行
  213.         keyout &= 0x03;
  214.         switch (keyout)                //釋放引腳
  215.         {
  216.           case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;
  217.     case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
  218.     case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
  219.     case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;
  220.     default: break;
  221.         }
  222. }
復(fù)制代碼

本人初學(xué),僅供參考,存在錯(cuò)誤和不足之處,請(qǐng)大家回帖多多指教,切勿照搬,Keil代碼下載:
LCD1602智能計(jì)算器1.0.7z (37.46 KB, 下載次數(shù): 186)

評(píng)分

參與人數(shù) 1黑幣 +30 收起 理由
admin + 30

查看全部評(píng)分

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

使用道具 舉報(bào)

沙發(fā)
ID:124010 發(fā)表于 2022-3-16 10:40 | 只看該作者
你好,請(qǐng)問(wèn)這個(gè)是實(shí)時(shí)顯示的嗎?比如我輸入5.23
按下5 顯示5
按下 . 顯示5.
按下2 顯示5.2
按下3 顯示5.23
回復(fù)

使用道具 舉報(bào)

板凳
ID:224024 發(fā)表于 2022-5-30 11:29 | 只看該作者
程序有問(wèn)題 一直顯示光標(biāo)
回復(fù)

使用道具 舉報(bào)

地板
ID:916624 發(fā)表于 2022-6-21 22:06 | 只看該作者
伊森亨特 發(fā)表于 2022-3-16 10:40
你好,請(qǐng)問(wèn)這個(gè)是實(shí)時(shí)顯示的嗎?比如我輸入5.23
按下5 顯示5
按下 . 顯示5.

好像是的
回復(fù)

使用道具 舉報(bào)

5#
ID:916624 發(fā)表于 2022-6-21 22:07 | 只看該作者
轉(zhuǎn)身11111 發(fā)表于 2022-5-30 11:29
程序有問(wèn)題 一直顯示光標(biāo)

你去看LCD1602的命令集,命令集里有顯示光標(biāo)和不顯示光標(biāo)的,我覺(jué)得有光標(biāo)比較帥,就打開(kāi)了
回復(fù)

使用道具 舉報(bào)

6#
ID:128880 發(fā)表于 2022-8-9 17:05 | 只看該作者
采用定時(shí)器掃描按鍵,執(zhí)行效率比較高。
回復(fù)

使用道具 舉報(bào)

7#
ID:374444 發(fā)表于 2022-9-12 14:38 | 只看該作者
準(zhǔn)備下載試試,看看效果如何
回復(fù)

使用道具 舉報(bào)

8#
ID:1084356 發(fā)表于 2023-6-16 10:44 | 只看該作者
原理圖啥樣的
回復(fù)

使用道具 舉報(bào)

9#
ID:916624 發(fā)表于 2023-7-19 11:30 | 只看該作者

事過(guò)太久了,就是一個(gè)51開(kāi)發(fā)板。電路部分也不難,可以從網(wǎng)上搜模塊電路,改改工程里的管腳就能跑
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 日本在线视频一区二区 | 凹凸日日摸日日碰夜夜 | 99久久精品国产麻豆演员表 | 久久久久久久91 | 成人一区在线观看 | 玩丰满女领导对白露脸hd | 国产精品久久久99 | 一本在线 | 五月天国产 | 日韩国产中文字幕 | 精品欧美一区二区三区久久久小说 | 精品中文视频 | 亚洲天堂一区 | 久久精品女人天堂av | 国产精品视频免费播放 | 欧美日韩视频在线播放 | 中文精品久久 | 欧美一区二区三区在线观看视频 | 亚洲视频在线观看免费 | 精品视频一区二区 | 午夜免费观看网站 | 日韩高清一区 | av资源网站 | 欧美日韩在线一区二区 | 一区二区视屏 | 国产一二三区在线 | 成人毛片一区二区三区 | 99国内精品| aaaa一级毛片 | 免费人成激情视频在线观看冫 | 欧美日韩精品中文字幕 | 中文字幕不卡视频在线观看 | 久久久精彩视频 | 亚洲一区二区三区视频在线 | 久久人人爽人人爽 | 午夜小视频在线播放 | 亚洲精品国产区 | 亚洲欧美日韩精品久久亚洲区 | 精品视频在线一区 | wwwww在线观看 | 欧美在线日韩 |