课程设计计算器

计算器

////实验1
//void menu()
//{
//	printf("****************************\n");
//	printf("*        小小计算器        *\n");
//	printf("*        1.加法            *\n");
//	printf("*        2.减法            *\n");
//	printf("*        3.乘法            *\n");
//	printf("*        4.除法            *\n");
//	printf("*        5.取模运          *\n");
//	printf("*        6.计算圆周率      *\n");
//	printf("*        0.退出计算器      *\n");
//	printf("****************************\n");
//}
//int main()
//{
//	menu();
//	return 0;
//}
////实验2
//#include"stdio.h"
//#define PI 3.14
//void menu()
//{
//	printf("****************************\n");
//	printf("*        小小计算器        *\n");
//	printf("*        1.加法            *\n");
//	printf("*        2.减法            *\n");
//	printf("*        3.乘法            *\n");
//	printf("*        4.除法            *\n");
//	printf("*        5.取模运          *\n");
//	printf("*        6.计算圆周率      *\n");
//	printf("*        0.退出计算器      *\n");
//	printf("****************************\n");
//}
//void Calculator()
//{
//	int a, b;
//	float r;
//	int t = 1;
//	do
//	{
//		printf("请输入要进行的计算:\n");
//		scanf("%d", &t);
//		switch (t)
//		{
//		case 1:
//		{
//				  printf("请输入值:");
//				  scanf("%d %d", &a, &b);
//				  printf("十进制形式输出结果:%d+%d=%d\n", a, b, a + b);
//				  break;
//		}
//		case 2:
//		{
//				  printf("请输入值:");
//				  scanf("%d %d", &a, &b);
//				  printf("十进制形式输出结果:%d-%d=%d\n", a, b, a - b);
//				  break;
//		}
//		case 3:
//		{
//				  printf("请输入值:");
//				  scanf("%d %d", &a, &b);
//				  printf("十进制形式输出结果:%d*%d=%d\n", a, b, a * b);
//				  printf("乘法的指数形式:%e", a*b);
//				  break;
//		}
//		case 4:
//		{
//				  printf("请输入值:");
//				  scanf("%d %d", &a, &b);
//				  printf("%d÷%d=%f\n", a, b, (float)a / b);
//				  break;
//		}
//		case 5:
//		{
//				  printf("请输入值:");
//				  scanf("%d %d", &a, &b);
//				  printf("十进制:%d对%d取模运算得:%d\n", a, b, (int)a % (int)b);
//				  break;
//		}
//		case 6:
//		{
//				  printf("请输入圆的半径:");
//				  scanf("%f", &r);
//				  printf("圆的整数结果为:%d\n", (int)(PI*r*r));
//				  printf("圆的面积为:%f\n", PI*r*r);
//				  printf("圆的面积保留两位小数:%.2f\n", PI*r*r);
//				  break;
//		}
//		}
//	} while (t != 0);
//}
//int main()
//{
//	menu();
//	Calculator();
//	return 0;
//}
//综合实验
#include"stdio.h"
#define PI 3.14
void LeapYear();
void GradeChange();
void  OddSum();
void EvenSum();
void ThreeTimes();
void Divide_3_5();
void ShuiXianHua();
int MaxInTwo(int,int);
void MaxAndMin();
void Bubble();
void Transposition();
void DiagnoalSum();
void CountWords();
void Sort();
void StuBubble(struct student stu[]);
void menu()
{
	printf("***********************************************\n");
	printf("*            小小计算器                       *\n");
	printf("*      1.加法                                 *\n");
	printf("*      2.减法                                 *\n");
	printf("*      3.乘法                                 *\n");
	printf("*      4.除法                                 *\n");
	printf("*      5.取模运                               *\n");
	printf("*      6.计算圆周率                           *\n");
	printf("*      7.判断闰年                             *\n");
	printf("*      8.成绩转换                             *\n");
	printf("*      9.计算1到输入数之间的奇数和            *\n");
	printf("*      10.计算从1到输入数之间的偶数和         *\n");
	printf("*      11.计算从1到输入数之间所有3的倍数      *\n");
	printf("*      12.求既能被3整除又能被5整除的数        *\n");
	printf("*      13.求水仙花数                          *\n");
	printf("*      14.求两个数中的最大值                  *\n");
	printf("*      15.                                    *\n");
	printf("*      16.冒泡排序                            *\n");
	printf("*      17.矩阵转置                            *\n");
	printf("*      18.求对角线的和                        *\n");
	printf("*      19.统计单词个数                        *\n");
	printf("*      20.                                    *\n");
	printf("*      21.                                    *\n");
	printf("*      22.学生成绩排序                        *\n");
	printf("*      0.退出程序                             *\n");
	printf("***********************************************\n");
}
void Calculator()
{
	int a, b;
	float r;
	int t = 1;
	do
	{
		printf("请输入要进行的计算:\n");
		scanf("%d", &t);
		switch (t)
		{
		case 1:
		{
				  printf("请输入值:");
				  scanf("%d %d", &a, &b);
				  printf("十进制形式输出结果:%d+%d=%d\n", a, b, a + b);
				  printf("八进制形式输出结果:%d+%d=%o\n", a, b, a + b);
				  printf("十六进制形式输出结果:%d+%d=%x\n", a, b, a + b);
				  break;
		}
		case 2:
		{
				  printf("请输入值:");
				  scanf("%d %d", &a, &b);
				  printf("十进制形式输出结果:%d-%d=%d\n", a, b, a - b);
				  printf("八进制形式输出结果:%d-%d=%o\n", a, b, a - b);
				  printf("十六进制形式输出结果:%d-%d=%x\n", a, b, a - b);
				  break;
		}
		case 3:
		{
				  float a1, a2;
				  printf("请输入值:");
				  scanf("%f %f", &a1, &a2);
				  printf("乘法的小数形式:%f\n", a1*a2);
				  printf("乘法的指数形式:%e\n", a1*a2);
				  break;
		}
		case 4:
		{
				  printf("请输入值:");
				  scanf("%d %d", &a, &b);
				  printf("%d÷%d=%f\n", a, b, (float)a / b);//除的运算可能除不尽
				  break;
		}
		case 5:
		{
				  printf("请输入值:");
				  scanf("%d %d", &a, &b);
				  printf("十进制:%d对%d取模运算得:%d\n", a, b, (int)a % (int)b);
				  printf("八进制:%d对%d取模运算得:o\n", a, b, (int)a % (int)b);
				  printf("十六进制:%d对%d取模运算得:%x\n", a, b, (int)a % (int)b);
				  break;
		}
		case 6:
		{
				  printf("请输入圆的半径:");
				  scanf("%f", &r);
				  printf("圆的整数结果为:%d\n", (int)(PI*r*r));
				  printf("圆的面积为:%f\n", PI*r*r);
				  printf("圆的面积保留两位小数:%.2f\n", PI*r*r);
				  break;
		}
		case 7:
		{
				  LeapYear();
				  break;
		}
		case 8:
		{
				  GradeChange();
				  break;
		}
		case 9:
		{
				  OddSum();
				  break;
		}
		case 10:
		{
				   EvenSum();
				   break;
		}
		case 11:
		{
				   ThreeTimes();
				   break;
		}
		case 12:
		{
				   Divide_3_5();
				   break;
		}
		case 13:
		{
				   ShuiXianHua();
				   break;
		}
		case 14:
		{
				   int num1, num2;
				   printf("请输入要求的两个数:");
				   scanf("%d %d", &num1, &num2);
				   printf("两个数中的最大值为:%d\n", MaxInTwo(num1, num2));
				   break;
		}
		case 15:
		{
				   MaxAndMin();
				   break;
		}
		case 16:
		{
				   Bubble();
				   break;
		}
		case 17:
		{
				   Transposition();
				   break;
		}
		case 18:
		{
				   DiagnoalSum();
				   break;
		}
		case 19:
		{
				   CountWords();
				   break;
		}
		case 20:
		{

		}
		case 21:
		{

		}
		case 22:
		{
				   Sort();
		}
		}
	} while (t != 0);
}
int main()
{
	menu();
	Calculator();
	return 0;
}
void LeapYear()
{
	int year;
	printf("请输入你要判断的闰年:");
	scanf("%d", &year);
	if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
	{
		printf("%d是闰年\n", year);
	}
}
void GradeChange()
{
	int Grade;
	printf("请输入要转换的(百分制)成绩:");
	scanf("%d", &Grade);
	if (Grade<0 || Grade>100)//增强函数的功能
	{
		printf("输入错误!\n");
	}
	else
	{
		switch (Grade / 10)
		{
		case 10:
		case 9:
		{
				  printf("优秀\n");
				  break;
		}
		case 8:
		{
				  printf("良好\n");
				  break;
		}
		case 7:
		{
				  printf("中等\n");
				  break;
		}
		case 6:
		{
				  printf("及格\n");
				  break;
		}
		default:
			printf("不及格\n");
		}
	}
}
void  OddSum()
{
	int num, sum = 0;
	printf("请输入范围的最大值:");
	scanf("%d", &num);
	for (int i = 1; i <= num; i+=2)//这种方式递增比较简单
	{
		sum = sum + i;
	}
	printf("奇数的和为%d\n", sum);
}
void EvenSum()
{
	int num, sum = 0, i=2;
	printf("请输入该范围的最大值;");
	scanf("%d", &num);
	while (i <= num)
	{
		sum = sum + i;
		i += 2;
	}
	printf("偶数的和为:%d\n", sum);
}
void ThreeTimes()
{
	int num, i = 1;
	printf("请输入该范围的最大值;");
	scanf("%d", &num);
	do
	{
		if (i % 3 == 0)
		{
			printf("%d ", i);
		}
		i++;
	} while (i <= num);
	printf("\n");
}
void Divide_3_5()
{
	int num1, num2;
	printf("输入要求的数的范围:");
	scanf("%d %d", &num1,&num2);
	do
	{
		if (num1 % 3 == 0 && num1 % 5 == 0)
		{
			printf("%d ", num1);
		}
		num1++;
	} while (num1 <= num2);
	printf("\n");
}
void ShuiXianHua()
{
	for (int i = 1; i <= 9; i++)
	{
		for (int j = 0; j <= 9; j++)
		{
			for (int k = 0; k <= 9; k++)
			{
				if (i*i*i + j*j*j + k*k*k == i * 100 + j * 10 + k)
				{
					printf("%d水仙花数:%d %d %d\n", i * 100 + j * 10 + k, i, j, k);
				}
			}
		}
	}
}
int MaxInTwo(int num1,int num2)
{
	int max;
	return (max = num1 > num2 ? num1 : num2);
}
void MaxAndMin()
{

}
void Bubble()
{
	int i, j, tmp;
	int a[10] = { 0 };
	printf("请输入十个整数:");
	for (i = 0; i < 10; i++)
	{
		scanf("%d", &a[i]);
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
	for (i = 0; i < 9; i++)
	{
		for (j = 0; j < 9-i; j++)
		{
			if (a[j]>a[j + 1])
			{
				tmp = a[j + 1];
				a[j + 1] = a[j];
				a[j] = tmp;
			}
		}
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", a[i]);
	}
}
void Transposition()
{
	int arr[3][4] = {
		{ 1, 2, 3, 4 },
		{ 4, 5, 6, 7 },
		{ 7, 8, 9, 0 },
	};
	for (int i = 0; i < 3; i++)//三行
	{
		for (int j = 0; j < 4; j++)//四列
		{
			printf("%-4d", arr[i][j]);
		}
		printf("\n");
	}
	printf("转置后的数组:\n");
	for (int i = 0; i < 4; i++)//由上一个循环的行变成列,行写在列的位置
	{
		for (int j = 0; j < 3; j++)//由上一个循环的列变成行,列写在行的位置
		{
			printf("%-4d  ", arr[j][i]);
		}
		printf("\n");
	}
}
void DiagnoalSum()
{
	int sum = 0;
	int arr[3][3] = {
		{ 1, 2, 3 },
		{ 4, 5, 6 },
		{ 7, 8, 9 },
	};
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			if (i == j)
			{
				sum += arr[i][j];
			}
		}
	}
	printf("对角线的和为:%d\n",sum);
}
void CountWords()
{
	char arr[100] = { 0 };
	int i, MarkWord=1, count = 0;//MarkWord标记是否在单词内,在单词内为1 不在为0
	printf("请输入英文句子:");
	gets(arr);
	char ch = 0;
	while ((ch = getchar()) != '\n')//getchar()在缓冲区读取字符串
	{
		if (ch == ' ')
		{
			MarkWord = 0;//I am a cat.根据这个单词串,走一下while里面的循环
		}
		else if (MarkWord == 0)
		{
			MarkWord = 1;
			count++;
		}
	}
	printf("单词个数为:%d\n", count+1);//count+1的原因是,最后一个单词后面没有空格
}
struct student{
	char Sno[10];
	char name[10];
	float Grade;
};
void Sort()
{
	float sum = 0, Avg;
	struct student stu[10];
	printf("请依次输入这十个学生的学号、姓名和成绩:\n");
	for (int i = 0; i < 10; i++)
	{
		printf("请输入第%d个学生的学号、姓名和成绩\n",i);
		scanf("%s %s %f", &stu[i].Sno, &stu[i].name, &stu[i].Grade);//用这种方式输入Sno和name比gets()方便
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%s %s %.2f\n", stu[i].Sno, stu[i].name, stu[i].Grade);
	}
	//StuBubble(stu);
	for (int i = 0; i < 10; i++)
	{
		sum = sum + stu[i].Grade;
	}
	Avg = sum / 10;
	printf("总成绩为:%.2f\n平均成绩为:%.2f\n", sum, Avg);
}
//void StuBubble(struct student stu[])
//{
//	int i, j;
//	float tmp;
//	for (i = 0; i < 9; i++)
//	{
//		for (j = 0; j < 9 - i; j++)
//		{
//			if (stu[j].Grade>stu[j + 1].Grade)
//			{
//				tmp = stu[j + 1].Grade;
//				stu[j + 1].Grade = stu[j].Grade;
//				stu[j].Grade = tmp;
//			}
//		}
//	}
//	for (int i = 0; i < 10; i++)
//	{
//		printf("%s %s %.2f\n", stu[i].Sno, stu[i].name, stu[i].Grade);
//	}
//}
课程程设计,简易议计算器!实验已经成功目录 1、引言……………………………………………………………………………………………… 2 1.1 计算器意义………………………………………………………………………………2 1.2 电子计算器的特殊键 …………………………………………………………………2 2 、单片机概述.……………………………………………………………………………………2 3 、芯片简介 ………………………………………………………………………………………3 3.1 MSC-51芯片简介…………………………………………………………………………3 4 、相关知识 ………………………………………………………………………………………6 4.1数码管显示…………………………………………………………………………………6 4.2矩阵按键 …………………………………………………………………………………6 5 、计算器硬件电路设 …………………………………………………………………………7 6 、计算器程序设计………………………………………………………………………………7 6.1存储单元分配………………………………………………………………………………7 6.2 主程序设计…………………………………………………………………………………7 6.3 数码管显示数据转换子程序CONV ……………………………………………………7 6.4 数码管动态显示子程序………………………………………………………………… 7 7 、系统硬件设计……………………………………………………………………………………7 7.1 系统总框图如下……………………………………………………………………………8 7.2 计算器硬件线路图…………………………………………………………………………8 7.3 系统工作原理 ………………………………………………………………………………9 8、汇编语言程序源代码……………………………………………………………………………10 9 、结语………………………………………………………………………………………………17 10、设计实物图……………………………………………………………………………18 摘要 近年来随着科技的飞速发展,单片机的应用正在不断深入,同时带动传统控制检测技术日益更新。在实时检测和自动控制的单片机应用系统中,单片机往往作为一个核心部件来使用,仅单片机方面知识是不够的,还应根据具体硬件结构软硬件结合,加以完善。 本任务是个简易的两位数的四则运算,程序都是根据教材内和网络中的程序参考编写而成,在功能上还并不完善,限制也较多。本任务重在设计构思与团队合作,使得我们用专业知识、专业技能分析和解决问题全面系统的锻炼。 关键词: 单片机 计算器 范围 加减乘除 1 引言 1.1 计算器的历史 说起计算器,值得我们骄傲的是,最早的计算工具诞生在中国。中国古代最早采用的一种计算工具叫筹策,又被叫做算筹。这种算筹多用竹子制成,也有用木头,兽骨充当材料的。约二百七十枚一束,放在布袋里可随身携带。直到今天仍在使用的珠算盘,是中国古代计算工具领域中的另一项发明,明代时的珠算盘已经与现代的珠算盘几乎相同。17世纪初,西方国家的计算工具有了较大的发展,英国数学家纳皮尔发明的"纳皮尔算筹",英国牧师奥却德发明了圆柱型对数计算尺,这种计算尺不仅能做加减乘除、乘方、开方运算,甚至可以计算三角函数,指数函数和对数函数,这些计算工具不仅带动了计算器的发展,也为现代计算器发展奠定了良好的基础,成为现代社会应用广泛的计算工具。 1.2 电子计算器的特殊键 在使用电子计算器进行四则运算的时候,一般要用到数字键,四则运算键和清除数据键。除了这些按键,还有一些特殊键,可以使计算更加简便迅速。 2 单片机概述 单片机微型计算机是微型计算机的一个重要分支,也是颇具生命力的机种。单片机微型计算机简称单片机,特别适用于控制领域,故又称为微控制器。 通常,单片机由单块集成电路芯片构成,内部包含有计算机的基本功能部件:中央处理器、存储器和I/O接口电路等。因此,单片机只需要和适当的软件及外部设备相结合,便可成为一个单片机控制系统。 单片机经过1、2、3、3代的发展,目前单片机正朝着高性能和多品种方向发展,它们的CPU功能在增强,内部资源在增多,引角的多功能化,以及低电压底功耗。 3 芯片简介 3.1 MSC-51芯片简介 MCS-51单片机内部结构 AT89C51是与MCS-51系列单片机兼容的典型产品,我们以这一代表性的机型进行系统的讲解。 AT89C51单片机包含中央处理器、程序存储器(ROM)、数据存储器(RAM)、定时/计数器、并行接口、串行接口和中断系统等几大单元及数据总线、地址总线和控制总线等三大总线,现在我们分别加以说明: •中央处理器: 中央处理器(CPU)是整个单片机的核心部件,是8位数据宽度的处理器,能处理8位二进制数据或代码,CPU负责控制、指挥和调度整个单元系统协调的工作,完成运算和控制输入输出功能等操作。 •数据存储器(RAM) AT89C51内部有128个8位用户数据存储单元和128个专用寄存器单元,它们是统一编址的,专用寄存器只能用于存放控制指令数据,用户只能访问,而不能用于存放用户数据,所以,用户能使用的RAM只有128个,可存放读写的数据,运算的中间结果或用户定义的字型表。 图1 •程序存储器(ROM): AT89C51共有4096个8位掩膜ROM,用于存放用户程序,原始数据或表格。 •定时/计数器(ROM): AT89C51有两个16位的可编程定时/计数器,以实现定时或计数产生中断用于控制程序转向。 •并行输入输出(I/O)口: AT89C51共有4组8位I/O口(P0、 P1、P2或P3),用于对外部数据的传输。 •全双工串行口: AT89C51内置一个全双工串行通信口,用于与其它设备间的串行数据传送,该串行口既可以用作异步通信收发器,也可以当同步移位器使用。 •中断系统: AT89C51具备较完善的中断功能,有两个外中断、两个定时/计数器中断和一个串行中断,可满足不同的控制要求,并具有2级的优先级别选择。 •时钟电路: AT89C51内置最高频率达12MHz的时钟电路,用于产生整个单片机运行的脉冲时序,但AT89C51单片机需外置振荡电容。 单片机的结构有两种类型,一种是程序存储器和数据存储器分开的形式,即哈佛(Harvard)结构,另一种是采用通用计算机广泛使用的程序存储器与数据存储器合二为一的结构,即普林斯顿(Princeton)结构。INTEL的MCS-51系列单片机采用的是哈佛结构的形式,而后续产品16位的MCS-96系列单片机则采用普林斯顿结构。 下图是MCS-51系列单片机的内部结构示意图2。 图2 MCS-51的引脚说明: MCS-51系列单片机中的8031、AT89C51及8751均采用40Pin封装的双列直接DIP结构,右图是它们的引脚配置,40个引脚中,正电源和地线两根,外置石英振荡器的时钟线两根,4组8位共32个I/O口,中断口线与P3口线复用。现在我们对这些引脚的功能加以说明: MCS-51的引脚说明: MCS-51系列单片机中的8031、AT89C51及8751均采用40Pin封装的双列直接DIP结构,右图是它们的引脚配置,40个引脚中,正电源和地线两根,外置石英振荡器的时钟线两根,4组8位共32个I/O口,中断口线与P3口线复用。现在我们对这些引脚的功能加以说明:如图3 图3 Pin9:RESET/Vpd复位信号复用脚,当AT89C51通电,时钟电路开始工作,在RESET引脚上出现24个时钟周期以上的高电平,系统即初始复位。初始化后,程序计数器PC指向0000H,P0-P3输出口全部为高电平,堆栈指针写入07H,其它专用寄存器被清“0”。RESET由高电平下降为低电平后,系统即从0000H地址开始执行程序。然而,初始复位不改变RAM(包括工作寄存器R0-R7)的状态,AT89C51的初始态。 AT89C51的复位方式可以是自动复位,也可以是手动复位,见下图4。此外,RESET/Vpd还是一复用脚,Vcc掉电其间,此脚可接上备用电源,以保证单片机内部RAM的数据不丢失。 图4 •Pin30:ALE/ 当访问外部程序器时,ALE(地址锁存)的输出用于锁存地址的低位字节。而访问内部程序存储器时,ALE端将有一个1/6时钟频率的正脉冲信号,这个信号可以用于识别单片机是否工作,也可以当作一个时钟向外输出。更有一个特点,当访问外部程序存储器,ALE会跳过一个脉冲。 如果单片机是EPROM,在编程其间, 将用于输入编程脉冲。 •Pin29: 当访问外部程序存储器时,此脚输出负脉冲选通信号,PC的16位地址数据将出现在P0和P2口上,外部程序存储器则把指令数据放到P0口上,由CPU读入并执行。 •Pin31:EA/Vpp程序存储器的内外部选通线,8051和8751单片机,内置有4kB的程序存储器,当EA为高电平并且程序地址小于4kB时,读取内部程序存储器指令数据,而超过4kB地址则读取外部指令数据。如EA为低电平,则不管地址大小,一律读取外部程序存储器指令。显然,对内部无程序存储器的8031,EA端必须接地。 在编程时,EA/Vpp脚还需加上21V的编程电压。 4 相关知识 4.1数码管显示 在本任务中用4位数码管显示当前数值的千,百,十,个,由于数码管个数多,如采用静态显示方式,则占用单片机的I/O口线太多,如果用定时器/计数器的串行移位寄存器工作方式及外接串入并出移位寄存器74LS164的方式,则电路复杂。所以,在数码管个数较多时,常采用动态显示方式。 如图1-1所示为单片机应用系统中的一种数码管动态显示电路图,4位数码管的相同段并联在一起,由一个8位I/O(P1口)输出字形码控制显示某一字形,每个数码管的公共端由另外一个I/O口(P0口)输出的字位码控制,即数码管显示的字形是由单片机I/O口输出的字形码确定,而哪个数码管点亮是由单片机I/O口输出的字位码确定的。4个数码管分时轮流循环点亮,在同一时刻只有1个数码管点亮,但由于数码管具有余辉特性及人眼具有视觉暂留特性,所以适当地选取循环扫描频率,看上去所有数码管是同时点亮的,察觉不出闪烁现象。动态显示方式所接数码管不能太多,否则会因每个数码管所分配的实际导通时间太少,使得数码管的亮度不足。在本任务中,为了简便,字形码和字位码都没由加驱动电路,在实际应用中应加驱动电路。数码管有共阴极和共阳极两种,对于共阳数码管,字形驱动输出0有效,字位驱动输出1有效;而对于共阴数码管则相反,即:字形驱动输出1有效,字位驱动输出0有效。 4.2矩阵按键 键盘是单片机系统中最常用的人机对话输入设备,用户通过键盘向单片机输入数据或指令。键盘控制程序需完成的任务有:监测是否有键按下,有键按下时,在无硬件去抖的动电路时,应用软件延时方法消除按键抖动影响;当有多个键同时按下时,只处理一个按键,不管一次按键持续多长时间,仅执行一次按键功能程序。 矩阵按键扫描程序是一种节省IO口的方法,按键数目越多节省IO口就越可观,思路:先判断某一列(行)是否有按键按下,再判断该行(列)是那一只键按下。但是,在程序的写法上,采用了最简单的方法,使得程序效率最高。本程序中,如果检测到某键按下了,就不再检测其它的按键,这完全能满足绝大多数需要,又能节省大量的CPU时间。 本键盘扫描程序的优点在于:不用专门的按键延时程序,提高了CPU效率,也不用中断来扫描键盘,节省了硬件资源。另外,本键盘扫描程序,每次扫描占用CPU时最短,不论有键按下或者无键按下都可以在很短的时间完成一次扫描。 本键盘扫描子程序名叫key,每次要扫描时用lcall key调用即可。 5 计算器硬件电路设计 AT89C51单片机的P2口作键盘口,其中P2.4-P2.7为键盘扫描输出线,P2.0-P2.3为键盘扫描输入线。键盘由4*4共16个按键组成,10个数字键(由0-9组成)5个运算符号(加减乘除等于)组成,1个清除键(作用相当于整体复位)。4个数码管用于显示当前数值的千,百,十,个,采用动态显示方式,P1口接4个数码管的七段,P0口分别接4个数码管的公共端,P1口输出数码管的字形码,P0口输出数码管的字位码。 6 计算器程序设计 6.1存储单元分配 30H单元:数值个位显示单元;31H单元:数值十位显示单元;32H单元:数值百位显示单元;33H单元:数值千位显示单元;23H单元:第一操作数存储单元;24H单元:第二操作数存储单元;25H单元:键值暂存单元;27H单元:清除键状态;34H-37H单元:结果数据转换暂存单元;38H-39H单元:结果高低8位暂存单元;R5单元:操作数计数单元;R4单元:操作数数值位数计数单元;R3单元:运算符号存储单元。 6.2 主程序设计 主程序进行程序中用到的一些存储单元的初始化,数值显示和4*4键盘扫描。首先,进行存储单元初始化,给数码管显示单元30H-33H赋予“0000”字形数据,将数值计数单元,存储单元,23H-25H,34H-37H,38H,39H,3AH,3BH,3CH,赋予初值零。之后,调用键盘扫描子程序,和数码管显示数据转换程序,数码管动态显示子程序。主程序不断进行键盘扫描,数码管显示数据转换子程序和动态显示子程序。 6.3 数码管显示数据转换子程序CONV 由于数值单元存放的是二进制数,而用户熟悉的是十进制数,所以应将数值单元中的二进制转换为十进制数,即BCD码。要通过数码管显示出当前数值,还必须将BCD码进一步转换为七段码,转换的最终结果数据存放于显示缓冲区30H-33H单元中,其中30H单元存放数值的个位七段码,31H单元存放数值的十位七段码,32H单元存放数值的百位七段码,33H单元存放数值的千位七段码。 6.4 数码管动态显示子程序 本任务由P1口输出字形码,P0口输出字位码。先将存放于30H单元的数值个位七段码由P1口输出,同时P0口输出使数值个位显示数码管点亮的字位码。由于采用的是共阳数码管,所以只有该位数码管对应的P0.0为1,其他位P0.1-P0.3位0,点亮延时10MS。然后P1口输出数值十位七段码,P0.1位1,数值十位数码管点亮,延时10MS。接着P1口输出数值百位七段码,P0.2为1,数值百位数码管点亮,延时10MS。最后P1口输出数值千位七段码,P0.3为1,数值千位数码管点亮,延时10MS。 7 系统硬件设计 选用设备AT89C51单片机一片,选用设备:AT89C51单片机一片,17个键盘,4位共阳极的七段数码管一个,连线若干,电容3个,电阻5个,晶振1个。 7.1 系统总框图如下:
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彭就是我的姓i

你的鼓励是我创作的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值