完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
这是网上一个人写的程序,我给加了注释,对于大家理解程序很有帮助,但是始终不明到两个操作数是怎样传递给Tmp1和Tmp2的!
/* * Easy calculator * * K4:+ K8:- K12:* K16:/ K14:Clear K15:= * * Made by Kingst-刚哥 * date: 2010.12.21 */ #include typedef unsigned char uint8; typedef unsigned int uint16; typedef unsigned long uint32; typedef char int8; typedef int int16; typedef long int32; ***it KeyIn1 = P2^4; ***it KeyIn2 = P2^5; ***it KeyIn3 = P2^6; ***it KeyIn4 = P2^7; ***it KeyOut1 = P2^3; ***it KeyOut2 = P2^2; ***it KeyOut3 = P2^1; ***it KeyOut4 = P2^0; ***it ADDR0 = P1^0; ***it ADDR1 = P1^1; ***it ADDR2 = P1^2; ***it ADDR3 = P1^3; ***it ENLED = P1^4; ***it BUZZ = P1^6; //蜂鸣器控制位 #define FADD 10 #define FSUB 11 #define FMUL 12 #define FDIV 13 #define FRES 14 #define FEQU 15 #define KEY_DELAY 300 //延时常数 #define BUZ_DELAY 80 code uint8 Ledcode[13]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf,0x86}; uint8 Led_n=0; //co为0,f9为1,类推 uint8 Led_buf[6]; //定义Led_buf[6]数? float Tmp1=0, Tmp2=0; //用于存储输入的两个变量 int8 C_flag=0; /* * 延时 */ void delay(uint16 n) { while (n--); } /* * 蜂鸣器发声 */ void buzzer_sound(void) { uint16 i; for (i=0; i BUZZ = ~BUZZ; //BUZZ初始状态为高电平,蜂鸣器熄灭 delay(100); } BUZZ = 1; } /* * 按键扫描 */ int8 scan_key(void) { int8 val=-1; //此处未初始化val,val为按键的标志位 //当没有按键时,val的值为-1 KeyOut1 = 0; KeyOut2 = 1; KeyOut3 = 1; KeyOut4 = 1; if (KeyIn1 == 0) { delay(KEY_DELAY); if (KeyIn1 == 0) val = 1; } if (KeyIn2 == 0) { delay(KEY_DELAY); if (KeyIn2 == 0) val = 2; } if (KeyIn3 == 0) { delay(KEY_DELAY); if (KeyIn3 == 0) val = 3; } if (KeyIn4 == 0) { delay(KEY_DELAY); if (KeyIn4 == 0) val = FADD; //FADD此处为10 } while ((KeyIn1 == 0)||(KeyIn2 == 0)||(KeyIn3 == 0)||(KeyIn4 == 0)); /*此处只要有一个按键被按下,就在此处循环*/ KeyOut1 = 1; KeyOut2 = 0; KeyOut3 = 1; KeyOut4 = 1; if (KeyIn1 == 0) { delay(KEY_DELAY); //KEY_DELAY为300 if (KeyIn1 == 0) val = 4; } if (KeyIn2 == 0) { delay(KEY_DELAY); if (KeyIn2 == 0) val = 5; } if (KeyIn3 == 0) { delay(KEY_DELAY); if (KeyIn3 == 0) val = 6; } if (KeyIn4 == 0) { delay(KEY_DELAY); if (KeyIn4 == 0) val = FSUB; //此处FSUB为11 } while ((KeyIn1 == 0)||(KeyIn2 == 0)||(KeyIn3 == 0)||(KeyIn4 == 0)); /*此处只要有一个按键被按下,就在此处循环*/ KeyOut1 = 1; KeyOut2 = 1; KeyOut3 = 0; KeyOut4 = 1; if (KeyIn1 == 0) { delay(KEY_DELAY); if (KeyIn1 == 0) val = 7; } if (KeyIn2 == 0) { delay(KEY_DELAY); if (KeyIn2 == 0) val = 8; } if (KeyIn3 == 0) { delay(KEY_DELAY); if (KeyIn3 == 0) val = 9; } if (KeyIn4 == 0) { delay(KEY_DELAY); if (KeyIn4 == 0) val = FMUL; //此处FMUL为12 } while ((KeyIn1 == 0)||(KeyIn2 == 0)||(KeyIn3 == 0)||(KeyIn4 == 0)); KeyOut1 = 1; KeyOut2 = 1; KeyOut3 = 1; KeyOut4 = 0; if (KeyIn1 == 0) { delay(KEY_DELAY); if (KeyIn1 == 0) val = 0; } if (KeyIn2 == 0) { delay(KEY_DELAY); if (KeyIn2 == 0) val = FRES; //FRES 14 } if (KeyIn3 == 0) { delay(KEY_DELAY); if (KeyIn3 == 0) val = FEQU; //FEQU 15 } if (KeyIn4 == 0) { delay(KEY_DELAY); if (KeyIn4 == 0) val = FDIV; //此处FDIV为13 } while ((KeyIn1 == 0)||(KeyIn2 == 0)||(KeyIn3 == 0)||(KeyIn4 == 0)); if (val > 0) // 此处为当有按键按下时,蜂鸣器响起,根据val的值判断 buzzer_sound(); return val; } /* * 验证数据有效性 */ bit check_num(float f_num) { if (f_num >= 100000) return 1; return 0; //返回值为位0 } /* * 制作数码管错误标志 */ void make_led_error(void) { int8 i; for (i=0; i<5; i++) Led_buf[i] = Ledcode[10]; //Ledcode[10]为0xf为小灯全部熄灭 Led_buf[5] = Ledcode[12]; //Ledcode[12]为0x86此处为字符E } /* * 制作数码管整数数据 */ void make_led_inumber(int32 i_num) //函数参数传递i_num的值为0 { bit s_flag=0; int16 sit; int8 i; if (i_num < 0) { s_flag = 1; i_num = -i_num; } ET0 = 0; //禁止T0溢出中断 for (i=4, sit=10000; i>=1; i--, sit/=10) //当sit为1 { if (i_num >= sit) break; Led_buf[i] = Ledcode[10]; //Ledcode[10]为0xf为小灯全部熄灭 i_num -= i_num/sit*sit; } for (;i>=1; i--, sit/=10) { Led_buf[i] = Ledcode[i_num/sit]; i_num -= i_num/sit*sit; } Led_buf[0] = Ledcode[i_num] & 0x7F; if (s_flag) Led_buf[5] = Ledcode[11]; else Led_buf[5] = Ledcode[10]; ET0 = 1; } /* * 制作数码管浮点数据 */ void make_led_fnumber(float f_num) { bit s_flag=0; int32 num; int16 sit; int8 i, decimal, dot_sit=0; if (f_num < 0) { s_flag = 1; //如果计算结果f_num <0 ; 则s_flag的值则为1 f_num = -f_num; //把f_num的值按整数计算 } num = (int32)(f_num*10000+0.5); //把计算结果乘以10000,再加0.5,然后强制取整 for (decimal=4; decimal>0; decimal--) //对于10取余,直到余数不等于0,跳出循环体 { if (num % 10 != 0) break; num /= 10; } dot_sit = decimal; // decimal为小数点位数 if (f_num >= 10000) //如果f_num的值大于10000,怎小数点位数为0 dot_sit = 0; else if (f_num >= 1000) //如果此数大于1000,且小数点位数多于以为,则取一位小数 if (decimal >= 1) //因为数码管的显示范围 dot_sit = 1; else if (f_num >= 100) if (decimal >= 2) dot_sit = 2; else if (f_num >= 10) if (decimal >= 3) dot_sit = 3; for (i=0; i num = (int32)(f_num+0.5); ET0 = 0; //禁止T0溢出中断 /* 此分为两步分别讨论 1 第一步,把此数用不到的各位的数码管分别熄灭 2 第二步,把有数位分别赋值到数码管上去 */ for (i=4, sit=10000; i>=1; i--, sit/=10) { if (num >= sit) break; //如果此数大于10000,或者小数点位数为4位,则跳出,同理 if (i == dot_sit) break; Led_buf[i] = Ledcode[10]; //Ledcode[10]为0xf为小灯全部熄灭 num -= num/sit*sit; //此处为不断的获取书num上以后各位的数值大小 } /*此处的for语句用于不断的给数组Led_buf[i]赋上计算结果的各位*/ for (;i>=1; i--, sit/=10) { Led_buf[i] = Ledcode[num/sit]; //利用Ledcode[]直接给Led_buf[i]依此赋值 num -= num/sit*sit; //此处为不断的获取书num上以后各位的数值大小 } Led_buf[0] = Ledcode[num]; //赋上个位的数值 Led_buf[dot_sit] &= 0x7F; //与上0111,1111,点亮小数点 if (s_flag) Led_buf[5] = Ledcode[11]; //如果计算结果小于0,则Led_buf[5]则为0xbf为“-” else Led_buf[5] = Ledcode[10]; //Ledcode[10]为0xff为小灯全部熄灭 ,不显示 ET0 = 1; //允许T0溢出中断 } /* * 数码管显示 */ void show_num(uint8 *buf) { ENLED = 1; switch (Led_n) { case 0: ADDR0 = 0; ADDR1 = 0; ADDR2 = 0; P0 = buf[0]; break; case 1: ADDR0 = 1; ADDR1 = 0; ADDR2 = 0; P0 = buf[1]; break; case 2: ADDR0 = 0; ADDR1 = 1; ADDR2 = 0; P0 = buf[2]; break; case 3: ADDR0 = 1; ADDR1 = 1; ADDR2 = 0; P0 = buf[3]; break; case 4: ADDR0 = 0; ADDR1 = 0; ADDR2 = 1; P0 = buf[4]; break; case 5: ADDR0 = 1; ADDR1 = 0; ADDR2 = 1; P0 = buf[5]; break; } ENLED = 0; if (Led_n >= 5) Led_n = 0; else Led_n++; } /* * 计算程序 */ void calculate(int8 key_val) //键盘输入的按键标识符key_val { float ans; bit err=0; if ((key_val >= FADD) && (key_val <= FDIV)) //判断输入的值是否为运算符 { C_flag = key_val; //如果运算符是四则运算符,则C_flag的值等于key_val } else if (key_val == FEQU) //FEQU为等于号 { switch (C_flag) { case FADD: ans = Tmp1+Tmp2; break; //ans为浮点数值 case FSUB: ans = Tmp1-Tmp2; break; case FMUL: ans = Tmp1*Tmp2; break; case FDIV: if (Tmp2 == 0) { err = 1; //如果输入除数为零,则错误 break; } else { ans = Tmp1/Tmp2; break; } } if (check_num(ans)) //如果数据发生溢出,则报错 err = 1; if (err) make_led_error(); //如果发生错误,则显示错误 else make_led_fnumber(ans); C_flag = 0; Tmp1 = 0; Tmp2 = 0; } //此处与第一个if语句相对应 else if (key_val == FRES) //如果按下复位键 { make_led_fnumber(0); C_flag = 0; Tmp1 = 0; Tmp2 = 0; } else { if (C_flag == 0) { ans = Tmp1; ans *= 10; ans += key_val; if (check_num(ans)) return; else Tmp1 = ans; make_led_inumber(Tmp1); } else { ans = Tmp2; ans *= 10; ans += key_val; if (check_num(ans)) return; else Tmp2 = ans; make_led_inumber(Tmp2); //制作数码管整数数据 } } } /*此处为主函数*/ main() { int8 key_val; ADDR3 = 1; ENLED = 0; make_led_inumber(0); // 在按键之前先显示制作数码管整数数据 TMOD = 0x01; //使用T0的16为定时器方式 TH0 = 0xF8; //使用T0的时间为1.84sec TL0 = 0xCC; TR0 = 1; //启动定时器T0 ET0 = 1; //允许定时器T0溢出中断 EA = 1; //打开中断总开关,允许中断 while (1) { key_val = scan_key(); //根据val,确定按键的值 if (key_val == -1) continue; calculate(key_val); //计算数值 } } void time0() interrupt 1 //中断程序使用定时器T0 { TR0 = 0; TH0 = 0xF8; TL0 = 0xCC; show_num(Led_buf); TR0 = 1; } |
|
相关推荐
6个回答
|
|
自己顶自己一下吧!,希望大家多踊跃啊!
|
|
|
|
全局变量,就像RAM,不掉电就一直存着,下次运算继续使用,所以刚开始,他初始化为0
|
|
|
|
|
|
|
|
|
|
|
|
Tmp1 = ans;
|
|
|
|
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
464 浏览 0 评论
478 浏览 1 评论
基于瑞萨FPB-RA4E2智能床头灯项目——1编译环境搭建与点亮驱动ws2812全彩LED
439 浏览 0 评论
嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-LCD显示图片编程示例之介绍mmap
994 浏览 0 评论
《DNESP32S3使用指南-IDF版_V1.6》第二章 常用的C语言知识点
1056 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
11793 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-26 00:40 , Processed in 0.713642 second(s), Total 81, Slave 64 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号