课程设计报告

时间:2024.4.20

《单片机原理与应用》

课程设计报告书

         课题名称:电子计算器

*姓名:

*学号:

*学院:

*专业:

*方向:

*指导教师:

           

             20##年5月30日

                                 目录

设计要求…………………………………………………………………3

设计过程…………………………………………………………………3

一、系统总体设计方案规划与选定……………………………………3

二、硬件设计……………………………………………………………3

   1、硬件组成…………………………………………………………3

   2、硬件连接…………………………………………………………6

三、软件设计……………………………………………………………7

四、调试…………………………………………………………………7

    1、软件调试步骤…………………………………………………7

    2、具体调试过程…………………………………………………8

五、新增功能及实现方法……………………………………………8

六、小结与体会………………………………………………………9

七、参考文献…………………………………………………………10

八、附录(程序、电路图)…………………………………………10

   1、附录一  程序………………………………………………10

    2、附录二  连接图……………………………………………20

设计要求:

   1.设计一个电子计算器,实现两个4位数(包括整数和小数)的加、减、乘、除运算功能。

     2.要求数据的输入及运算结果的显示与我们平时使用的计数器相同;

     3.采用8279接口4*6键盘及8位LED显示器。

     4.可以用汇编语言或是c语言

     5.鼓励创新,增添附加功能

一、系统总体设计方案规划与选定

    1、8279的功能是:对键盘进行管理控制,自动扫描键盘;对LED显示器进行控制、对显示数据、显示方式进行管理。

    8279芯片对键盘进行扫描,当有按键按下时,数据被写入FIFO,产生中断,数据送单片机进行运算,运算结果回馈8279,8279控制数据显示到LED数码管。

    2、(1)初始化8279及清零:选择键盘和显示方式,根据外接的CLK频率选定定标值,使内部时钟为100kHz,选择写显示RAM方式,选择读FIFO RAM方式。

    (2)键盘程序:当有键被按下时,8279通过粗扫描感知到,然后通过细扫描确定被按下的键码,然后产生中断。

    (3)显示程序:只需将字形码输出到数据口,8279即会按规定的方式写入显示RAM,并通过动态扫描进行动态显示。

二、硬件设计

1、硬件组成

    1、单片机采用89C51,本次课设用到的管脚及其功能解析如下

         

Vcc:接+5V电源

Vss:接地端

ALE:与8279的CLK引脚相连,使8279和系统时钟同步

P0--P7口:输入、输出口, 作地址、数据总线

2、8279

                  

8279是一款由+5V电源供电的可编程键盘显示接口芯片。

RD、WR、CS分别与单片机的对应接口相连,AD[0..7]与单片机的P0--P7相连,RL[0..7]接键盘的列,OUT_A0-----OUT_A3及OUT_B0—OUT_B3是输出,接八位数码管的段选。

其功能是:对键盘进行管理控制;

对LED显示器进行控制、对显示数据、显示方式进行管理

3、74HC138译码器

                      

A,B,C分别接8279的SL0—SL2,Y0—Y7连接锁存器后对键盘进行行扫描,并控制八位数码管的位选。

4、74HC373锁存器

                 

将译码结果锁存在Q端,使信号暂时不受D端信号的影响,将扫描信号由Q端送入键盘和显示器。

5、键盘

    

选用4×6键盘,行线连接8279 SL端经译码输出信号进行行扫描,列线连接8279的SL端。

有键被按下时,通过行列扫描,确定是哪个键被按下。

6、八位共阴极LED数码管

左侧八个接口连接段选,右端八个接口连接位选。

2、硬件连接  

将单片机的P0口连接到8279的AD端,8279的OUT_B和OUT_A通过一个74HC373接到LED显示器的段选。8279的CS端和51的P2.7相接;A0与P2.0相接;RD和WR分别与51单片机相接;IRQ通过一个非门与51的INT1相接以产生外部中断;CLK与51的ALE相接以采用相同的时钟频率。RES隔电容接高电平,隔电阻接地。74HC138的E1接高电平,E2和E3接地。74HC373的LE接高电平,OE接地。

键盘由4*6的开关阵组成,显示采用8位共阴极LED显示器,并都采用74HC373来提高驱动能力。将8279的扫描信号输出端通过三八译码器分别接到显示器的片选线和按键矩阵的每一行上。按键矩阵的每一列都连接到8279的RL输入端。

三、软件设计

    (1) 初始化8279:选择键盘和显示方式,键盘采用中断方式,对单片机开中断。根据外接的CLK频率选定定标值,使内部时钟为100kHz,选择写显示RAM方式,选择读FIFO RAM方式,并通过控制口向8279发送读键码指令。

     (2) 结果显示:只需将字形码输出到数据口,8279即会按规定的方式写入显示RAM,并通过动态扫描进行动态显示到八位LED数码管。

     整数部分:根据整数的位数,把待显示数除以10的倍数并取整,即得到每一位的值,然后查出每一位的字形码,依次写显示RAM即可在LED上显示得数。

    小数部分:根据小数的位数,把待显示数除以0.1的倍数并取整即得到每一位的小数值,然后查出每一位的字形码,依次写显示RAM即可在LED上显示得数。(小数部分默认显示7位,然后通过从后往前查询最后一位是否是0,然后将末尾的0删掉,只显示非0部分)

    (3) 键盘程序:采用中断方式,当有键按下时,产生中断,在中断服务中读取按键数据,经过查键功能表,即可查得此键功能.如果按下的是数字键,会将此数字存储到一个数组中,同时将这个数字显示出来。如果按下的是运算符键,将把此运算符记下并将运算符前的数求出来,然后清除显示。如果按下等号键,会将运算符后面的数求出来并且根据运算符将运算结果算出来并显示出来。如果按下清零键,会将数字数组、显示、符号位等等都清零,即最右端显示0。

四、调试

一.软件调试步骤

    1、新建工程:打开Keil软件,在Project菜单中选择New Project命令,建立一个新项目,然后存盘并输入工程文件名(不用写文件格式)。

2、新建文件:新建文件,输入源程序代码,保存文件并令文件格式为.c

3、把源文件添加到工程中:鼠标右键选中Source Group 1,然后添加文件到工程中,选择要添加的文件(即刚才的.c文件)

4、设置对象选项:点击“Options for Target”,设置Output、Target、Debug选项

5、编译:对项目文件进行编译。若出现errors、warnings时,按照指示,检查出错原因。

6、用Proteus仿真软件画出电路图,点击AT89C51,添加.hex文件,点击开始进行仿真。

7.对仿真的计算器进行操作,选择典型计算方式及典型数据进行计算,验证显示结果是不是自己的设计初衷。

二、具体调试过程

    由于第一次接触Keil和Proteus,感觉生疏异常,于是,上网百度找教程,最后终于弄清了Keil和Proteus的使用步骤。

    在51里烧进程序后,一经运行,八位数码管就显示8个8,经过多番尝试及请教高人,最后在仔细研究电路图后,终于发现了问题所在,原来是引出8279的一根粗线没有贴标签。贴上标签后,立马一切正常了。

五、新增功能及实现方法

1、开平方运算:X^(1/2)

实现方法:输入一个数后,内部程序会进行求数运算,并显示该数,按下该键后, 由自带函数sqrt求得开方,按下等号后显示计算结果。        

2、取倒数运算:X^-1

按下第一个数后,将其值算出并显示,按下改键后,求1/X运算,并将结果显示。

3、清除键:Clear

按下改键后,将执行清除命令。

4、求阶乘:!

执输入一个整数X后,按下该键,会执行X*(X—1)*(X—2)*(X—3)*1运算,并将结果显示。

5、求平方:X^2

按下一个数字X后,按下改键,便会执行X*X运算,按下等号后,将结果显示。

6、求立平:X^3

按下一个数字X后,按下改键,便会执行X*X*X运算,按下等号后,会将结果显示。

7、求N次方:X^N

按下一个数字X后,按下该键,再按下数字N,便会执行一个循环命令,求出X^N,并显示。

六、小结与体会

    本次课程设计的要求是设计一个电子计算器,实现两个4位数(包括整数和小数)的加、减、乘、除运算功能。刚看到设计题目及要求时,顿觉非常困惑,感觉这要求超出了我的能力范围、无从下手。但是,随着翻看的有关单片机的教材及课程设计实例的增加以及跟同组及其他组同学多次的探讨研究,慢慢地,感觉逐渐对8279及51的各个接口及中断有了大体的概念,并且,逐渐地,课设的思路不知不觉间在大脑中慢慢形成。

    当课设真正进行的时候,豁然发现,头脑中的念相与实际能够做出来的差距是何等的大。在设计过程中,遇到很多的困难,如Keil及Proteus软件的安装,以前学过UG,感觉UG软件很难安装,没想到,Proteus安装起来也是很不简单的,再比如程序的调试,辛辛苦苦写的程序,编译时显示大量的errors、warnings确实是一件极其痛苦的事情,但是历经审查、修改,最后程序完全正确了,烧入单片机后,可以按照要求进行运行了,那种快乐也是无法用三言两语形容的。

    在本次课程设计中,控制电路选取AT89C51单片机,同时选取能够对键盘和LED实现控制和管理的8279芯片,它能自动扫描行列值,控制LED的显示,使得控制便利化,可通过软件实现实时控制,大大提高CPU的工作效率。键盘方面使用4×6键盘,分别对不同的键赋予功能,而显示器采用动态显示。由于感觉本软件用汇编语言会比较困难,因此采用C语言编程,其中由于编程不熟练遇到了很多新的难题,通过查找C语言课本复习了C语言的语法,把困难一一解决了(感觉自己的C语言水平又上升了数个台阶)。

    通过这次课设,我认识到只有书本知识是万万不够的,我们还要多动手,多实际操作,让知识从实践中来,到实践中去。通过实践,不仅可以检验自己所学、所理解的知识是不是正确的,是不是可以带动生产力进步的,而且可以加深对知识的掌握,进而可以为学好新知识打下良好基础,更好地去学习新知识。

    通过这次课程设计,我更加认识到合作的重要性,自己解决不了的问题,通过与同学探讨,往往可以轻而易举地把问题解决,毕竟,群众的力量是无穷的。

   

七、参考文献

1、《单片机原理、接口及应用》(第二版)   肖看  李群芳    编著

2、《单片微型计算机原理及应用》 张毅坤 西电

3、《Keil Cx51 V7.0单片机高级语言编程与uVision2应用技术》 徐爱钧 电子工业出版社

4、80C51单片机原理与应用技术   吴炳胜等编著

八、附录(程序、电路图)

附录一    程序

 #include<reg51.h>

#include<math.h>

#include<.absacch>

#define uint unsigned int

#define unch unsigned char

#define D8279 XBYTE[0x7EFF]

#define CTRL8279 XBYTE[0x7FFF]

uint a[10]={0};       //参与计算的数

uint jieshou;     //8279返回值

unch  i;            //数组的第i位数

uint  led[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

unch  geshu;    //输入的数字和符号的个数

unch   shuru;  //表示输入的数字

unch   shuzigeshu; //输入的数字的个数

unch   zhengshugeshu;//小数计算,整数的位数

float shuq;         // 参与计算的第一个数

float shuw;           //    参与计算的第二个数

unch  jisuanfangshi;  //要使用的计算方式

unch  xiaoshudian;   //是否使用小数点

unch key;   //表示按键所代表的意义

unch  Q;    //表示小数点前的led显示的数

void clear()                       //总清除

{

CTRL8279=0xd1;                

   jieshou=CTRL8279;

   jieshou&=0x80;         //读出8279的状态寄存器中显示的状态,读DU位

   while(jieshou==0x80)                 //确认清除完毕

     {

          jieshou=CTRL8279;            

          jieshou&=0x80;

     }

}

void chushihua()  //初始化

{

 CTRL8279=0x90;  //写显示RAM,地址自动加一//

 CTRL8279=0x34;               //定标//

 CTRL8279=0x10;               //8个字符显示右边输入,编码扫描,键盘锁定//

}

void shuzuqingchu()

{

for(i=0;i<10;i++)

       a[i]=0;

            i=0;

}

void yunsuanqingchu()

{

             xiaoshudian=0;

         zhengshugeshu=0;

             shuzuqingchu();

}

void scan()   //清零

{

      geshu=0;                     //记录数字个数的变量清0

      shuzigeshu=0;                        //记录数字和符号个数的变量清0

     shuw=0;

      shuq=0;

      shuru=0    ;

    zhengshugeshu=0;

      jisuanfangshi=0;

      xiaoshudian=0;               

    clear();         

    D8279=0xbf;

}

void jisuan1()

{

    uint  j;

      float middle=0.1;

           shuq=0;

             if(xiaoshudian==0)

             zhengshugeshu=shuzigeshu;

   for(j=0;j<zhengshugeshu;j++)

   {

       shuq=a[j]+shuq*10;

      }

      if(xiaoshudian==1)

      { 

      shuq=1.0*shuq;

      for(j=zhengshugeshu;j<shuzigeshu;j++)     

      {

      shuq=shuq+a[j]*middle;

      middle=middle*0.1;

      }

      }

      geshu=0;

      shuzigeshu=0;

}

void jisuan2()

{

    unch  j   ;

      float middle=0.1;

           shuw=0;

              if(xiaoshudian==0)

             zhengshugeshu=shuzigeshu;

   for(j=0;j<zhengshugeshu;j++)

   {

       shuw=a[j]+shuw*10;

      }

      if(xiaoshudian==1)

      { 

      shuw=1.0*shuw;

      for(j=zhengshugeshu;j<shuzigeshu;j++)     

       {

      shuw=shuw+a[j]*middle;

      middle=middle*0.1;

      }

      }

      geshu=0;

    shuzigeshu=0;

}

void suanshufangshi()

{

   float m ;

   chushihua();

   shuq=shuq*1.0 ;

   shuw=shuw*1.0;

   if(jisuanfangshi==1)

   shuq=shuq+shuw;

   if(jisuanfangshi==2)

   shuq=shuq-shuw;

   if(jisuanfangshi==3)

   shuq=shuq*shuw;

   if(jisuanfangshi==4)

   shuq=1.0*shuq/shuw;

   if(jisuanfangshi==5)

   {

   m=shuq;

   shuq=1;         

   for(;m>0;m--)

   shuq=shuq*m;

   }

   if(jisuanfangshi==6)

   shuq=shuq*shuq;

   if(jisuanfangshi==7)

   for(;shuw>0;shuw--)

   shuq=shuq*shuq;

   if(jisuanfangshi==8)

   shuq=1/shuq;

}

void xianshijieguo(float xianshishu)

{   

uint j;     //循环次数计量

uint n;    //整数个数

uint m;            //整数输出

float y;         //复杂小数的整数部分

uint k;       //复杂小数的循环次数

float r;   //复杂小数的小数部分

unch z[9];     //小数输出

uint zhongjianliang; 

chushihua();

   if(xianshishu==(long)xianshishu)                      //整数的显示

   {

   n=(long)(log10(xianshishu))+1;

      for(j=0;j<n;j++)

       {

        m=xianshishu;

        xianshishu=(long)(xianshishu/10);

            m=m-xianshishu*10;

         z[j]=m;

            }

             for(j=0;j<n;j++)

             a[j]=z[n-j-1];

         for(j=0;j<n;j++)

             D8279=led[a[j]];

   j=0;

   m=0;

      for(j=0;j<n;j++)

       {

       z[j]=0;

       a[j]=0;

       }

   }

  

   else                           //计算小数

   {

       if ((long)xianshishu==0)              //计算简单小数

       {

       D8279=0xbf;

            for(j=0;j<6;j++)

            {

          m=(long)(xianshishu*10);

          xianshishu=xianshishu*10-m;

          D8279=led[m];

            }

       m=0;

       j=0;

       }

       else                                                            //计算复杂小数

       { 

         y=(long)(xianshishu);

        n=(long)(log10(xianshishu))+1 ;

             for(j=0;j<n;j++)

             {

            m=y;

            y=(long)(y/10);

                    m=m-y*10;

                  z[j]=m;

                }

             for(j=0;j<n;j++)

             a[j]=z[n-j-1];

         for(j=0;j<n;j++)

                   {

                     if(j<n-1)

                    D8279=led[a[j]];

              if(j==n-1)

                     D8279=led[a[j]]|0x80;

                    }      

             r=xianshishu-(long)xianshishu;

           for(k=0;k<(8-n);k++)

           {

             r=r*10;

             z[k]=(long)r;

             r=r-z[k];

           }

      while(z[k]==0)

      k--;

        zhongjianliang=k+1;

          for(k=0;k<zhongjianliang;k++)

          {

         D8279=led[z[k]];

              }

        y=0;

        n=0;

        k=0;

        i=0;

        for(k=0;k<8;k++)

        z[k]=0;

      }

   }

}

int1( ) interrupt 2 //计算器矩阵键盘扫描中断函数,从左到右,从上到下

{

    if(geshu==0) //没输入数字时,进行初始化

    chushihua();

       CTRL8279=0x40;                     //发送读FIFO/RAM命令//

       shuru=D8279;

   switch(shuru)

   {

   case 0x04:   key=0;

                a[i]=0;

                        i++;

                        geshu++;

                        shuzigeshu++;

                        D8279=0x3f;

                        break;

   case 0x0c:    key=1;

                a[i]=1;

                        i++;

                        geshu++;

                        shuzigeshu++;

                        D8279=0x06;

                        break;

   case 0x0b: key=2;

                a[i]=2;

                        i++;

                        geshu++;

                        shuzigeshu++;

                        D8279=0x5b;

                        break;

      case 0x0a: key=3;

                a[i]=3;

                        i++;

                        geshu++;

                        shuzigeshu++;

                        D8279=0x4f;

                        break;

      case 0x14: key=4;

                a[i]=4;

                        i++;

                        geshu++;

                        shuzigeshu++;

                        D8279=0x66;

                        break;

      case 0x13: key=5;

                a[i]=5;

                        i++;

                        geshu++;

                        shuzigeshu++;

                        D8279=0x6d;

                        break;

      case 0x12: key=6;

                a[i]=6;

                        i++;

                        geshu++;

                        shuzigeshu++;

                        D8279=0x7d;

                        break;

      case 0x1c: key=7;

                a[i]=7;

                        i++;

                        geshu++;

                        shuzigeshu++;

                        D8279=0x07;

                        break;

      case 0x1b: key=8;

                a[i]=8;

                        i++;

                        geshu++;

                        shuzigeshu++;

                        D8279=0x7f;

                        break;

      case 0x1a: key=9;

                a[i]=9;

                        i++;

                        geshu++;

                        shuzigeshu++;

                        D8279=0x6f;

                        break;

      case  0x03:   key='.';

                   geshu++;

                         zhengshugeshu=shuzigeshu;

                         CTRL8279=0x60+zhengshugeshu-1; 

                         Q=D8279;

                 CTRL8279=0x80+zhengshugeshu-1;

                 D8279=Q|0x80;

                 xiaoshudian=1;

                         CTRL8279=0x90+zhengshugeshu;                

                         break;                                        

        case   0x02:  key='=';

                           jisuan2();

                           suanshufangshi();

                           xianshijieguo(shuq);

                           break;

        case   0x19:   key='+';

                              jisuanfangshi=1;

                              jisuan1();

                              yunsuanqingchu();

                              clear();

                              chushihua();

                               break;

       case   0x11:    key='-';                

                              jisuanfangshi=2;

                              jisuan1();

                              yunsuanqingchu();

                              clear();

                              chushihua();

                               break;

       case  0x09:     key='*';

                      jisuanfangshi=3;

                              jisuan1();

                              yunsuanqingchu();

                              clear();

                              chushihua();

                               break;

      case   0x01:     key='/' ;

                      jisuanfangshi=4;

                              jisuan1();

                              yunsuanqingchu();

                              clear();

                              chushihua();

                               break;

      case   0x18:       key='!';

                                jisuanfangshi=5;

                              jisuan1();

                              yunsuanqingchu();

                              clear();

                              chushihua();

                               break;

      case   0x10:         key='p' ;

                         jisuanfangshi=6;

                              jisuan1();

                              yunsuanqingchu();

                              clear();

                              chushihua();

                               break;

      case   0x08:         key='^';

                                jisuanfangshi=7;

                              jisuan1();

                              yunsuanqingchu();

                              clear();

                              chushihua();

                               break;

      case  0x00:           key='d'  ;

                                 jisuanfangshi=8;

                              jisuan1();

                              yunsuanqingchu();

                              clear();

                              chushihua();

                               break;

      case  0x1d:           clear();

                        chushihua();

                                shuzuqingchu();

                                yunsuanqingchu();

                                scan();

                                break;

      case  0x15:

                                break;

      case  0x0d:

                                 break;

      case 0x05:

                                  break;

   }

}

void main()

{

clear(); //总清除

chushihua(); //8279初始化

scan();

IT1=0;     //设置INT1中断方式为低电平

EX1=1;    //允许INT1中断

EA=1;     //CPU允许中断

while(1);     //等待中断           

附录二    硬件连接图  

更多相关推荐:
课程设计报告

1课程设计目的课程设计是船舶设计原理课程重要的实践性教学环节是培养学生掌握船舶设计基本原理和能力的技术基础主尺度论证与总布置设计是船舶总体设计的重要组成部分通过课程设计的训练力求使学生实现从学生到船舶设计师的角...

课程设计报告内容

一设计目的1强化上机动手能力在理论和实践的基础上进一步巩固数据结构课程学习的内容掌握工程化软件设计的基本方法2掌握图的创建和应用3掌握迪杰斯特拉以及Prim等基本算法思想4掌握if语句及switch语句的运用方...

课程设计报告

中国计量学院信息工程学院课程设计报告课程设计名称系统设计与仿真课程计二级学院信息工程学院专业班级10电信2班学姓成绩号名1000301232廖壁波指导老师20xx年12月13日中国计量学院信息工程学院课程设计报...

课程设计报告模板

信息科学与工程学院高级语言程序设计课程设计报告学生成绩管理系统学科专业计算机科学与技术班级1301学号指导教师唐郑熠讲师学生二零年月目录目录1设计任务12需求分析121基础功能122扩展功能13系统概要设计13...

课程设计报告

扬州大学数据结构课程设计报告课题名称姓名学院系科班级指导老师日期自来水管架设问题广陵学院陈宏建1一课程设计的题目自来水管理架设问题问题描述若要在扬州大学的八个居民区A区B区C区D区E区F区G区H区之间架设自来水...

课程设计报告

系统软件课程设计时钟中断与进程调度学号姓名指导教师11070319许明秀金雪云20xx年12月一报告摘要进程调度是操作系统十分重要的一个部分在操作系统的设计过程中进程调度和时钟中断形成了密不可分的关系系统时钟定...

课程设计报告

计算机高级语言课程设计报告班级学号姓名蔡路日期学生成绩管理系统19xx3120xx100031020xx年1月18日一课程设计题目与要求实习题目学生成绩管理系统实习内容C语言面向对象的分析与设计基本要求学生成绩...

课程设计报告模板

江汉大学文理学院课程设计报告课程设计题目现代交通灯控制系统设计部系专业姓名学号指导教师20xx年6月26日目录一设计目的3二设计要求4三总体方案4四具体实现错误未定义书签五实现过程中遇到的问题及措施6六设计心得...

20xx课程设计报告模板

XXXXXXX机电学院电子课程设计报告论文题目多功能电子表设计专业班级电气工程及其自动化123姓名时间20xx060920xx0620指导教师完成日期20xx年06月17日交通灯控制器设计任务书1设计目的与要求...

课程设计报告

课程设计报告课程名称单片机在电力系统的应用课题名称多用户电子式电能表的设计20xx年07月3日前言多用户电子式单相电能表采用单片机作为中央处理器每块电能表可对多达24户的用电情况进行集中检测循环显示各户的用电量...

课程设计报告

HUNANUNIVERSITY工程软件应用课程设计报告20xx年3月18日课程设计题目课程设计时间学生姓名柱塞泵测绘及建模参数化设计20xx年2月27日3月21日何伟成20xx0930303肖宇20xx0430...

C语言课程设计报告(完整版)

大连交通大学软件学院C语言课程设计报告SOFTWAREINSTITUTEOFDALIANJIAOTONGUNIVERSITYEXPERIMENTDESIGNINGC语言课程设计报告ExperimentDesig...

课程设计报告(33篇)