1、定时显示
开辟一显示缓冲区,显示中断程序定时读取缓冲区显示各灯位,每灯位显示2.5ms,显示4只灯需要10ms,也就是显示的刷新频率是100Hz,亮度为25%。这样既保证亮度又不闪烁,同时CPU还有足够时间做其他事情。
2、键盘中断扫描
利用键盘中断扫描程序,读出按键的键码,存入键盘缓冲区,供主程序读区。
3、计算器的主程序读取键盘缓冲区的键码,驱动计算器的运行,计算器的运行过程要清晰明了;
4、计算中需要十进制与十六进制(或二进制)转化。
#define LED_seg XBYTE[0x6000] //段码地址 #define LED_light XBYTE[0x8000] //灯位地址 #include "reg51.h" #include "absacc.h" unsigned char read_key(unsigned char); unsigned char display(unsigned char,unsigned char); void delay(unsigned int); unsigned char light[4]={0xfe,0xfd,0xfb,0xf7}; //扫描值 灯位码 unsigned char seg[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //段码 unsigned char disp_buffer[5]={1,0,0,0,0}; //当前灯位、 显示区 unsigned char key_buffer[2]={0,0xff}; //缓冲区满标志、键码 void main() { Unsigned char temp[5]; unsigned char i; unsigned char operator=0; unsigned int tempa,tempb; bit first=1; TMOD=0x01; //置T0为方式1 TL0=0x0; //延时2.5mS的定时器初始值 TH0=0xf7; //赋初值 PT0=1; //定时中断0优先设置 TR0=1; //启动定时 ET0=1; //允许定时 IT1=0; //电平触发低电平有效 EX1=1; //允许外中断 PX1=1; // 外部中断1优先级设定 EA=1; //中断总允许 while(1) { P1=0xf0; //扫描 if (key_buffer[0]) { switch(key_buffer[1]) //缓冲区满 { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: if (first) for(i=1;i<=4;i++) //保存数据,等待另一个数据输入 { temp[i]=disp_buffer[i]; disp_buffer[i]=0; } first=0; for(i=1;i<=3;i++) disp_buffer[i]=disp_buffer[i+1]; disp_buffer[4]=key_buffer[1]; break; case 10: case 11: case 12: case 13: case 14: first=1;
tempa=1000*disp_buffer[1]+100*disp_buffer[2]+10*disp_buffer[3]+disp_buffer[4]; tempb=1000*temp[1]+100*temp[2]+10*temp[3]+temp[4]; switch(operator) { case 10:tempa+=tempb; break; case 11:tempa=tempb-tempa; break; case 12:tempa*=tempb; break; case 13:tempa=tempb/tempa; } tempa%=10000; disp_buffer[1]=tempa/1000; tempa%=1000; disp_buffer[2]=tempa/100; tempa%=100; disp_buffer[3]=tempa/10; disp_buffer[4]=tempa%10; operator=key_buffer[1]; break; case 15: for(i=1;i<=4;i++) disp_buffer[i]=temp[i]=0; first=1; operator=0; } key_buffer[0]=0; //缓冲区空 } } } void disp_LED() interrupt 1 { TL0=0x0; //延时2.5mS的定时器初始值 TH0=0xf7; if (disp_buffer[0]==5) disp_buffer[0]=1; display(disp_buffer[disp_buffer[0]],disp_buffer[0]); disp_buffer[0]++; } void get_keypad_code() interrupt 2 { unsigned char i,key; EA=0; for (i=0;i<=3;i++) { key=read_key(light[i]); //读键码 if (key!=0xff) delay(10); //延时5-10ms,去抖动 if (read_key(light[i])!=key) key=0xff; //读键码比较 if (key!=0xff) { key_buffer[0]=1; //缓冲区满 key_buffer[1]=key; //键码 } } EA=1; } unsigned char read_key(unsigned char scan) { P1=scan; //扫描 switch(P1) //返回扫描码->键码 { case 0x77:return(0x7); case 0xb7:return(0x8); case 0xd7:return(0x9); case 0xe7:return(0xd); case 0x7b:return(0x4); case 0xbb:return(0x5); case 0xdb:return(0x6); case 0xeb:return(0xc); case 0x7d:return(0x1); case 0xbd:return(0x2); case 0xdd:return(0x3); case 0xed:return(0xb); case 0x7e:return(0xf); case 0xbe:return(0x0); case 0xde:return(0xe); case 0xee:return(0xa); default: return(0xff); } } unsigned char display(unsigned char disp_key,unsigned char n) //disp_key 显示字符,n 灯位 { if ((n<=4)&&(n>=1)) LED_light=light[n-1]; else LED_light=0xff; if ((disp_key>=0)&&(disp_key<=16)) LED_seg=seg[disp_key]; else LED_seg=0x00; return light[n-1]; } void delay(unsigned int k) //延时k*1ms { unsigned int i,j; for (j=0;j<=k;j++) for(i=0;i<=1085;i++); }
上一篇:自制51单片机超大数码管时钟
下一篇:STC自动下载器
推荐阅读最新更新时间:2024-03-16 13:04
设计资源 培训 开发板 精华推荐
- Allegro MicroSystems 在 2024 年德国慕尼黑电子展上推出先进的磁性和电感式位置感测解决方案
- 左手车钥匙,右手活体检测雷达,UWB上车势在必行!
- 狂飙十年,国产CIS挤上牌桌
- 神盾短刀电池+雷神EM-i超级电混,吉利新能源甩出了两张“王炸”
- 浅谈功能安全之故障(fault),错误(error),失效(failure)
- 智能汽车2.0周期,这几大核心产业链迎来重大机会!
- 美日研发新型电池,宁德时代面临挑战?中国新能源电池产业如何应对?
- Rambus推出业界首款HBM 4控制器IP:背后有哪些技术细节?
- 村田推出高精度汽车用6轴惯性传感器
- 福特获得预充电报警专利 有助于节约成本和应对紧急情况