HD7279是一款用于扩展单片机I/O口的芯片,至少我是这么认为的,虽然它占用了单片机4个I/O但是真正作为传输的仅仅是一根总线,它可以同时驱动8位共阴数码管(或者8×8点阵),及8×8的矩阵键盘,而同时接在单片机上的话,至少需要3~4组I/O,当然单总线控制的芯片基本需要自己的指令和时序。
接到这个课程设计之前我自己懒懒散散地看了一段时间的C51(用C语言编写单片机代码),之前老师教的是A51(用汇编编写单片机代码),我玩了很久,但是发现A51真的很局限,汇编这种语言是写给机器看的,真正地写0和写1,真正是一个寄存器一个寄存器的调用,对于8位的51单片机来说,要实现1000×1000或者小数是比较困难的。老师推荐用C,之前只是看书实现过一些小东西这回要做比较大的项目了,虽然还有其他课题比如温度计和数字钟,不过都做过,只是环境不一样,修改一下代码太没有挑战性了。
确实开始轻敌了,真正做的时候发现不是那么简单,
高中的时候学过一点VB做过计算器,如果让我现在做,也许给我几天我可以做出来,用C我也没什么问题,但是C51就有难度了,要考虑太多硬件的东西,特别是显示这个模块好不容易瘦下去的头又两个大了。等我真正意识到的时候,已经过去几个礼拜了,呵呵,要和朋友说抱歉了,虽然我答应“等我做完计算器之后再帮你改下程序”但是没一个实现。
当然,此程序因为基本全是自己写的,被方晋甬老师称之为“程序设计不成熟、比较乱”的,额,本来准备用switch语句,但是吕昂老师说switch语句会产生过多闲置寄存器(可是他没有考虑到我仅仅是实现很少的功能),这段程序只实现+-×÷,符号闪烁,过八位报错等功能但是没有小数,只能计算一步(加少数程序即可计算多部)。其实程序挺早就写出来了,只是一直出不来效果,后来在仿真和VC++编译环境下修改了很多,理论上是可以实现了,可是还是没有显示,于是抓狂了“看来我已处在瓶颈...”,晃了最后一个礼拜,周日周一看了两天晚上,依然没有看出什么来,礼拜二去方晋甬老师办公室请教,查了近3个钟头【基本看过了我所有奇形怪状的子程序—。—||||】,在仿真多遍之后发现就少了一句“while(!key)【检测释放按键】”【程序中红字部分即主程序最后一句】囧啊~~~~以至于周四答辩的时候我演示之后,刚点看ppt他就说直接给A,不用答了。。。。
程序的完整版下载地址:http://www.51hei.com/ziliao/file/jsjq.rar
/////////////////////////////****************程序*****************///////////////////////
#include<reg51.h>
#include<math.h>
sbit cs=P2^6;
sbit clk=P1^0;
sbit dat=P1^1;
sbit key=P3^3;
bit add,sub,mul,div,equ,clr;
unsigned char times,st,l,data_jp,flag,d;
unsigned int tmr;
unsigned long num[8],sn[8],disp[8],sh,result,hp=100000000;
void send(unsigned char);
unsigned char receive(void);
unsigned long real(unsigned long ,unsigned char);
unsigned long calcu(unsigned long, unsigned long);
void display(unsigned long);
unsigned long write_key(unsigned char);
void char_flk(void);
void test(void);
void error(void);
void long_delay(void);
void short_delay(void);
void delay10ms(unsigned char);
/////////**************主函数****************//////////
void main ()
{
times=0;
l=times;
st=0;
flag=0;
test();
while(1)
{
unsigned char i;
if(!key)
{
send(0x15);
data_jp=receive();
cs=1;
d=write_key(data_jp);
if (data_jp<=9)
{
flag=0;
num[times]=d;
}
else
{
flag=1;
//times-=1;
}
if(flag!=1)
{
if(num[0]==0)
{
times=0;
continue;
}
if(7>times>=1)
{
send(0xa1);
}
send(0x80);
send(num[times]);
while(!key);
delay10ms(1);
times=times+1;
cs=1;
if(times>7)
{
send(0xa4);
error() ;
times=0;
send(0xa4);
}
}
else
{
send(0xa4);
char_flk();
times-=1;
l=times;
for(i=0;i<=times;i++)
{
num[i]=real(num[i],l);
sh=sh+num[i];
l--;
}
sn[st]=sh;
if(st>=1)
{
result=calcu(sn[st],sn[st-1]);
sn[st-1]=result;
st--;
}
st++;
times=0;
flag=0;
sh=0;
if(equ==1)
{
st=0;
send(0xa4);
display(result);
equ=0;
}
if(clr==1)
{
st=0;
times=0;
flag=0;
sh=0;
add=0;
sub=0;
mul=0;
div=0;
equ=0;
clr=0;
send(0xa4);
}
while(!key);
}
}
}
}
/////////*********************测试子函数****************////////
void test(void)
{
char i;
delay10ms(2);
send(0xbf);
cs=1;
for (i=0;i<=3;i++)
{
delay10ms(100);
}
send(0xa4);
cs=1;
delay10ms(20);
}
///////***********************读键盘程序**************///////
unsigned long write_key(unsigned char data_jp)
{
unsigned char shuzi;
if(data_jp<10)
{
shuzi=data_jp;
}
else
{
if(data_jp==10)
{
add=1;
}
else if(data_jp==11)
{
sub=1;
}
else if(data_jp==12)
{
mul=1;
}
else if(data_jp==13)
{
div=1;
}
else if(data_jp==14)
{
equ=1;
}
else if(data_jp==15)
{
clr=1;
}
shuzi=0xff;
}
return(shuzi) ;
}
///////***********************发送子函数*************//////
void send(unsigned char data_out)
{
unsigned char i;
cs=0;
long_delay();
for(i=0;i<=7;i++)
{
if(data_out&0x80)
{
dat=1;
}
else
{
dat=0;
}
clk=1;
short_delay();
clk=0;
short_delay();
data_out=data_out<<1;
}
dat=0;
}
/////************************接收键盘子函数************//////
unsigned char receive(void)
{
unsigned char i,data_in;
dat=1;
long_delay();
for(i=0;i<=7;i++)
{
clk=1;
short_delay();
data_in=data_in<<1;
if(dat)
{
data_in=data_in|0x01;
}
else
{
data_in=data_in|0x00;
}
clk=0;
short_delay();
}
dat=0;
return(data_in);
}
/////////***************************显示数字处理子函数***********/////////
unsigned long real(unsigned long so, unsigned char s)
{
unsigned char z;
if(s!=0)
{
for(z=0;z<=(s-1);z++)
{
if(s!=0)
{
so=so*10;
}
else
{
so=so;
}
}
}
else
{
so=so;
}
return(so);
}
//////////*************************计算子函数*******************///////////
unsigned long calcu(unsigned long sn0,unsigned long sn1 )
{
if(add==1)
{
sn0=sn0+sn1;
add=0;
}
if(sub==1)
{
sn0=sn1-sn0;
sub=0;
}
if(mul==1)
{
sn0=sn0*sn1;
mul=0;
}
if(div==1)
{
if(sn0>0)
sn0=sn1/sn0;
else
error();
div=0;
}
return(sn0);
}
////////****************************报错错误子函数***************/////////
void error(void)
{
while(key)
{
send(0x96);
send(0x4f);
delay10ms(2);
send(0x95);
send(0x05);
delay10ms(2);
send(0x94);
send(0x05);
delay10ms(2);
send(0x93);
send(0x1d);
delay10ms(2);
send(0x92);
send(0x05);
delay10ms(2);
}
}
///////////********************显示子函数*********////////////
void display(unsigned long display)
{
unsigned char i,asus=8;
if(display>99999999)
error();
else
{
for(i=0;i<=7;i++)
{
if((display/hp)>=1)
break;
else
{
hp=hp/10;
asus-=1;
}
}
for(i=0;i<=asus;i++)
{
disp[i]=display/hp;
if(hp>1)
{
display=display%hp;
hp=hp/10;
}
}
for(i=0;i<=asus;i++)
{
if(i>0)
{ send(0xa1); }
send(0x80);
send(disp[i]);
}
}
}
///////////********************符号判断闪烁显示*********////////////
void char_flk(void)
{
if(add==1)
{
send(0x97);
send(0x77);
}
else if(sub==1)
{
send(0x97);
send(0x01);
}
else if(mul==1)
{
send(0x97);
send(0x37);
}
else if(div==1)
{
send(0x97);
send(0x49);
}
else if(clr)
{
;
}
send(0x88);
send(0x7f);
}
//////************************延时子函数*************///////
void long_delay(void)
{
char i;
for(i=0;i<=25;i++) ;
}
void short_delay(void)
{
char j;
for(j=0;j<=4;j++);
}
void delay10ms(unsigned char time)
{
unsigned char i;
unsigned int j;
for (i=0;i<=time;i++)
{
for(j=0;j<=0x390;j++);
}
}
///////////////////////////************效果图*************////////////////////

以上演示的为9876543÷234,其本来的结果是42207.4487179……无法显示小数位,所以结果为42207 。
