51单片机简易计算器程序
- 格式:docx
- 大小:18.40 KB
- 文档页数:11
51单片机外部脉冲计数程序51单片机外部脉冲计数程序是一种常见的嵌入式应用程序,它可以通过计数外部脉冲信号来实现各种功能,如测量速度、记录行程、控制电机等。
在本文中,我们将介绍如何编写一个简单的51单片机外部脉冲计数程序,供初学者参考。
一、程序框架```c#include <reg52.h>sbit PulsePin = P1^0; //定义脉冲信号输入引脚unsigned long cnt = 0; //计数器void ExternalInterrupt0() interrupt 0 //外部中断0的中断服务程序{cnt++; //计数器加一}```程序中定义了一个脉冲信号输入引脚PulsePin,一个计数器cnt,并在主程序中开启了全局中断和外部中断0,并设置外部中断0为下降沿触发。
在外部中断0的中断服务程序中,计数器cnt会加一。
二、程序解析1. 硬件连接将需要计数的脉冲信号输入引脚连接到单片机的P1.0引脚上,并连接好单片机的电源和地线。
2. 宏定义和全局变量首先定义了PulsePin引脚为输入模式,并定义了计数器cnt为无符号长整型变量。
3. 主程序在主程序中,首先开启了全局中断和外部中断0,然后设置外部中断0为下降沿触发。
最后加入一个无限循环,等待外部中断的触发。
4. 外部中断0的中断服务程序在外部中断0的中断服务程序中,计数器cnt会加一。
三、总结本文介绍了如何编写一个简单的51单片机外部脉冲计数程序。
通过外部中断0的中断服务程序,可以实现对外部脉冲信号的计数。
本程序只是一个简单的例子,读者可以根据自己的需求对其进行改进和优化。
#include <reg51.h>#include <intrins.h>unsigned char data digit;unsigned char data index;unsigned char data buf[16];unsigned char code table[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};unsigned int temp_dat;unsigned long int temp1,temp2,temp;unsigned int flag,flag1,key_times,key_flag,key_temp;unsigned char key_scan();void delay(void);void key_proc();void sys_init();void dis_result();void dis_init();void result_proc();void start_proc();void dat_proc(unsigned int key_dat);void char_proc(unsigned char i);void delayms(unsigned char ms);void main(){sys_init();while(1){key_proc();dis_result();}}void sys_init(){P0=0xff;P2=0x00;TMOD=0x01;TH0=0xfc;TL0=0x17;digit=0x00;index=0;temp=0;temp1=0;temp2=0;flag=0;key_times=0;temp_dat=0;key_flag=0;key_temp=0;dis_init();IE=0x82;TR0=1;}void dis_init(){buf[0]=table[10];buf[1]=table[10];buf[2]=table[10];buf[3]=table[10];buf[4]=table[10];buf[5]=table[10];buf[6]=table[10];buf[7]=table[10];buf[8]=table[10];buf[9]=table[10];buf[10]=table[10];buf[11]=table[10];buf[12]=table[10];buf[13]=table[10];buf[14]=table[10];buf[15]=table[10];}void dis_result(){if((temp<=4294967295)&&(temp>999999999)) {buf[0]=table[10];buf[1]=table[10];buf[2]=table[10];buf[3]=table[10];buf[4]=table[10];buf[5]=table[10];buf[6]=table[temp/1000000000];buf[7]=table[(temp%1000000000)/100000000];buf[8]=table[((temp%1000000000)%100000000)/10000000];buf[9]=table[(((temp%1000000000)%100000000)%10000000)/1000000];buf[10]=table[((((temp%1000000000)%100000000)%10000000)%1000000)/100000];buf[11]=table[(((((temp%1000000000)%100000000)%10000000)%1000000)%100000)/10000];buf[12]=table[((((((temp%1000000000)%100000000)%10000000)%1000000)%100000)%10000) /1000];buf[13]=table[(((((((temp%1000000000)%100000000)%10000000)%1000000)%100000)%10000 )%1000)/100];buf[14]=table[((((((((temp%1000000000)%100000000)%10000000)%1000000)%100000)%1000 0)%1000)%100)/10];buf[15]=table[((((((((temp%1000000000)%100000000)%10000000)%1000000)%100000)%1000 0)%1000)%100)%10];}if((temp<=999999999)&&(temp>99999999)){buf[0]=table[10];buf[1]=table[10];buf[2]=table[10];buf[3]=table[10];buf[4]=table[10];buf[5]=table[10];buf[6]=table[10];buf[7]=table[temp/100000000];buf[8]=table[(temp%100000000)/10000000];buf[9]=table[((temp%100000000)%10000000)/1000000];buf[10]=table[(((temp%100000000)%10000000)%1000000)/100000];buf[11]=table[((((temp%100000000)%10000000)%1000000)%100000)/10000];buf[12]=table[(((((temp%100000000)%10000000)%1000000)%100000)%10000)/1000]; buf[13]=table[((((((temp%100000000)%10000000)%1000000)%100000)%10000)%1000)/100];buf[14]=table[(((((((temp%100000000)%10000000)%1000000)%100000)%10000)%1000)%100) /10];buf[15]=table[(((((((temp%100000000)%10000000)%1000000)%100000)%10000)%1000)%100) %10];}if((temp<=99999999)&&(temp>9999999)){buf[0]=table[10];buf[1]=table[10];buf[2]=table[10];buf[3]=table[10];buf[4]=table[10];buf[5]=table[10];buf[6]=table[10];buf[7]=table[10];buf[8]=table[temp/10000000];buf[9]=table[(temp%10000000)/1000000];buf[10]=table[((temp%10000000)%1000000)/100000];buf[11]=table[(((temp%10000000)%1000000)%100000)/10000];buf[12]=table[((((temp%10000000)%1000000)%100000)%10000)/1000];buf[13]=table[(((((temp%10000000)%1000000)%100000)%10000)%1000)/100];buf[14]=table[((((((temp%10000000)%1000000)%100000)%10000)%1000)%100)/10];buf[15]=table[((((((temp%10000000)%1000000)%100000)%10000)%1000)%100)%10];}if((temp<=9999999)&&(temp>999999)){buf[0]=table[10];buf[1]=table[10];buf[2]=table[10];buf[3]=table[10];buf[4]=table[10];buf[5]=table[10];buf[6]=table[10];buf[7]=table[10];buf[8]=table[10];buf[9]=table[temp/1000000];buf[10]=table[(temp%1000000)/100000];buf[11]=table[((temp%1000000)%100000)/10000];buf[12]=table[(((temp%1000000)%100000)%10000)/1000];buf[13]=table[((((temp%1000000)%100000)%10000)%1000)/100];buf[14]=table[(((((temp%1000000)%100000)%10000)%1000)%100)/10];buf[15]=table[(((((temp%1000000)%100000)%10000)%1000)%100)%10];}if((temp<=999999)&&(temp>99999)){buf[0]=table[10];buf[2]=table[10];buf[3]=table[10];buf[4]=table[10];buf[5]=table[10];buf[6]=table[10];buf[7]=table[10];buf[8]=table[10];buf[9]=table[10];buf[10]=table[temp/100000];buf[11]=table[(temp%100000)/10000];buf[12]=table[((temp%100000)%10000)/1000];buf[13]=table[(((temp%100000)%10000)%1000)/100];buf[14]=table[((((temp%100000)%10000)%1000)%100)/10];buf[15]=table[((((temp%100000)%10000)%1000)%100)%10]; }if((temp<=99999)&&(temp>9999)){buf[0]=table[10];buf[1]=table[10];buf[2]=table[10];buf[3]=table[10];buf[4]=table[10];buf[5]=table[10];buf[6]=table[10];buf[7]=table[10];buf[8]=table[10];buf[9]=table[10];buf[10]=table[10];buf[11]=table[temp/10000];buf[12]=table[(temp%10000)/1000];buf[13]=table[((temp%10000)%1000)/100];buf[14]=table[(((temp%10000)%1000)%100)/10];buf[15]=table[(((temp%10000)%1000)%100)%10];}else if((temp<=9999)&&(temp>999)){buf[0]=table[10];buf[1]=table[10];buf[2]=table[10];buf[3]=table[10];buf[4]=table[10];buf[5]=table[10];buf[7]=table[10];buf[8]=table[10];buf[9]=table[10];buf[10]=table[10];buf[11]=table[10];buf[12]=table[temp/1000];buf[13]=table[(temp%1000)/100];buf[14]=table[((temp%1000)%100)/10];buf[15]=table[((temp%1000)%100)%10]; }else if((temp<=999)&&(temp>99)){buf[0]=table[10];buf[1]=table[10];buf[2]=table[10];buf[3]=table[10];buf[4]=table[10];buf[5]=table[10];buf[6]=table[10];buf[7]=table[10];buf[8]=table[10];buf[9]=table[10];buf[10]=table[10];buf[11]=table[10];buf[12]=table[10];buf[13]=table[temp/100];buf[14]=table[(temp%100)/10];buf[15]=table[(temp%100)%10];}else if((temp<=99)&&(temp>9)){buf[0]=table[10];buf[1]=table[10];buf[2]=table[10];buf[3]=table[10];buf[4]=table[10];buf[5]=table[10];buf[6]=table[10];buf[7]=table[10];buf[8]=table[10];buf[9]=table[10];buf[10]=table[10];buf[11]=table[10];buf[13]=table[10];buf[14]=table[temp/10];buf[15]=table[temp%10];}else if(temp<=9){buf[0]=table[10];buf[1]=table[10];buf[2]=table[10];buf[3]=table[10];buf[4]=table[10];buf[5]=table[10];buf[6]=table[10];buf[7]=table[10];buf[8]=table[10];buf[9]=table[10];buf[10]=table[10];buf[11]=table[10];buf[12]=table[10];buf[13]=table[10];buf[14]=table[10];buf[15]=table[temp];}}unsigned char key_scan(){unsigned char code_h,code_l;P1=0xf0;if((P1&0xf0)!=0xf0){delayms(2);if((P1&0xf0)!=0xf0) //两次判断,确认有键按下{code_h=0xfe; //低四位为行地址,对每一行进行扫描,即将每一行依次赋值0while((code_h&0x10)!=0x00){P1=code_h;if((P1&0xf0)!=0xf0){code_l=(P1&0xf0|0x0f);return((~code_h)+(~code_l)); //取反之后,高四位与低四位都只有一个1,相加不会进位}elsecode_h=((code_h<<1)|0x01); //依次进行扫描}}}return(0);}void key_proc(){unsigned char key_value;key_value=key_scan();switch(key_value){case 0x18: dat_proc(7);break; //7case 0x28: dat_proc(4);break; //4case 0x48: dat_proc(1);break; //1case 0x14: dat_proc(8);break; //8case 0x24: dat_proc(5);break; //5case 0x44: dat_proc(2);break; //2case 0x84: dat_proc(0);break; //0case 0x12: dat_proc(9);break; //9case 0x22: dat_proc(6);break; //6case 0x42: dat_proc(3);break; //3case 0x82: result_proc();break; //=case 0x11: char_proc(4);break; ///case 0x21: char_proc(3);break; //*case 0x41: char_proc(2);break; //-case 0x81: char_proc(1);break; //+case 0x88: start_proc();break; //ondefault :break;}}void dat_proc(unsigned int key_dat){if(key_times==0)temp=key_dat;else{if(flag==0)temp=(temp1*10+key_dat);else if(flag==1)temp=(temp2*10+key_dat);}if(flag==0)temp1=temp;else if(flag==1)temp2=temp;delayms(200);key_times++;}void char_proc(unsigned char i){key_times=0;key_flag=i;if(temp==0)flag=0;else{flag=1;}}void result_proc(){unsigned char flag_value;flag_value=key_flag;switch(flag_value){case 1: temp=(temp1+temp2);break;case 2: temp=(temp1-temp2);break;case 3: temp=(temp1*temp2);break;case 4: temp=(temp1/temp2);break;}key_times=0;flag=0;}void start_proc(){temp=0;temp1=0;temp2=0;flag=0;key_times=0;temp_dat=0;key_flag=0;}void time0() interrupt 1 using 2 {TH0=0xfc;TL0=0x17;P2=0x00;P0=buf[index];P2=digit;digit=digit++;index++;index&=0x0f;}void delayms(unsigned char ms) {unsigned char i;while(ms--){for(i = 0; i < 120; i++);}}D0D1D2D3D4D5D6D7P3.1Q1CSDAQ2INT1Q3LCDENQ4WRQ6RDQ7Q0Q5Q4Q7Q5Q6Q 3Q 0Q 1Q 2D 0D 7D 6D 5D 4D 3D 2D 1W 0W 1W 2W 3W 4W 5W 6W 7D 0D 1D 2D 3D 4D 5D 6D 7W 8W 10W 11W 12W 13W 14W 15W 9W0W1W2W3W4W5W6W7W8W9W10W11W12W13W14W15XTAL218XTAL119ALE 30EA31PSEN 29RST9P0.0/AD039P0.1/AD138P0.2/AD237P0.3/AD336P0.4/AD435P0.5/AD534P0.6/AD633P0.7/AD732P1.0/T21P1.1/T2EX 2P1.23P1.34P1.45P1.56P1.67P1.78P3.0/RXD 10P3.1/TXD 11P3.2/INT012P3.3/INT113P3.4/T014P3.7/RD17P3.6/WR 16P3.5/T115P2.7/A1528P2.0/A821P2.1/A922P2.2/A1023P2.3/A1124P2.4/A1225P2.5/A1326P2.6/A1427U3AT89C52234567891RP1RESPACK-812365489=7+CONABCD1243A 1B 2C3E16E24E35Y015Y114Y213Y312Y411Y510Y69Y77U174HC138A 1B 2C3E16E24E35Y015Y114Y213Y312Y411Y510Y69Y77U274HC138U4NOTU5NOTU6NOTU7NOTU8NOTU9NOTU10NOTU11NOTU12NOTU13NOTU14NOTU15NOTU16NOTU17NOTU19NOTU20NOTU22NOT。
#include <reg52.h>#include <intrins.h>#include <math.h>#define uchar unsigned char#define uint unsigned intsbit LCD_RS=P2^2;//数据和命令端sbit LCD_EN=P2^0;//使能端sbit LCD_RW=P2^1;sbit CS1=P2^4;sbit CS2=P2^3;uint keytime,keyno[10];uint result,date1,date2,w_date1,w_date2;uint KeyNO1,opercha;uint date10n;uint date10n_d[16];uchar code hz[]={/*-- 文字: 数--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x10,0x92,0x54,0x38,0xFF,0x38,0x54,0x52,0x80,0xF0,0x1F,0x12,0x10,0xF0,0x10,0x00,0x42,0x42,0x2A,0x2E,0x13,0x1A,0x26,0x02,0x40,0x20,0x13,0x0C,0x33,0x60,0x20,0x00,/*-- 文字: 据--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x08,0x08,0x08,0xFF,0x88,0x40,0xFE,0x92,0x92,0x92,0xF2,0x92,0x92,0x9E,0x80,0x00,0x02,0x42,0x81,0x7F,0x40,0x30,0x0F,0xFC,0x44,0x44,0x47,0x44,0x44,0xFC,0x00,0x00,/*-- 文字: 结--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x20,0x30,0xAC,0x63,0x10,0x00,0x08,0x48,0x48,0x48,0x7F,0x48,0x48,0x48,0x08,0x00,0x22,0x23,0x22,0x12,0x12,0x00,0x00,0x7E,0x22,0x22,0x22,0x22,0x22,0x7E,0x00,0x00,/*-- 文字: 果--*//*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/0x00,0x00,0x00,0x3E,0x2A,0x2A,0x2A,0xFE,0x2A,0x2A,0x2A,0x3E,0x00,0x00,0x00,0x00,0x21,0x21,0x11,0x11,0x09,0x05,0x03,0xFF,0x03,0x05,0x09,0x09,0x11,0x31,0x11,0x00};uchar code sz[]={0x00,0x00,0xF0,0xF8,0x08,0x68,0xF8,0xF0,0x00,0x00,0x07,0x0F,0x0B,0x08,0x0F,0x07, //0 0x00,0x20,0x20,0x30,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x00,0x00, //1 0x00,0x30,0x38,0x08,0x88,0xF8,0x70,0x00,0x00,0x0C,0x0E,0x0B,0x09,0x08,0x08,0x00, //2 0x00,0x30,0x38,0x88,0x88,0xF8,0x70,0x00,0x00,0x06,0x0E,0x08,0x08,0x0F,0x07,0x00, //3 0x00,0x00,0xF8,0xF8,0x00,0xE0,0xE0,0x00,0x00,0x03,0x03,0x02,0x02,0x0F,0x0F,0x02, //4 0x00,0xF8,0xF8,0x88,0x88,0x88,0x08,0x00,0x00,0x08,0x08,0x08,0x0C,0x07,0x03,0x00, //5 0x00,0xC0,0xE0,0x78,0x58,0xC8,0x80,0x00,0x00,0x07,0x0F,0x08,0x08,0x0F,0x07,0x00, //6 0x00,0x08,0x08,0x88,0xE8,0x78,0x18,0x00,0x00,0x00,0x0E,0x0F,0x01,0x00,0x00,0x00, //7 0x00,0x70,0xF8,0xC8,0x88,0xF8,0x70,0x00,0x00,0x07,0x0F,0x08,0x09,0x0F,0x07,0x00, //8 0x00,0xF0,0xF8,0x08,0x08,0xF8,0xF0,0x00,0x00,0x00,0x09,0x0D,0x0F,0x03,0x01,0x00, //90x00,0x00,0x00,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x0C,0x0C,0x0C,0x00,0x00, //: 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x0C,0x0C,0x00,0x00//.};/*******************************名称:delay()输入:延时数输出: 无功能:延时********************************/void delay(uint x){int y,z;for(y=x;y>0;y--)for (z=120;z>0;z--);}void write_c(uchar c) //写指令端{LCD_RW=0;LCD_RS=0;LCD_EN=1;P0=c;LCD_EN=0;delay(1);LCD_EN=1;}void write_d(uchar d)//写数据{LCD_RW=0;LCD_RS=1;LCD_EN=1;P0=d;LCD_EN=0;delay(1);LCD_EN=1;}void pianxuan(screen) //片选{switch(screen){case 0:CS1=0;CS2=0;break;case 1:CS1=1;CS2=0;break;case 2:CS1=0;CS2=1;break;case 3:CS1=1;CS2=1;break;}}void qinping(screen)//清屏,从第一行第一列开始{uint x,y; //页的设置位pianxuan(screen);//选择哪个清屏for(x=0xb8;x<0xc0;x++){write_c(x);//页初始值为0XB8到0xc0共八页write_c(0x40);//列的初始地址为0x40,共64列for(y=0;y<64;y++){write_d(0x00);//选择全部清屏}}}/*LCD显示汉字字库函数*/void lcd_display_hanzi(uchar screen,uchar page,uchar lie,uint mun) //screen:选择屏幕参数,page:选择页参数0-3,lie列参数0-3,mun:显示第几个汉字的参数{int i; //page页其实就是行,是行计数器页指针共九位计数器,高三位为X,低六位为Ymun=mun*32;pianxuan(screen) ; //片选看哪个段write_c(0x40+(lie*16)); //一个汉字占用两个字节write_c(0xb8+(page*2)); //一个字节显示for ( i=0;i<16;i++){write_d(hz[mun++]);}write_c(0x40+(lie*16));write_c(0xb8+(page*2)+1);for (i=0;i<16;i++){write_d(hz[mun++]);}}void lcd_display_shuzi(uchar screen,uchar page,uchar lie,uint mun) //screen:选择屏幕参数,page:选择页参数0-3,lie列参数0-3,mun:显示第几个汉字的参数{int i; //page页其实就是行,是行计数器页指针共九位计数器,高三位为X,低六位为Ymun=mun*16;pianxuan(screen) ; //片选看哪个段write_c(0x40+(lie*8)); //一个汉字占用两个字节write_c(0xb8+(page*2)); //一个字节显示for ( i=0;i<8;i++){write_d(sz[mun++]);}write_c(0x40+(lie*8));write_c(0xb8+(page*2)+1);for (i=0;i<8;i++){write_d(sz[mun++]);}}void LCD_init(){write_c(0x3f);// 显示开启write_c(0xc0); //显示起始行,从第一位开始,从0到63 write_c(0xb8);// 设置页得地址从0到7write_c(0x40); //设置列的地址,从第一位开始,从0到63 }/*******************************名称:GET_key()输入:无输出: 按键的相应数目功能:扫描按键********************************/uchar GET_key(){uchar Tmp,KeyNO;P1 = 0xf0;delay(1);Tmp = P1;switch(Tmp){case 0xe0: KeyNO = 3; break;case 0xd0: KeyNO = 2; break;case 0xb0: KeyNO = 1; break;case 0x70: KeyNO = 0;}P1 = 0x0f;delay(1);Tmp = P1;switch(Tmp){case 0x0e: KeyNO+= 12; break;case 0x0d: KeyNO+= 8; break;case 0x0b: KeyNO+= 4; break;case 0x07: KeyNO+= 0; break;default: break;}return(KeyNO);}void write_key(){uchar i,j,m,n;m = 7;n = 7;KeyNO1 = GET_key();if (KeyNO1>=0 && KeyNO1<=9){keytime++;}if (KeyNO1>=10 && KeyNO1<=13){/* keytime= keytime-1;for (j=keytime; j>=0;j--){if ((keytime-j) == 0)w_date1=keyno[keytime];else{for (k=0; k<keytime-j; k++){w_date1=keyno[keytime--]*10;}}date1=date1+w_date1;}*/keytime = 0;opercha = KeyNO1;}if (!(opercha>=10 && opercha<=13)){date1=0;if ((keytime-1) < 10 ){keyno[keytime-1] = KeyNO1;if (keytime-1>=0 && keytime-1 <= 7){for (i=keytime; i>0; i--){lcd_display_shuzi(1,0,m,keyno[i-1]);m--;if ((keytime-i) == 0){w_date1=keyno[i-1];}else{for (j=0; j<keytime-i; j++){w_date1=keyno[i-1]*10;}}date1=date1+w_date1;}}else{for (i=keytime-8; i>0; i--){lcd_display_shuzi(2,0,n,keyno[i-1]);n--;for (j=0; j<keytime-i; j++){w_date1=keyno[i-1]*10;}date1=date1+w_date1;}m=7;for (i=keytime; i>keytime-8; i--){lcd_display_shuzi(1,0,m,keyno[i-1]);m--;if ((keytime-i) == 0)w_date1=keyno[i-1];else{for (j=0; j<keytime-i; j++){w_date1=keyno[i-1]*10;}}date1=date1+w_date1;}}}}if ( (opercha>=10 && opercha<=13) && (KeyNO1 != 14) ) {date2=0;if ((keytime-1)<10 && (keytime-1)>=0){keyno[keytime-1] = KeyNO1;if (keytime-1 <= 7){for (i=keytime; i>0; i--){lcd_display_shuzi(1,1,m,keyno[i-1]);m--;if ((keytime-i) == 0)w_date2=keyno[i-1];else{for (j=0; j<keytime-i; j++){w_date2=keyno[i-1]*10;}}date2=date2+w_date2;}}else{for (i=keytime-8; i>0; i--){lcd_display_shuzi(2,1,n,keyno[i-1]);n--;for (j=0; j<keytime-i; j++){w_date1=keyno[i-1]*10;}date2=date2+w_date2;}m=7;for (i=keytime; i>keytime-8; i--){lcd_display_shuzi(1,1,m,keyno[i-1]);m--;if ((keytime-i) == 0)w_date2=keyno[i-1];else{for (j=0; j<keytime-i; j++){w_date2=keyno[i-1]*10;}}date2=date2+w_date2;}}}}/*if (KeyNO1 == 15){keytime= keytime-1;for (j=keytime; j>=0;j--){if ((keytime-j) == 0)w_date2=keyno[keytime];else{for (i=0; i<keytime-j; i++){w_date2=keyno[keytime--]*10;}}date2=date2+w_date2;}} */if (opercha>=10 && opercha<=13){m=7;if (KeyNO1 == 14){switch(opercha){case 10:result=date1+date2;break;case 11:result=date1-date2;break;case 12:result=date1*date2;break;case 13:result=date1/date2;break;default:break;}for (i=1; ;i++){date10n=1;for (j=0; j<i-1; j++){date10n=date10n*10;}date10n_d[i-1]=(result / date10n) % 10;if (date10n*10>result){j=i;break;}}P3=result / date10n;for (i=0;i<j;i++){lcd_display_shuzi(1,2,m,date10n_d[i]);m--;}/* lcd_display_shuzi(1,2,7,result);P3 =opercha; */}}}void main(){keytime=0;date1=0;date2=0;w_date1=0;w_date2=0;result=0;opercha=0;KeyNO1=16;date10n=1;LCD_init();qinping(0);lcd_display_hanzi(2,0,0,0); //LCD显示汉字"数" //screen:选择屏幕参数,page:选择页参数0-3,lie列参数0-3,mun:显示第几个汉字的参数lcd_display_hanzi(2,0,1,1); //LCD显示汉字"据"lcd_display_shuzi(2,0,4,1); //LCD显示数字"1"lcd_display_shuzi(2,0,5,10);//LCD显示符号":"lcd_display_hanzi(2,1,0,0); //LCD显示汉字"数"lcd_display_hanzi(2,1,1,1); //LCD显示汉字"据"lcd_display_shuzi(2,1,4,2); //LCD显示数字"2"lcd_display_shuzi(2,1,5,10);//LCD显示符号":"lcd_display_hanzi(2,2,0,2); //LCD显示汉字"结"lcd_display_hanzi(2,2,1,3); //LCD显示汉字"果"lcd_display_shuzi(2,2,4,10);//LCD显示符号":"while(1){P1 = 0x0f;if (P1 != 0x0f){delay(1);if (P1 != 0x0f){write_key();while (P1 != 0x0f);}}}}。
单片机双字节十六进制减法实验设计摘要本设计是基于51系列的单片机进行的双字节十六进制减法设计,可以完成计算器的键盘输入,进行加、减、3位无符号数字的简单运算,并在LED上相应的显示结果。
设计过程在硬件与软件方面进行同步设计。
硬件方面从功能考虑,首先选择内部存储资源丰富的AT89C51单片机,输入采用5个键盘。
显示采用3位7段共阴极LED动态显示。
软件方面从分析计算器功能、流程图设计,再到程序的编写进行系统设计。
编程语言方面从程序总体设计以及高效性和功能性对C语言和汇编语言进行比较分析,针对计算器四则运算算法特别是乘法和除法运算的实现,最终选用KEIL公司的μVision3软件,采用汇编语言进行编程,并用proteus 仿真。
引言十六进制减法计算器的原理与设计是单片机课程设计课题中的一个。
在完成理论学习和必要的实验后,我们掌握了单片机的基本原理以及编程和各种基本功能的应用,但对单片机的硬件实际应用设计和单片机完整的用户程序设计还不清楚,实际动手能力不够,因此对该课程进行一次课程设计是有必要的。
单片机课程设计既要让学生巩固课本学到的理论,还要让学生学习单片机硬件电路设计和用户程序设计,使所学的知识更深一层的理解,十进制加法计算器原理与硬软件的课程设计主要是通过学生独立设计方案并自己动手用计算机电路设计软件,编写和调试,最后仿真用户程序,来加深对单片机的认识,充分发挥学生的个人创新能力,并提高学生对单片机的兴趣,同时学习查阅资料、参考资料的方法。
关键词:单片机、计算器、AT89C51芯片、汇编语言、数码管、加减目录摘要 (01)引言 (01)一、设计任务和要求.............................1、1 设计要求1、2 性能指标1、3 设计方案的确定二、单片机简要原理.............................2、1 AT89C51的介绍2、2 单片机最小系统2、3 七段共阴极数码管三、硬件设计...................................3、1 键盘电路的设计3、2 显示电路的设计四、软件设计...................................4、1 系统设计4、2 显示电路的设计五、调试与仿真.................................5、1 Keil C51单片机软件开发系统5、2 proteus的操作六、心得体会....................................参考文献......................................... 附录1 系统硬件电路图............................ 附录2 程序清单..................................一、设计任务和要求1.1 设计要求本次课程设计,我选择的课题是单片机十进制加法计算器软硬件设计,设计任务为:设计一键盘显示装置,键盘上除需定义16个十六进制数字键外还要相应的功能键,其它键不定义无响应。
51单⽚机简易计算器设计-51单⽚机简易计算器课程设计⽬录⼀、设计任务和要求 (2)1、设计要求 (2)2、设计⽅案的确定 (2)⼆、硬件设计 (2)1、单⽚机最⼩系统 (2)2、键盘电路的设计 (3)3、显⽰电路的设计 (3)4、系统硬件电路图 (4)三、软件设计 (5)1 系统设计 (5)2 显⽰电路的设计 (6)3、程序清单 (8)四、调试与仿真 (14)五、试验箱实物图 (14)六、⼼得体会 (15)⼀、设计任务和要求1、设计要求利⽤单⽚机设计并制作简易计算器。
具体要求如下:1、4*4按键⽤于0~9的数字输⼊、加减乘除、等于、清零功能;2、能实现简单的加减乘除运算;3、输⼊数字及计算结果通过LED或LCD显⽰器显⽰。
2、设计⽅案的确定按照设计要求,本课题需要使⽤数码管显⽰和扩展4*4键盘,由于AT89C51芯⽚的I⼝不够多,⽽且为了硬件电路设计的简单化,故选择串⾏动态显⽰和⽤P1⼝扩展4*4键盘,扩展的4*4键盘定义⼗个数字键,六个功能键,使⽤串⾏动态显⽰显⽰运算结果。
主程序进⾏初始化,采⽤⾏列扫描进⾏查表得出键值,每次按键后调⽤显⽰⼦程序。
⼆、硬件设计简易数字计算器系统硬件设计主要包括:键盘电路,显⽰电路以及其他辅助电路。
下⾯分别进⾏设计。
1.单⽚机最⼩系统单⽚机最⼩系统就是⽀持主芯⽚正常⼯作的最⼩部分,包括主控芯⽚、复位电路和晶振电路。
(1)、复位电路复位电路本设计采⽤上电与⼿动复位电路,电阻分别选取100和10K,电容选取10uF,系统⼀上电,芯⽚就复位,或者中途按按键也可以进⾏复位。
(2)、晶振电路图三晶振电路晶振电路是单⽚机的⼼脏,它⽤于产⽣单⽚机⼯作所需要的时钟信号。
单⽚机的晶振选取11.0592MHz,晶振旁电容选取30pF。
2.键盘电路的设计键盘可分为两类:编码键盘和⾮编码键盘。
编码键盘是较多按键(20个以上)和专⽤驱动芯⽚的组合,当按下某个按键时,它能够处理按键抖动、连击等问题,直接输出按键的编码,⽆需系统软件⼲预。
51单片机做的简易计算器//by 河南大学电子信息06级金玉川//使用时应保证本计算器的输入数值与输出数值均不大于65536 数码管驱动芯片用的MAX7219,运算和键盘扫描用AT89S51 #include<at89x51.h>unsigned char key,temp;#define DIN P1_0 //串行数据输入引脚#define CLK P1_2 //同步时钟#define LOAD P1_1 //数据输入使能//--------10ms延时子程序-------------void delay10ms(unsigned char time){unsigned char a,b,c;for(a=0;a<time;a++)for(b=0;b<10;b++)for(c=0;c<120;c++);}//--------按键扫描子程序-------------//“1--9”号键的key值分别为1--9; “ +、-、*、/ ” 的key 值分别为13、14、15、16 //“ = ”的key 值为10//“on/c”的key值为11void KeyScan(void){P2=0xFF;P2_0=0;temp=P2;temp&=0xF0;if(temp !=0xF0){delay10ms(1);temp=P2;temp&=0xF0;if(temp !=0xF0){switch(temp){case 0xE0:key=7;break;case 0xd0:key=8;break;case 0xb0:key=9;break;case 0x70:key=16;break; //“除号”}}}P2=0xFF;P2_1=0;temp=P2;temp&=0xF0;if(temp !=0xF0)delay10ms(1);temp=P2;temp&=0xF0;if(temp !=0xF0){switch(temp){case 0xE0:key=4;break;case 0xd0:key=5;break;case 0xb0:key=6;break;case 0x70:key=15;break;//“乘号”}}}P2=0xFF;P2_2=0;temp=P2;temp&=0xF0;if(temp !=0xF0){delay10ms(1);temp=P2;temp&=0xF0;if(temp !=0xF0){switch(temp){case 0xE0:key=1;break;case 0xd0:key=2;break;case 0xb0:key=3;break;case 0x70:key=14;break;//减号}}P2=0xFF;P2_3=0;temp=P2;temp&=0xF0;if(temp !=0xF0){delay10ms(1);temp=P2;temp&=0xF0;if(temp !=0xF0){switch(temp){case 0xE0:key=11;break;//复位ON/Ccase 0xd0:key=10;break;//0case 0xb0:key=12;break;//等号case 0x70:key=13;break;//加号}}}}//-------数据发送子程序----------------void send(unsigned char addr,unsigned char dat) {unsigned char ADS,i,j;LOAD=0;i=0;while(i<16){if(i<8) ADS=addr;elseADS=dat;for(j=8;j>=1;j--){DIN=ADS&0x80;ADS<<=1;CLK=1;CLK=0;}i+=8;}LOAD=1;}//--------数据显示子程序--------------------void display(unsigned int n){unsigned char n2;unsigned char n3;unsigned char n4;unsigned char n5;if(n/10000==0&&(n%10000)/1000==0&&((n%10000)%1000)/100==0&&(((n%10000)%1000)%100)/10==0) //灭掉不必要的“0”{n2=0x0f;n3=0x0f;n4=0x0f;n5=0x0f;}else if(n/10000==0&&(n%10000)/1000==0&&((n%10000)%1000)/100==0&&(((n%10000)%1000)%100)/10!=0){n2=0x0f;n3=0x0f;n4=0x0f;n5=(((n%10000)%1000)%100)/10;}else if(n/10000==0&&(n%10000)/1000==0&&((n%10000)%1000)/100!=0){n2=0x0f;n3=0x0f;n4=((n%10000)%1000)/100;n5=(((n%10000)%1000)%100)/10;}else if(n/10000==0&&(n%10000)/1000!=0){n2=0x0f;n3=(n%10000)/1000;n4=((n%10000)%1000)/100;n5=(((n%10000)%1000)%100)/10;}else{n2=n/10000;n3=(n%10000)/1000;n4=((n%10000)%1000)/100;n5=(((n%10000)%1000)%100)/10;}send(0x0c,0x01); //掉电控制寄存器设置为正常操作send(0x0b,0x05); //扫描边界,显示前6位send(0x0a,0xf5); //亮度控制send(0x09,0xff); //译码方式send(0x01,0x0f); //最大显示结果65535;最高位不显示,灭零;send(0x02,n2);send(0x03,n3);send(0x04,n4);send(0x05,n5);send(0x06,n%10);}//-----------主函数-----------void main(void){unsigned int first;unsigned int second;unsigned int result;//最终运算结果unsigned char op;//用来存储+、-、*、/操作符键的值unsigned char flag;LOOP:first=0;second=0;result=0;op=0;flag=1;display(0);while(1){KeyScan();if(key<11&&key>0&&flag==1){first=first*10+key;key=0;display(first);}delay10ms(20);KeyScan();if(key>12&&key<=16){op=key;key=0;flag=2;}KeyScan();if(key<11&&key>0&&flag==2){second=second*10+key;key=0;display(second);}delay10ms(20);KeyScan();if(key==12){switch(op){case 13:result=first+second;break; case 14:result=first-second;break; case 15:result=first*second;break; case 16:result=first/second;break;}display(result);key=0;flag=1;}KeyScan();if(key==11)goto LOOP;}}。
DBUF EQU 30HTEMP EQU 40HYJ EQU 50H ;结果存放YJ1 EQU 51H ;中间结果存放GONG EQU 52H ;功能键存放ORG 00HSTART:MOV R3,#0 ;初始化显示为空MOV GONG,#0MOV 30H,#10HMOV 31H,#10HMOV 32H,#10HMOV 33H,#10HMOV 34H,#10HMLOOP:CALL DISP ;PAN调显示子程序WAIT:CALL TESTKEY ;判断有无按键JZ WAITCALL GETKEY ;读键INC R3 ;按键个数CJNE A,#0,NEXT1 ;判断是否数字键LJMP E1 ;转数字键处理NEXT1:CJNE A,#1,NEXT2LJMP E1NEXT2:CJNE A,#2,NEXT3LJMP E1NEXT3:CJNE A,#3,NEXT4LJMP E1NEXT4:CJNE A,#4,NEXT5LJMP E1NEXT5:CJNE A,#5,NEXT6LJMP E1NEXT6:CJNE A,#6,NEXT7LJMP E1NEXT7:CJNE A,#7,NEXT8LJMP E1NEXT8:CJNE A,#8,NEXT9LJMP E1NEXT9: CJNE A,#9,NEXT10LJMP E1NEXT10: CJNE A,#10,NEXT11 ;判断是否功能键LJMP E2 ;转功能键处理NEXT11:CJNE A,#11,NEXT12LJMP E2NEXT12:CJNE A,#12,NEXT13LJMP E2NEXT13:CJNE A,#13,NEXT14LJMP E2NEXT14:CJNE A,#14,NEXT15LJMP E2NEXT15: LJMP E3 ;判断是否清除键E1: CJNE R3,#1,N1 ;判断第几次按键LJMP E11 ;为第一个数字N1:CJNE R3,#2,N2LJMP E12 ;为第二个数字N2:CJNE R3,#3,N3LJMP E13 ;为第三个数字N3: LJMP E3 ;第四个数字转溢出E11:MOV R4,A ;输入值暂存R4 MOV 34H,A ;输入值送显示缓存MOV 33H,#10HMOV 32H,#10HLJMP MLOOP ;等待再次输入E12:MOV R7,A ;个位数暂存R7 MOV B,#10MOV A,R4MUL AB ;十位数ADD A,R7MOV R4,A ;输入值存R4MOV 32H,#10H ;输入值送显示缓存MOV 33H,34HMOV 34H,R7LJMP MLOOPE13:MOV R7,AMOV B,#10MOV A,R4MUL ABJB OV,E3 ;输入溢出ADD A,R7JB CY,E3 ;输入溢出MOV R4,AMOV 32H,33H ;输入值送显示缓存MOV 33H,34HMOV 34H,R7LJMP MLOOPE3: MOV R3,#0 ;按键次数清零MOV R4,#0 ;输入值清零MOV YJ,#0 ;计算结果清零MOV GONG,#0 ;功能键设为零MOV 30H,#10H ;显示清空MOV 31H,#10HMOV 32H,#10HMOV 33H,#10HMOV 34H,#10HLJMP MLOOPE2: MOV 34H,#10HMOV 33H,#10HMOV 32H,#10HMOV R0,GONG ;与上次功能键交换MOV GONG,AMOV A,R0CJNE A,#10,N21 ;判断功能键LJMP JIA ;”+"N21: CJNE A,#11,N22LJMP JIAN ;"-"N22:CJNE A,#12,N23LJMP CHENG ;"*”N23:CJNE A,#13,N24LJMP CHU ;”/”N24:CJNE A,#0,N25LJMP FIRST ;首次按功能键N25:LJMP DEN ;”=”N4:LJMP E3FIRST: MOV YJ,R4 ;输入值送结果MOV R3,#0 ;按键次数清零LJMP DISP1 ;结果处理JIA:MOV A,YJ ;上次结果送累加器ADD A,R4 ;上次结果加输入值JB CY,N4 ;溢出MOV YJ,A ;存本次结果MOV R3,#0 ;按键次数清零LJMP DISP1JIAN:MOV A,YJSUBB A,R4 ;上次结果减输入值JB CY,N4 ;负数溢出MOV YJ,AMOV R3,#0LJMP DISP1CHENG:M OV A,YJMOV B,AMOV A,R4MUL AB ;上次结果乘输入值JB OV,N4 ;溢出MOV YJ,ALJMP DISP1CHU:MOV A,R4MOV B,AMOV A,YJDIV AB ;上次结果除输入值MOV YJ,AMOV R3,#0LJMP DISP1DEN:MOV R3,#0LJMP DISP1DISP1:MOV B,#10MOV A,YJ ;结果送累加器DIV AB ;结果除10MOV YJ1,A ;暂存”商”MOV A,B ;取个位数MOV 34H,A ;个位数送显示缓存MOV A,YJ1JZ DISP11 ;结果是否为一位数MOV B,#10MOV A,YJ1DIV ABMOV YJ1,AMOV A,BMOV 33H,A ;十位送显示缓存MOV A,YJ1JZ DISP11 ;结果是否为二位数MOV 32H,A ;百位数送显示缓存DISP11: LJMP MLOOPDISP:MOV R0,#DBUF ;显示子程序MOV R1,#TEMP+4MOV R2,#5DP10:MOV DPTR,#SEGTABMOV A,@R0MOVC A,@A+DPTRMOV @R1,AINC R0DEC R1DJNZ R2,DP10MOV R0,#TEMPDP12:MOV A,@R0MOV P0,Aclr P2。
基于51单片机的简易教学计算器设计设计目的:本设计旨在基于51单片机实现一个简易的教学计算器,可以进行基本的四则运算,并具备一些辅助功能,帮助学生进行数学计算和学习。
设计要求:1.显示器:使用液晶显示器(LCD)来显示操作数和计算结果。
2.键盘输入:设计一个按键矩阵作为输入设备,用于输入数字和操作符。
3.四则运算:实现加法、减法、乘法和除法四种基本运算。
4.辅助功能:提供开平方、取倒数等辅助功能。
5.界面友好:界面清晰、操作简单。
硬件设计:1.51单片机(AT89C52):作为计算器的核心芯片,控制程序运行和与外围设备的交互。
2.液晶显示器(LCD):用于显示操作数和计算结果。
3.按键矩阵:用于输入数字和操作符。
4.运算模块:用于进行四则运算和辅助功能计算。
软件设计:1.系统初始化:初始化51单片机和LCD屏幕,设置键盘矩阵的引脚。
2.输入处理:通过按键矩阵检测用户输入,并将输入的字符存储在缓冲区中。
3.表达式计算:根据用户输入的表达式,通过逆波兰表达式算法将其转换为后缀表达式,并进行计算得到结果。
4.显示结果:将计算结果显示在LCD屏幕上。
5.辅助功能:根据用户选择的辅助功能,进行相应的计算,并显示结果。
6.重置功能:提供清零功能,将计算器的状态和显示结果重置。
操作流程:1.系统初始化:开机时,系统进行初始化,屏幕显示“计算器”字样。
2.输入操作数和操作符:用户通过按键矩阵输入操作数和操作符。
3.计算结果:用户输入“=”符号后,计算器根据输入的表达式进行计算,并将结果显示在LCD屏幕上。
4.辅助功能:在计算结果显示完成后,用户可选择进行辅助功能,如开平方、取倒数等操作。
5.重置功能:用户可通过按下“C”键进行重置,将计算器状态和显示结果清零。
总结:本设计基于51单片机实现了一个简易的教学计算器,具备基本的四则运算功能和一些辅助功能。
其使用液晶显示器作为显示设备,利用按键矩阵进行输入操作,通过逆波兰表达式算法进行计算,并将结果显示在屏幕上。
单片机课程设计题目名称基于51单片机的简易计算器学生学院____ 信息工程学院_______专业班级信息工程(应用电子方向)12(2)班姓名______虞君权__________学号**********指导教师_ _____李优新 ___2015年1月151一、课程设计的内容本次课程设计的内容从下面两个方面任选一个:一是在学院的单片机实验平台上进行,开发一个基于单片机与PWM技术的灯光调节系统,主要开发内容为按键定义、输入与防抖动技术、PWM调节技术以及显示技术等程序设计。
二是利用51系列单片机及必要的外围芯片、输入输出等接口电路设计开发一个简易的单片机系统,在此基础上,自行设计一个单片机应用程序来实现一些实用的功能。
通过这些内容的设计、开发、安装、调试等一系列工作,熟练掌握单片机系统的开发流程与工作机理,加深对所学课程知识的理解与把握,为将来相关的研究开发工作打下坚实的基础。
二、设计内容本次实验的任务就是要以51系列单片机为核心实现一个简易计算器计算器,它的结构非常简单,外部主要由4*4矩阵键盘和一个液晶显示屏构成,内部由一块AT89C51单片机构成,通过软件编程可实现简单加减乘除。
三、方案论证经分析,计算器电路包括三个部分:显示电路、4*4键扫描电路、单片机微控制电路。
具体如下:⒈)LCD显示电路LCD1602作为一个成熟的产品,使用简单,模式固定,便于移植到各种类型的程序,但是初学者往往要注意结合LCD本身的时序图来完善初始化程序。
又以其微功耗、体积小、显示内容丰富、超薄轻巧的诸多优点,故采用LCD.⒉)4*4键盘扫描电路(中断式,扫描式,反转式)用户设计行列键盘接口,一般常采用 3 种方法读取键值。
一种是中断式,外两种是扫描法和反转法。
中断式:在键盘按下时产生一个外部中断通知CPU,并由中断处理程序通过不同的地址读取数据线上的状态,判断哪个案件被按下。
本实验采用中断式实现用户键盘接口。
扫描法:对键盘上的某一行送低电平,其他行为高电平,然后读取列值。
新基于51单片机的简易计算器一、引言计算器是一种广泛应用的电子设备,用于进行常见的数值运算。
在现代社会,计算器是广大人们日常生活和学习中常用的工具之一、本文将介绍一种新基于51单片机的简易计算器的设计和实现,该计算器具有计算基本四则运算的功能,并且操作简便、界面友好。
二、设计实现1.系统硬件设计该计算器的硬件主要由51单片机、LCD显示屏、按键开关、电源等组成。
(1)51单片机:使用51系列单片机作为计算器的核心处理器,它具有处理能力强、易编程等特点,可以快速实现计算功能。
(2)LCD显示屏:采用16*2字符LCD显示屏,用于显示计算结果和用户输入的数字。
(3)按键开关:设置数字键盘开关、运算符键盘开关、等号键开关等,用户通过按下对应的按键输入数字和运算符。
(4)电源:使用直流电源供电,通过稳压电路和滤波电路提供稳定的电压和电流。
2.系统软件设计该计算器的软件主要由嵌入式C语言编写,实现了计算基本四则运算的功能。
(1)初始化:在系统启动时对各个设备进行初始化设置,包括LCD显示屏的初始化、按键开关的初始化等。
(2)用户输入:通过按键开关读取用户输入的数字和运算符,将其保存在缓冲区中。
(3)计算功能:根据用户输入的数字和运算符,通过判断运算符的类型进行相应的数值计算,并将结果保存在特定的寄存器中。
(4)结果显示:将计算结果从寄存器中读取并显示在LCD显示屏上,用户可以直观地看到计算结果。
三、系统特点1.硬件结构简单:该计算器的硬件结构简单,主要由几个常见元件组成,易于制作和调试。
2.操作简便:用户只需通过按键输入数字和运算符,即可完成计算操作,无需进行复杂的设置和调试。
3.界面友好:通过LCD显示屏直观地显示计算结果,用户可以清楚地了解计算过程和结果。
4.功能强大:该计算器可以进行基本的四则运算,满足大多数日常计算需求。
四、应用范围该简易计算器可以广泛应用于日常生活和学习中,包括商品购物计算、数学运算、财务统计等场景。
80c51单片机简易计算器源程序#include#include#include#define uint unsigned int#define unch unsigned char#define D8279 XBYTE[0x7EFF]#define CTRL8279 XBYTE[0x7FFF]unchZXM[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};unch n;unch result_flag;unch p;//浮点型数字的精确度unch Q;//小数点前一位数的字形码unch m;//存放键码unch key;//记录按下键盘后所代表的数字或运算符unch temp;//中间变量unch num;//实时记录数字和运算符在内的所有ASC码字符的个数unch num1;//实时记录数字的个数uint a[10]={0};//用于存放运算符两侧数的各个位unch i;//上面数组的循环控制变量unch aa;//小数运算时,记录小数点前面的个数unch bb;//记录小数点后面的变量long total_1,total_2;//total_1表示运算符左边的数,total_2表示运算符右边的数unch operator_flag;//要进行何种运算的标志变量float total_operation,total;//total_operation除法运算时用于存放结果的变量,total表示经过运算后的数float total1_point; //小数运算时用于记录运算符左边的小数float total2_point; //小数运算时用于记录运算符右边的小数unch point_flag;//小数运算的标志变量void Operation();void clear_array()//数组清除函数,用于清除运算符左边或右边的运算数的各个位{for(i=0;i<10;i++)a[i]=0;i=0;}void newset() //8279初始化//{CTRL8279=0x90; //写显示RAM,地址自动加一//CTRL8279=0x34; //定标//CTRL8279=0x10; //8个字符显示右边输入,编码扫描,键盘锁定//}void clear_ram()//总清除命令//{CTRL8279=0xd1;i=CTRL8279;i&=0x80; //读出8279的状态寄存器中显示的状态,重点读DU 位//while(i==0x80) //等待清除完成,直到DU位变成0,说明清除完毕,才可在写显示里写入字形码//{i=CTRL8279;i&=0x80;}}void key_scan() //独立键盘函数归零函数{clear_ram();newset();num=0; //记录数字个数的变量清0num1=0; //记录数字和符号个数的变量清0total_1=0; //运算符左边数暂存变量清0total_2=0;total1_point=0;total2_point=0;//运算符右边数暂存变量清0total=0; //运算结果暂存变量清0clear_array(); //数组清0D8279=0xbf;}void calculate_1() //求得运算符左边的那个数{unch j;long middle;for(j=0,middle=1;j<="">//这里多乘了10倍因为后面会先除以10在作乘法运算for(j=0;j<num1;j++)< bdsfid="137" p=""></num1;j++)<> {middle=middle/10; //每次乘数都要缩小10倍total_1=total_1+a[j]*middle; //将运算符左边的每个数字乘以相应的倍数再累加得到运算符左边的数并存放到total_1中}if(point_flag==1)//出现小数时,则计算得到其值{for(j=0,middle=1;j<bb;j++)< bdsfid="145"p=""></bb;j++)<>middle=middle*10;total1_point=1.0*total_1/middle;//totall_point为整数部分}num1=0; //确定完运算符左边的数后将统计数字个数的变量清0 }void calculate_2() //求得运算符右边的那个数{unch j;long middle;for(j=0,middle=1;j<="" p="">middle=middle*10; //确定最一开始每个数字要乘以的倍数//这里多乘了10倍因为后面会先除以10在作乘法运算for(j=0;j<num1;j++)< bdsfid="159" p=""></num1;j++)<> {middle=middle/10;//每次乘数都要缩小10倍total_2+=a[j]*middle;//将运算符左边的每个数字乘以相应的倍数//再累加得到运算符左边的那个数//并存放到total_2中}if(point_flag==1)//出现小数时则计算得到其值{for(j=0,middle=1;j<bb;j++)< bdsfid="169" p=""></bb;j++)<>middle=middle*10;total2_point=1.0*total_2/middle;}num1=0;//确定完运算符右边的数后将统计数字个数的变量清0 }////////******************用于显示经过运算后得到的整形结果的函数*******************************////////void display(long total_temp){unch j;long middle,temp;n=(long)(log10(total_temp))+1;//确定是几位数for(j=0,middle=1;j<="">middle=middle*10;//middle运算后为100000for(j=0;j<n-1;j++)< bdsfid="185" p=""></n-1;j++)<>{middle=middle/10;//middle每次缩小10倍,例如此处为10000temp=(long)(total_temp/middle);//将结果12345除以10000得到商1D8279=ZXM[temp];total_temp=total_temp-temp*middle; //12345-10000=2345,继续类似确定出每1位,}D8279=ZXM[total_temp]|0x80;}//////*************************用于显示经过运算后得到的浮点型结果的函数***********************/////////void display_decimals(float temp1,unch r){unch j,z[]={0};for(j=0;j<="">{z[j]=(long)(temp1*10);temp1=temp1*10-((long)(temp1*10));// 3.42-3=0.42}while(z[r-1]==0)r--; //如果最后一位是0,继续检测前面一位,直到检测非零值;for(j=0;j<r;j++)< bdsfid="208" p=""></r;j++)<>D8279=ZXM[z[j]];}int1( ) interrupt 2 //计算器矩阵键盘扫描中断函数,从左到右,从上到下{if(num==0) //若输入为第一个数字时,将显示器'0.'{newset();}CTRL8279=0x40; //发送读FIFO/RAM命令//m=D8279;switch(m){case 0x1d: key=7;a[i++]=7; //每按下一个数字就把该数字存入数组中,同时数组控制变量+1num++;num1++; //每按下一个数字,统计数字个数变量+1,统计数字和运算符个数变量+1D8279=0x07;break;case 0x1c: key=8;a[i++]=8;num++;num1++;D8279=0x7f;break;case 0x1b: key=9;a[i++]=9;num++;num1++;D8279=0x6f;break;case 0x1a: key='+';operator_flag=4;//运算符标志变量赋予不同值表示不同的运算方式bb=num1-aa; //确定小数点后有几位数calculate_1();//按下一个运算符后就把其左侧的运算数计算出来clear_array();//确定1个运算数后数组清0aa=0;bb=0;point_flag=0;num++; //统计数字和运算符个数变量+1clear_ram();newset();break;case 0x19: key='%';operator_flag=9;bb=num1-aa; //确定小数点后有几位数calculate_1();//按下一个运算符后就把其左侧的运算数计算出来clear_array();//确定1个运算数后数组清0aa=0;bb=0;point_flag=0;num++; //统计数字和运算符个数变量+1clear_ram();newset();bb=num1-aa; //确定小数点后有几位数clear_ram();Operation();result_flag=1;break;case 0x18: key='c';key_scan();break;case 0x15: key=4;a[i++]=4;//每按下一个数字就把该数字存入数组中,同时数组控制变量+1num++;num1++; //每按下一个数字,统计数字个数变量+1,统计数字和运算符个数变量+1D8279=0x66;break;case 0x14: key=5;a[i++]=5;num++;num1++;D8279=0x6d;break;case 0x13: key=6;a[i++]=6;num++;num1++;D8279=0x7d;break;case 0x12: key='-';operator_flag=3;//运算符标志变量赋予不同值表示不同的运算方式bb=num1-aa; //确定小数点后有几位数calculate_1();//按下一个运算符后就把其左侧的运算数计算出来clear_array();//确定1个运算数后数组清0aa=0;bb=0;point_flag=0;num++; //统计数字和运算符个数变量+1clear_ram();newset();break;case 0x11: key='z';operator_flag=8;//运算符标志变量赋予不同值表示不同的运算方式bb=num1-aa; //确定小数点后有几位数calculate_1();//按下一个运算符后就把其左侧的运算数计算出来clear_array();//确定1个运算数后数组清0aa=0;bb=0;point_flag=0;num++; //统计数字和运算符个数变量+1clear_ram();newset();break;case 0x10: key='^';operator_flag=5;bb=num1-aa; //确定小数点后有几位数calculate_1();//按下一个运算符后就把其左侧的运算数计算出来clear_array();//确定1个运算数后数组清0aa=0;bb=0;point_flag=0;num++; //统计数字和运算符个数变量+1clear_ram();newset();bb=num1-aa; //确定小数点后有几位数clear_ram();Operation();result_flag=1;break;case 0x0d: key=1;a[i++]=1;//每按下一个数字就把该数字存入数组中,同时数组控制变量+1num++;num1++;//每按下一个数字,统计数字个数变量+1,统计数字和运算符个数变量+1D8279=0x06;break;case 0x0c: key=2;a[i++]=2;num++;num1++;D8279=0x5b;break;case 0x0b: key=3;a[i++]=3;num++;num1++;D8279=0x4f;break;case 0x0a: key='*';operator_flag=2;//运算符标志变量赋予不同值表示不同的运算方式bb=num1-aa; //确定小数点后有几位数calculate_1();//按下一个运算符后就把其左侧的运算数计算出来clear_array();//确定1个运算数后数组清0aa=0;bb=0;point_flag=0;num++; //统计数字和运算符个数变量+1clear_ram();newset();break;case 0x09: key='!';operator_flag=10;bb=num1-aa; //确定小数点后有几位数calculate_1();//按下一个运算符后就把其左侧的运算数计算出来clear_array();//确定1个运算数后数组清0aa=0;bb=0;point_flag=0;num++; //统计数字和运算符个数变量+1clear_ram();newset();bb=num1-aa; //确定小数点后有几位数clear_ram();Operation();result_flag=1;break;case 0x08: key='k';operator_flag=6;bb=num1-aa; //确定小数点后有几位数calculate_1();//按下一个运算符后就把其左侧的运算数计算出来clear_array();//确定1个运算数后数组清0aa=0;bb=0;point_flag=0;num++; //统计数字和运算符个数变量+1clear_ram();newset();break;case 0x05: key=0;a[i++]=0;//每按下一个数字就把该数字存入数组中,同时数组控制变量+1num++;num1++;//每按下一个数字,统计数字个数变量+1,统计数字和运算符个数变量+1D8279=0x3f;break;case 0x04 :key=',';//相当于输入为0的程序重复执行a[i++]=0;num++;num1++;D8279=0x3f;a[i++]=0;num++;num1++;D8279=0x3f;break;case 0x03: key='.';num++;aa=num1;//确定小数点前有几位数CTRL8279=0x60+aa-1;Q=D8279;CTRL8279=0x80+aa-1;D8279=Q|0x80;point_flag=1;CTRL8279=0x90+aa;break;case 0x02: key='/';operator_flag=1; //运算符标志变量赋予不同值表示不同的运算方式bb=num1-aa; //确定小数点后有几位数calculate_1(); //按下一个运算符后就把其左侧的运算数计算出来clear_array(); //确定一个运算数后数组清0aa=0;bb=0;point_flag=0;num++; //统计数字和运算符个数变量+1clear_ram();newset();break;case 0x01: key='x';operator_flag=7;bb=num1-aa; //确定小数点后有几位数calculate_1();//按下一个运算符后就把其左侧的运算数计算出来clear_array();//确定1个运算数后数组清0aa=0;bb=0;point_flag=0;num++; //统计数字和运算符个数变量+1clear_ram();newset();bb=num1-aa; //确定小数点后有几位数clear_ram();Operation();result_flag=1;break;case 0x00: key='=';bb=num1-aa; //确定小数点后有几位数clear_ram();Operation();result_flag=1;break;}}float en(float y,unch c){unch i;float sum=y;if(c==0)return 1;for(i=0;i<c-1;i++)< bdsfid="432" p=""></c-1;i++)<> sum*=y;return sum;}long jiecheng(unsigned int c){unsigned long sum;sum=1;while(c!=0){sum=sum*c;c--;}return sum;}void jieguo(float total_operation){unch v,w;if((total_operation-(long)total_operation)==0.0){if((long)total_operation!=0)display(total_operation);elseD8279=0xbf;}else{if((long)total_operation!=0){display((long)total_operation);v=(long)log10((long)total_operation)+1;w=8-v;display_decimals(1.0*(total_operation-(long)total_operation),w);}else{D8279=0Xbf;w=7;display_decimals(total_operation,w);}}}//////////**********************显示结果函数*************************////////// void Operation(){ newset();calculate_2();if(total1_point==0)total1_point=1.0*total_1;if(total2_point==0)total2_point=1.0*total_2;if(operator_flag==1)//*************如果输入/运算符**************// {operator_flag=0;//按了=键后计算得到运算符右边的数total=total1_point/total2_point;//转为浮点型数据jieguo(total);}if(operator_flag==2)//*******如果输入*运算符*********//{operator_flag=0;total=total1_point*total2_point;//转为浮点型数据jieguo(total);}if(operator_flag==3)//*******如果输入-运算符***********//{operator_flag=0;total=total1_point-total2_point; //进行减法运算if(total<0) //如果为负数{D8279=0x40;total=total2_point-total1_point;}jieguo(total);}if(operator_flag==4)//********如果输入+运算符*********// { operator_flag=0;total=(total1_point+total2_point);//转为浮点型数据jieguo(total);}if(operator_flag==5)//********如果输入^运算符*********// { operator_flag=0;total=(total1_point*total1_point);//转为浮点型数据jieguo(total);}if(operator_flag==6)//********如果输入√运算符*********// { operator_flag=0;total=log10((long)(total2_point));//转为浮点型数据jieguo(total);}if(operator_flag==7)//********如果输入1/x运算符*********// { operator_flag=0;total=1/(total1_point);//转为浮点型数据jieguo(total);}if(operator_flag==8)//********如果输入ncf运算符*********// { operator_flag=0;total=en(total1_point,(int)total2_point);//转为浮点型数据jieguo(total);}if(operator_flag==9)//**********如果输入%*********//{operator_flag=0;total=(total1_point)/100;//转为浮点型数据jieguo(total);}if(operator_flag==10)//**********如果输入阶乘!*********// { operator_flag=0;total=jiecheng((int)total1_point);jieguo(total);}}void main(){clear_ram(); //总清除newset(); //8279初始化key_scan();IT1=0; //设置INT1中断方式为低电平EX1=1; //允许INT1中断EA=1; //CPU允许中断while(1); //等待中断//}。
《微机原理与单片机课程设计》课程设计报告基于51单片机的简易计算器设计一、设计目的单片机的出现是计算机制造技术高速发展的产物,它是嵌入式控制系统的核心,如今,它已广泛的应用到我们生活的各个领域,电子、科技、通信、汽车、工业等。
本设计是基于51系列单片机来进行的简单数字计算器设计,可以完成计算器的键盘输入,进行加、减、乘、除六位整数数范围内的基本四则运算,并在LED上显示相应的结果。
软件方面使用C语言编程,并用PROTUES仿真。
二、总体设计及功能介绍根据功能和指标要求,本系统选用MCS-51系列单片机为主控机,实现对计算器的设计。
具体设计及功能如下:(1)由于要设计的是简单的计算器,可以进行四则运算,为了得到较好的显示效果,采用LED 显示数据和结果。
(2)另外键盘包括数字键(0~9)、符号键(+、-、×、÷)、清除键和等号键,故只需要16 个按键即可,设计中采用集成的计算键盘。
(3)执行过程:开机显示零,等待键入数值,当键入数字,通过LED显示出来,当键入+、-、*、/运算符,计算器在内部执行数值转换和存储,并等待再次键入数值,当再键入数值后将显示键入的数值,按等号就会在LED上输出运算结果。
(4)错误提示:当计算器执行过程中有错误时,会在LED上显示相应的提示,如:当输入的数值或计算得到的结果大于计算器的表示范围时,计算器会在LED上显示“CUO”,提示溢出。
三、系统模块组成框图:二、硬件设计(一)、总体硬件设计本设计选用AT89C51单片机为主控单元。
显示部分:采用LED动态显示。
按键部分:采用4*4集成计算键盘;总电路图:(1)4×4集成计算键盘集成计算键盘本质上是4×4矩阵键盘,矩阵键盘采用四条I/O 线作为行线,四条I/O 线作为列线组成键盘,在行线和列线的每个交叉点上设置一个按键。
这样键盘上按键的个数就为4×4个。
这种行列式键盘结构能有效地提高单片机系统中I/O 口的利用率。
目录一、设计任务和要求 (2)1、设计要求 (2)2、设计方案的确定 (2)二、硬件设计 (2)1、单片机最小系统 (2)2、键盘电路的设计 (3)3、显示电路的设计 (3)4、系统硬件电路图 (4)三、软件设计 (5)1 系统设计 (5)2 显示电路的设计 (6)3、程序清单 (8)四、调试与仿真 (14)五、试验箱实物图 (14)六、心得体会 (15)一、设计任务和要求1、设计要求利用单片机设计并制作简易计算器。
具体要求如下:1、4*4按键用于0~9的数字输入、加减乘除、等于、清零功能;2、能实现简单的加减乘除运算;3、输入数字及计算结果通过LED或LCD显示器显示。
2、设计方案的确定按照设计要求,本课题需要使用数码管显示和扩展4*4键盘,由于AT89C51芯片的I口不够多,而且为了硬件电路设计的简单化,故选择串行动态显示和用P1口扩展4*4键盘,扩展的4*4键盘定义十个数字键,六个功能键,使用串行动态显示显示运算结果。
主程序进行初始化,采用行列扫描进行查表得出键值,每次按键后调用显示子程序。
二、硬件设计简易数字计算器系统硬件设计主要包括:键盘电路,显示电路以及其他辅助电路。
下面分别进行设计。
1.单片机最小系统单片机最小系统就是支持主芯片正常工作的最小部分,包括主控芯片、复位电路和晶振电路。
(1)、复位电路复位电路本设计采用上电与手动复位电路,电阻分别选取100和10K,电容选取10uF,系统一上电,芯片就复位,或者中途按按键也可以进行复位。
(2)、晶振电路图三晶振电路晶振电路是单片机的心脏,它用于产生单片机工作所需要的时钟信号。
单片机的晶振选取11.0592MHz,晶振旁电容选取30pF。
2.键盘电路的设计键盘可分为两类:编码键盘和非编码键盘。
编码键盘是较多按键(20个以上)和专用驱动芯片的组合,当按下某个按键时,它能够处理按键抖动、连击等问题,直接输出按键的编码,无需系统软件干预。
通用计算机使用的标准键盘就是编码键盘。
整数加减乘除计算器-C51单片机C51单片机-整数加减乘除计算器本程序是基于技能大赛设备,所使用的模块为显示模块、主机模块和指令模块。
此计算器适合10位以内的加减乘除运算,除法没有小数位,只取整数位。
此程序仅供参考,可以相互学习使用。
/* ---简易整数计算器--- */#include //包含AT89s52头文件#define uchar unsigned char#define uint unsigned int#define ulong unsigned long/* ---1602液晶控制引脚--- */sbit rs=P2^0;sbit rw=P2^1;sbit e=P2^2;#define port P0 //1602数据端口#define port3 P3 //矩阵键盘uchar code tab[]="0123456789+-*/=c";ulong a1,a2,aa; //没有小数点的长整型变量uchar jsf; //运算符/* ---微秒延时--- */void delay(uint i){while(i--);}/* ---1602液晶各子函数--- */ void busy1602(){port=0xff;rs=0;rw=1;e=1;e=1;while(port&0x80);e=0;}void writecom(uchar com){busy1602();rs=0;rw=0;port=com;e=1;e=0;}void writedat(uchar dat){busy1602();rs=1;rw=0;port=dat;e=1;e=0;}void showstr(bit row,uchar col,uchar *s) //显示字符串{ uchar i;writecom(0x80+row*0x40+col);for(i=0;s[i]!=0;i++){writedat(s[i]);}}void shownum(bit row,uchar col,ulong num) //显示数字{ writecom(0x04);writecom(0x80+row*0x40+col);if(num>=0)writedat(num%10+'0');if(num>9)writedat(num/10%10+'0');if(num>99)writedat(num/100%10+'0');if(num>999)writedat(num/1000%10+'0');if(num>9999)writedat(num/10000%10+'0');if(num>99999)writedat(num/100000%10+'0');if(num>999999)writedat(num/1000000%10+'0');if(num>9999999)writedat(num/10000000%10+'0');if(num>99999999)writedat(num/100000000%10+'0'); if(num>999999999)writedat(num/1000000000%10+'0'); if(num>4294967294)showstr(0,4,"rorrE");}void init1602() //1602 初始化{writecom(0x38);writecom(0x0c);writecom(0x06);writecom(0x01);/* ---按键扫描程序--- */uchar keyscan(){uchar key=16,i;for(i=0;i<4;i++){port3=0xfe<>(8-i); //循环左移switch(port3&0xf0){case 0xe0:key=4*i;break;case 0xd0:key=4*i+1;break; case 0xb0:key=4*i+2;break; case 0x70:key=4*i+3;break; }}return key;}/* ---运算--- */void js()switch(jsf){case '+':aa=a1+a2;break; case '-':if(a1>=a2)aa=a1-a2; else if(a1< p="">break;case '*':aa=a1*a2;break; case '/':if(a2==0)aa=' '; else aa=a1/a2; break;}}void main(){uchar k;bit b=0,a;init1602();showstr(0,3,"jisuanqi"); while(1){if(keyscan()!=16&&b==0) {delay(200);if(keyscan()!=16){b=1;k=keyscan();if(k==0||k==1||k==2||k==3||k==4||k==5||k==6||k==7||k== 8||k= =9) //数字键{if(a==0){a1=a1*10+k;writecom(0x01);shownum(1,15,a1);}else{a2=a2*10+k;writecom(0x01);shownum(1,15,a2);}}else if(k==10||k==11||k==12||k==13) //+-*/键{a=1;writecom(0x01);switch(k){case 10:jsf='+';showstr(1,15,"+");break;case 11:jsf='-';showstr(1,15,"-");break;case 12:jsf='*';showstr(1,15,"*");break;case 13:jsf='/';showstr(1,15,"/");break;}}else if(k==14) //等号键{a=0;js();writecom(0x01);if(aa==' ')showstr(0,0,"Error"); //被除数为零不显示,第一行显示错误else shownum(1,15,aa);if(jsf=='-'&&a1<="" p="">else showstr(1,0," ");}else if(k==15) //清零键{a=0;a1=a2=aa=0;jsf=0;writecom(0x01);shownum(1,15,0);}}}else if(keyscan()==16)b=0;}}<>。