找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 12484|回复: 24
收起左侧

ATmega16计算器代码(数码管显示)

  [复制链接]
ID:114509 发表于 2018-12-20 14:27 | 显示全部楼层 |阅读模式
ATmega16计算器

单片机源程序如下:


  1. /**********************************************************************/

  2.     /**计数器按键**
  3.         
  4.     (1) (2) (3) (4)
  5.         (5) (6) (7) (8)
  6.         (9) (0) (C) (=)
  7.         (+) (-) (*) (/)
  8.         
  9.         10:清零 11:确认 12:加 13:减 14:乘 15:除
  10.         
  11. **********************************************************************/
  12. //头文件
  13. #include <iom16v.h>   //包含型号头文件
  14. #include <macros.h>  //包含"位"操作头文件
  15. //宏定义
  16. #define uchar unsigned char
  17. #define uint unsigned int
  18. //定义按键返回值
  19. unsigned char keyvalue;
  20. //定义数码管段码(共阳)
  21. uchar LED[]=
  22. {        
  23.         0xC0,0xF9,0xA4,0xB0,
  24.         0x99,0x92,0x82,0xF8,
  25.         0x80,0x90
  26. };
  27. //定义数码管位的控制端
  28. uchar tab[]={0,0,0,0};
  29. //IO端口初始化
  30. void IO_init(void)         
  31. {         
  32.          DDRA = 0XFF;
  33.          DDRB = 0XFF;
  34.          DDRC = 0XFF;
  35.          DDRD = 0XF0;
  36.         PORTA = 0X00;
  37.         PORTB = 0X00;
  38.         PORTC = 0X08;
  39.         //PORTD = 0XFF;
  40. }
  41. //8M晶振下,延时1ms
  42. void delayms(uint z)  
  43. {
  44.          uint x,y;
  45.          for(x=z;x>0;x--)
  46.                   for(y=1333;y>0;y--);
  47. }
  48. //数码管显示
  49. void display(uint num)
  50. {
  51.         tab[0]=num%10;                   //取个位数
  52.         tab[1]=num/10%10;        //取十位数
  53.         tab[2]=num/100%10;        //取百位数
  54.         tab[3]=num/1000%10; //取千位数
  55.         
  56.         if(num<=9)//检测为小于等于9的在个位数显示
  57.         {
  58.                  PORTA=LED[tab[0]];
  59.                 PORTC=0x08;
  60.                 delayms(1);
  61.         }
  62.         if(num>9&&num<=99)//检测为大于9与小于等于99在个十位显示
  63.         {
  64.                  PORTA=LED[tab[0]];
  65.                 PORTC=0x08;
  66.                 delayms(1);
  67.                 PORTA=LED[tab[1]];
  68.                 PORTC=0x04;
  69.                 delayms(1);
  70.         }
  71.         if(num>99&&num<=999)//检测为大于99与小于等于999在个十百位显示
  72.         {
  73.                  PORTA=LED[tab[0]];
  74.                 PORTC=0x08;
  75.                 delayms(1);
  76.                 PORTA=LED[tab[1]];
  77.                 PORTC=0x04;
  78.                 delayms(1);
  79.                 PORTA=LED[tab[2]];
  80.                 PORTC=0x02;
  81.                 delayms(1);
  82.         }
  83.         if(num>999&&num<=9999)//检测为大于999与小于等于9999在个十百千位显示
  84.         {
  85.                  PORTA=LED[tab[0]];
  86.                 PORTC=0x08;
  87.                 delayms(1);
  88.                 PORTA=LED[tab[1]];
  89.                 PORTC=0x04;
  90.                 delayms(1);
  91.                 PORTA=LED[tab[2]];
  92.                 PORTC=0x02;
  93.                 delayms(1);
  94.                 PORTA=LED[tab[3]];
  95.                 PORTC=0x01;
  96.                 delayms(1);
  97.         }
  98. }
  99. //按键扫描
  100. int key_scan(void)
  101. {
  102.          uint j;//按键循环次数变量定义
  103.         PORTD=0xEF;// PD端口输出 1111 1110
  104.         for(j=0;j<5;j++)//按键检测4次
  105.         if((PIND&0x0F)!=0x0F)//按键检测
  106.         {
  107.                  delayms(20);//延时消抖
  108.                 if((PIND&0x0F)!=0x0F)//再次检测
  109.                 {
  110.                          if((PIND&0x01)==0)        //第一个按键按下
  111.                         keyvalue=1;                        //返回按键值 1
  112.                         if((PIND&0x02)==0)        //第二个按键按下
  113.                         keyvalue=2;                        //返回按键值 2
  114.                         if((PIND&0x04)==0)        //第三个按键按下
  115.                         keyvalue=3;                        //返回按键值 3
  116.                         if((PIND&0x08)==0)        //第四个按键按下
  117.                         keyvalue=4;                        //返回按键值 4
  118.                         while((PIND&0x0F)!=0x0F);//等待按键释放
  119.                 }
  120.         }
  121.         PORTD=0xDF;
  122.         for(j=0;j<5;j++)
  123.         if((PIND&0x0F)!=0x0F)
  124.         {
  125.                  delayms(20);
  126.                 if((PIND&0x0F)!=0x0F)
  127.                 {
  128.                          if((PIND&0x01)==0)
  129.                         keyvalue=5;
  130.                         if((PIND&0x02)==0)
  131.                         keyvalue=6;
  132.                         if((PIND&0x04)==0)
  133.                         keyvalue=7;
  134.                         if((PIND&0x08)==0)
  135.                         keyvalue=8;
  136.                         while((PIND&0x0F)!=0x0F);
  137.                 }
  138.         }
  139.         PORTD=0xBF;
  140.         for(j=0;j<5;j++)
  141.         if((PIND&0x0F)!=0x0F)
  142.         {
  143.                  delayms(20);
  144.                 if((PIND&0x0F)!=0x0F)
  145.                 {
  146.                          if((PIND&0x01)==0)
  147.                         keyvalue=9;
  148.                         if((PIND&0x02)==0)
  149.                         keyvalue=0;
  150.                         if((PIND&0x04)==0)
  151.                         keyvalue=10;
  152.                         if((PIND&0x08)==0)
  153.                         keyvalue=11;
  154.                         while((PIND&0x0F)!=0x0F);
  155.                 }
  156.         }
  157.         PORTD=0x7F;
  158.         for(j=0;j<5;j++)
  159.         if((PIND&0x0F)!=0x0F)
  160.         {
  161.                  delayms(20);
  162.                 if((PIND&0x0F)!=0x0F)
  163.                 {
  164.                          if((PIND&0x01)==0)
  165.                         keyvalue=12;
  166.                         if((PIND&0x02)==0)
  167.                         keyvalue=13;
  168.                         if((PIND&0x04)==0)
  169.                         keyvalue=14;
  170.                         if((PIND&0x08)==0)
  171.                         keyvalue=15;
  172.                         while((PIND&0x0F)!=0x0F);
  173.                 }
  174.         }
  175. }
  176. /*  
  177. //两种按键扫描都可以选择
  178. //按键扫描
  179. uint key_scan(void)
  180. {
  181.           unsigned char X,Y,Z;
  182.         DDRD=0xF0;
  183.         PORTD=0x0F;
  184.         if(PIND!=0x0F) //判断是否有键按下
  185.         {
  186.                  delayms(5); //延时,软件去干扰
  187.                 if(PIND!=0x0F) //确认按键按下
  188.                 {
  189.                          X=PIND|0xF0;
  190.                         delayms(5);
  191.                         DDRD=0x0F;
  192.                         PORTD=0xF0;
  193.                         if(PIND!=0xF0) //判断是否有键按下
  194.                         {
  195.                                  delayms(5); //延时,软件去干扰
  196.                                 if(PIND!=0xf0) //确认按键按下
  197.                                 {
  198.                                          Y=PIND|0x0F;
  199.                                         Z=X&Y; //取出键值
  200.                                         switch ( Z ) //判断键值(那一个键按下)
  201.                                         {
  202.                                                  //对键值赋值
  203.                                                 case 0b11101110: keyvalue= 1; break;//数字1键
  204.                                                 case 0b11101101: keyvalue= 2; break;//数字2键
  205.                                                 case 0b11101011: keyvalue= 3; break;//数字3键
  206.                                                 case 0b11100111: keyvalue= 4; break;//数字4键
  207.                                                 case 0b11011110: keyvalue= 5; break;//数字5键
  208.                                                 case 0b11011101: keyvalue= 6; break;//数字6键
  209.                                                 case 0b11011011: keyvalue= 7; break;//数字7键
  210.                                                 case 0b11010111: keyvalue= 8; break;//数字8键
  211.                                                 case 0b10111110: keyvalue= 9; break;//数字9键
  212.                                                 case 0b10111101: keyvalue= 0; break;//数字0键
  213.                                                 case 0b10111011: keyvalue=10; break;//删除键
  214.                                                 case 0b10110111: keyvalue=11; break;//ok键
  215.                                                 case 0b01111110: keyvalue=12; break;//加键
  216.                                                 case 0b01111101: keyvalue=13; break;//减键
  217.                                                 case 0b01111011: keyvalue=14; break;//乘键
  218.                                                 case 0b01110111: keyvalue=15; break;//除键
  219.                                                 default:break;
  220.                                         }
  221.                                         while(PIND!=0xf0); //等待按键释放
  222.                                 }
  223.                         }
  224.                 }
  225.         }
  226. }  */

  227. void main(void)
  228. {
  229.          uint num=0;//按键值
  230.         uint shu=0,shu1=0,shu2=0,flag=0,jieguo,fuhao;//数值定义
  231.         IO_init();//IO端口初始化
  232.         while(1)
  233.          {
  234.                   /*键盘值赋给num,如果小于9,说明是数值,假如先按的数值键为2,
  235.                 第一次用到shu1的值为0,则shu1=shu1*10+num(0*10+2=2),
  236.                 如果再按下第二个数值键,假设按下的数值键为3,
  237.                 则shu1=shu1*10+num(2*10+2=23),这样就能按下的数值显示出来。
  238.                 */
  239.                 keyvalue=20;//按键初值
  240.                 key_scan();//按键扫描
  241.                 num=keyvalue;//按键值赋给num
  242.                 if(num<=9&&flag==0)//按键0~9
  243.                 {
  244.                          shu1=shu1*10+num; //计算第一个数
  245.                         shu=shu1;
  246.                 }
  247.                 /*flag是标志位,作用就是第一次按下数值键赋值后,再按下功能键后,
  248.                 flag=1,当再按下数值键,就运行下面程序。
  249.                 */
  250.                 if(num>=0&&num<=9&&flag==1)//按键0~9
  251.                 {
  252.                          shu2=shu2*10+num;//计算第二个数
  253.                         shu=shu2;
  254.                 }
  255.                 /*使得数码管把第二次的数值shu2显示出来*/
  256.                 if(num>=12&&num<=15)//按键12~15 显示运算符号
  257.                 {
  258.                          fuhao=num;
  259.                         flag=1;   
  260.                 }
  261.                 /*这程序表示按下功能键后,把功能键值赋给fuhao这个数,
  262.                 同时把fuaho置1,为下次按下数值键作准备。
  263.                 */
  264.                 if(num==11)//计算数值确认
  265.                 {
  266.                          flag=0;
  267.                         switch(fuhao)
  268.                         {
  269.                                  case 12:jieguo=shu1+shu2;break;
  270.                                 case 13:jieguo=shu1-shu2;break;
  271.                                 case 14:jieguo=shu1*shu2;break;
  272.                                 case 15:jieguo=shu1/shu2;break;
  273.                                 default:break;
  274.                         }
  275.                         shu=jieguo;//计算结果送到shu显示,把shu1和shu2数清零。
  276.                         shu1=0;
  277.                         shu2=0;
  278.                 }
  279.                 if(num==10)//计算结果清零
  280.                 {
  281.                          num=0;
  282.                         jieguo=0;
  283.                         shu=0;   
  284.                         shu1=0;
  285.                         shu2=0;
  286.                         flag=0;
  287.                         fuhao=0;
  288.                 }
  289.                 display(shu);//计算结果显示
  290.          }
  291. }
复制代码

所有资料51hei提供下载:
ATmega16计算器.zip (36.21 KB, 下载次数: 94)

评分

参与人数 2黑币 +51 收起 理由
51单片机1234 + 1 共享资料的黑币奖励!
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:114509 发表于 2018-12-21 10:00 | 显示全部楼层
实物图和手画原理图,供参考。
捕获.PNG
捕获2.PNG
回复

使用道具 举报

ID:114509 发表于 2020-6-20 22:46 | 显示全部楼层
程序好像有些问题
1.png
回复

使用道具 举报

ID:114509 发表于 2020-6-21 14:52 | 显示全部楼层
HI-XM 发表于 2020-6-20 22:46
程序好像有些问题

使用软件仿真的话数码管显示会显示不全?实物电路做的没问题,不知道什么原因?
回复

使用道具 举报

ID:114509 发表于 2020-6-24 10:13 | 显示全部楼层
if(num<=9)//检测为小于等于9的在个位数显示
        {
                 PORTA=LED[tab[0]];
                PORTC =0x08;
                delayms(2);
                PORTC =0;//这里关闭数码管显示
        }

数码管显示问题找到了,打开数码管显示后再把它关闭,问题就解决了。

回复

使用道具 举报

ID:114509 发表于 2020-7-18 17:57 | 显示全部楼层
1132209248 发表于 2020-7-2 16:05
楼主,我试了一下,一旦数码管显示到了两位数,就会显示不全

我仿真了没问题,我把程序和仿真文件发给你们。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表