长沙民政职业技术学院
课 程 设 计 报 告
课 题 名 称:
51 单片机的计算器设计
课
专
程:
业:
单片机技术及应用
应用电子技术
周扬
17
学生姓名
学
班
号
级
指导老师
孔计
15
张娇
14
0733
0733
方跃春老师
陈实
19
应用电子技术教研室
2009 年 9 月 2 日
一、课题任务及要求
要求:1、掌握数码管移位动态扫描显示的编程方法
2、掌握矩阵扫描的编程方法
3、掌握数据在内部运算的编程方法
任务:1、实现最大 6 位正整数加、减、乘、除
2、具备清零、等于功能
3、16 个按键功能依次为: 数字 0、数字 1、数字 2、数字 3、数字 4、
数字 5、数字 6、数字 7、数字 8、数字 9、清零、等于、加、减、乘、
除
1. 原理图
二、硬 件 设 计
2. 原理分析
该设计通过 89C51 芯片控制 6 个一位数码管显示,并实时检测按键按下情
况来实现计算器功能,16 个按键有 10 个为数字按键 其他 6 个分别为加、
减、乘、除、复位、等于
电路接上电源后 数码管显示个位显示数字 0 ,芯片对按键进行实时扫描,
通过矩阵键盘进行计算,特别注意的是,当结果为负数时,数码管显现 EORR。
(一)、硬件部分
1、数码管为一位共阴数码管,共 6 个;故在段码输出口外加 NPN 型三极管
作驱动
2、51 芯片 P1 口接键盘端(矩阵按键)、P3 口接段码、P2 口的 P2_0—P2_5
接位码
3、按键为四乘四矩阵,共 16 个键
(二)、软件部分
1、数码管移位显示的实现是通过标志位 wei2 的数值变化控制 dispiay 函
数显示位来实现的
2、程序的重要算法是通过类型为 unsigned int 的数 temp 和数组 str[]实
现整体加减乘除、各位显示的 只要弄懂这一算法,此程序就可轻易掌握
3. PCB 图
略。
4. 元件清单及造价预算
按键
万用板
20 个 单价 0.2 元
总计 4 元
2 块 单价 4 元
总计 8 元
一位共阴数码管 6 个 单价 2 元
总计 2 元
三极管
1K 电阻
7 个 单价 0.2 元
总计 1.4 元
20 个 单价 0.01 元
总计 2 毛
排插及排线
5 对 单价 1 元
电容
晶振
3 个 单价 0.2 元
1 个 单价 1 元
8051 芯片
1 个 单价 6 元
总计 5 元
总计 6 毛
总计 1 元
总计 6 元
费用总计 26.2 元
5.实物照片
三、程 序 设 计
头程序
str[6]=str[5]=str[4]=str[3]=str[2]=str[1]=10;
str1[6]=str1[5]=str1[4]=str1[3]=str1[2]=str#include
//51
//IO 端口定义 (矩阵扫描后 4 位端口)
//循环位移头文件
单片机基本定义头文件
#include
#define uchar unsigned char //宏定义
#define uint unsigned int
sbit P1_4=P1^4;
sbit P1_5=P1^5;
sbit P1_6=P1^6;
sbit P1_7=P1^7;
uchar i,num,s;
//全局变量定义
uchar wei,wei2,ss,ss1,ss2,str1[]={0,0,0,0,0,0,0};
long temp,temp1,str[]={10,10,10,10,10,10,10};
uchar code dutable[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,
0x82,0xf8,0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e};
uchar code wetable[]={
0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
void init();
void panduan();
void display();
void delay(uint z);
void shaomiao();
void main()
{
//段位编码
//函数声明
//主函数
init();
while(1)
//调用变量初始化函数
//大循环
{
}
}
void init()
{
shaomiao();
display();
//调用矩阵扫描加处理函数
//调用显示函数
//变量初始化函数
ss2=0;
wei2=1;
temp1=0;
ss=0;
ss1=0;
temp=0;
wei=0;
num=0;
}
void delay(uint z)//延时函数(单位 ms)
{
uchar i;
uint j;
for(j=z;j>0;j--)
for(i=114;i>0;i--);
}
void shaomiao()
{
//扫描加处理函数
for(i=0,s=0xfe;i<4;i++)
//低四位端口依次赋值 1
{
P1=s;
panduan();
s=_crol_(s,1);
s=s|0xf0;
}
}
void panduan()
{
//对 P1 口赋值
//调用判断处理函数
//s 循环位左移
//进行位或运算
(使高 4 位复原)
uchar n;
if(P1_4==0||P1_5==0||P1_6==0||P1_7==0)
{
delay(10);
P1=s|0xf0;
if(P1_4==0||P1_5==0||P1_6==0||P1_7==0)
{
if(P1_4==0)
{ n=1;num=i*4+n-1;}
else if(P1_5==0)
{ n=2;num=i*4+n-1;}
else if(P1_6==0)
{ n=3;num=i*4+n-1;}
else if(P1_7==0)
{ n=4;num=i*4+n-1;}
if(num<10&&wei!=7)
{
wei++;
if(ss1==1)
{
temp=0;
str[6]=str[5]=str[4]=str[3]=str[2]=str[1]=10;
str1[6]=str1[5]=str1[4]=str1[3]=str1[2]=str1[1]=0;
ss1=0;
}
temp=str[1];
temp=str[1]*10+str[2];
temp=str[1]*100+str[2]*10+str[3];
temp=str[1]*1000+str[2]*100+str[3]*10+str[4];
str[wei]=num;
if(str[1]!=10)
if(str[2]!=10)
if(str[3]!=10)
if(str[4]!=10)
if(str[5]!=10) temp=str[1]*10000+str[2]*1000+str[3]*100+str[4]*10+str[5];
if(str[6]!=10)
temp=str[1]*100000+str[2]*10000+str[3]*1000+str[4]*100+str[5]*10+str[6];
}
if(num>=10)
{
1[1]=0;
wei=0;
if(num==10)
{
temp=0;
wei=0;
temp1=0;
ss=0;
wei2=1;
}
if(ss1==0&&num==11||(ss1==0&&ss2!=0&&num>11&&num<16))
{
if(num==11)
ss2=0;