登录  | 立即注册

游客您好!登录后享受更多精彩

扫一扫,访问微社区

QQ登录

只需一步,快速开始

开启左侧

[寒假笔记] 使用LCD1602实现计算器功能

[复制链接]
发表于 2022-1-28 23:23:06 | 显示全部楼层 |阅读模式
学习笔记
学习科目: 单片机
学习安排: 单片机
开始时间: 2022-01-28
结束时间: 2022-01-28
注意在这个计算器程序中,当定时器中断进行keyscan()函数时,我们不能再把P20、P21的电频拉高了(P22、P23仍需要拉高)(这一点和之前的按键功能程序不一样)。因为如果在中断里对P20、P21电频拉高,那么每隔1ms进入中断时,LCD1602的RS与RW引脚的数值都会改变,如果是单片机在运行读状态、写指令、写数据这三个函数时进入了中断,那么P20、P21引脚电频的改变会终止读状态、写指令、写数据这三个函数的运行,即使中断结束,这三条指令也不会再正常运行,导致的结果就是LCD1602连初始化都无法完成。这就需要我们在LCD1602读状态、写指令、写数据的程序运行完毕之后再对P20(RS)、P21(RW)重新赋值,确保这三条指令在运行中即使进入了中断也不会对其造成影响,但此时按键的功能会有所下降,按键的扫描会不准确(不过问题不大,我在使用时就很少出现按键扫描不准确的状况,但还是有的)。

LCD1602实现计算机功能

1、LCD1602.c文件
#include<reg52.h>

#define LCD1602_DB P0         

sbit LCD1602_RS=P2^0;
sbit LCD1602_RW=P2^1;
sbit LCD1602_E=P1^2;
unsigned char i;

void LcdWaitReady()
{
        unsigned char sta=0;
        LCD1602_DB=0xFF;
        LCD1602_RS=0;
        LCD1602_RW=1;
        do
        {
                LCD1602_E=1;
                sta=LCD1602_DB;
                for(i=0;i<2;i++);
                LCD1602_E=0;
        }
        while(sta&0x80);
        LCD1602_RS=1;           
  LCD1602_RW=1;             //P20,P21&#214;&#216;D&#194;&#184;3&#214;μ£&#172;&#189;&#195;&#213;ykeyscan£¨£&#169;oˉêy
       
}
void LcdWritecmd(unsigned char cmd)
{
        LcdWaitReady();  
        LCD1602_RS=0;
        LCD1602_RW=0;
        LCD1602_DB=cmd;
        LCD1602_E=1;
        for(i=0;i<2;i++);
        LCD1602_E=0;
        LCD1602_RS=1;
        LCD1602_RW=1;            //P20,P21&#214;&#216;D&#194;&#184;3&#214;μ£&#172;&#189;&#195;&#213;ykeyscan£¨£&#169;oˉêy
}
void LcdWritedat(unsigned char dat)
{
        LcdWaitReady();  
        LCD1602_RS=1;
        LCD1602_RW=0;
        LCD1602_DB=dat;
        LCD1602_E=1;
        for(i=0;i<2;i++);
        LCD1602_E=0;
        LCD1602_RS=1;
        LCD1602_RW=1;           //P20,P21&#214;&#216;D&#194;&#184;3&#214;μ£&#172;&#189;&#195;&#213;ykeyscan£¨£&#169;oˉêy
}
void LcdSetCursor(unsigned char x,unsigned char y)
{
        unsigned char addr;
        if(y==0)
        {
                addr=0x00+x;
        }
        else
        {
                addr=0x40+x;
        }
        LcdWritecmd(0x80+addr);
}

void LcdShowstr(unsigned char x,unsigned char y,unsigned char *str)
{
        LcdSetCursor(x,y);
        while(*str!='\0')
        {
                LcdWritedat(*str++);
        }
}
void LcdAreaClean(unsigned char x,unsigned char y,unsigned char len)
{
        LcdSetCursor(x,y);
        while(len--)
        {
                LcdWritedat(' ');
        }
}
void LcdFullClaen()
{
        LcdWritecmd(0x01);
}
void initlcd1602()
{
        LcdWritecmd(0x38);     
        LcdWritecmd(0x0C);   
        LcdWritecmd(0x06);   
        LcdWritecmd(0x01);
}


2、keyboard.c文件
#include<reg52.h>

sbit P20=P2^0;
sbit P21=P2^1;
sbit P22=P2^2;
sbit P23=P2^3;
sbit kout1=P2^4;
sbit kout2=P2^5;
sbit kout3=P2^6;
sbit kout4=P2^7;


extern void GetResult();
extern void reset();
extern void Numkeraction(unsigned char n);
extern void Oprtkeyaction(unsigned char type);
extern void LcdShowstr(unsigned char x,unsigned char y,unsigned char *str);

unsigned char pdata keysta[4][4]={
        {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}         //°′&#188;ü×′ì&#172;&#188;ì2a
};
unsigned char code keycodeMap[4][4]={
  {'1','2','3',0x26},             //êy×&#214;&#188;ü1£&#187;êy×&#214;&#188;ü2£&#187;êy×&#214;&#188;ü3£&#187;&#207;òé&#207; &#188;ó
        {'4','5','6',0x25},             //êy×&#214;&#188;ü4£&#187;êy×&#214;&#188;ü5£&#187;êy×&#214;&#188;ü6£&#187;&#207;ò×ó &#188;&#245;
        {'7','8','9',0x28},             //êy×&#214;&#188;ü7£&#187;êy×&#214;&#188;ü8£&#187;êy×&#214;&#188;ü9£&#187;&#207;ò&#207;&#194; 3&#203;
        {'0',0x1B,0x0D,0x27}              //êy×&#214;&#188;ü0£&#187;ESC&#188;ü£&#187;&#187;&#216;3μ&#188;ü£&#187;   &#207;òóò 3y
};


void keyaction(unsigned char keycode)
{
        if((keycode>='0')&&(keycode<='9'))
        {
                Numkeraction(keycode-'0');
        }
        else if(keycode==0x26)
        {
                Oprtkeyaction(0);        //&#188;ó
        }
        else if(keycode==0x25)
        {
                Oprtkeyaction(1);        //&#188;&#245;
        }
        else if(keycode==0x28)
        {
    Oprtkeyaction(2);        //3&#203;
        }
        else if(keycode==0x27)
        {
                Oprtkeyaction(3);        //3y
        }
        else if(keycode==0x0D)
        {
                GetResult();             //μèóú
        }
        else if(keycode==0x1B)
        {
                reset();
                LcdShowstr(15,1,"0");    //1éá&#227;
        }
}

void keydrive()
{
        unsigned char i,j;                           //iê&#199;DD£&#172;jê&#199;áD
        static unsigned char pdata backup[4][4]={               
        {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}     
  };
       
        for(i=0;i<4;i++)
                {
                        for(j=0;j<4;j++)
                        {
                                if(backup[i][j]!=keysta[i][j])
                                {
                                        if(backup[i][j]!=0)
                                        {
                                                keyaction(keycodeMap[i][j]);
                                        }
                                        backup[i][j]=keysta[i][j];
                                }
                        }
                }
}

void keyscan()
{
        static unsigned char keyout=0;
        unsigned char i=0;
        static unsigned char keybuf[4][4]={
                0xFF,0xFF,0xFF,0xFF,
          0xFF,0xFF,0xFF,0xFF,
          0xFF,0xFF,0xFF,0xFF,
          0xFF,0xFF,0xFF,0xFF
        };
        P22=123=1;
        keybuf[keyout][0]=(keybuf[keyout][0]<<1)|P20;
        keybuf[keyout][1]=(keybuf[keyout][1]<<1)|P21;
        keybuf[keyout][2]=(keybuf[keyout][2]<<1)|P22;
        keybuf[keyout][3]=(keybuf[keyout][3]<<1)|P23;
       
        for(i=0;i<4;i++)
        {
                if((keybuf[keyout][i]&0x0F)==0x00)
                {
                        keysta[keyout][i]=0;
                }
                else if((keybuf[keyout][i]&0x0F)==0x0F)
                {
                        keysta[keyout][i]=1;
                }
                else{}
        }
       
        keyout++;
        if(keyout>=4)
        {
                keyout=0;
        }
        switch(keyout)
        {
                case 0:kout1=1;kout4=0;break;
                case 1:kout3=0;kout4=1;break;
                case 2:kout2=0;kout3=1;break;
                case 3:kout1=0;kout2=1;break;
    default :break;
        }

}


3、main.c文件
#include<reg52.h>

unsigned char T0RH=0;
unsigned char T0RL=0;
unsigned char step=0;
unsigned char oprt=0;
signed long num1=0;
signed long num2=0;
signed long result=0;

void configTimer0(unsigned int ms);
extern void LcdShowstr(unsigned char x,unsigned char y,unsigned char *str);
extern void initlcd1602();
extern void keydrive();
extern void keyscan();
extern void LcdAreaClean(unsigned char x,unsigned char y,unsigned char len);
extern void LcdFullClaen();



void main()
{
        EA=1;
        configTimer0(1);
        initlcd1602();
        LcdShowstr(15,1,"0");
        while(1)
        {
                keydrive();
        }
}
unsigned char LongToString(unsigned char *str,signed long dat)     //êy×&#214;×a&#187;&#187;&#206;a×&#214;·&#251;2¢ó&#195;len±íê&#190;&#198;&#228;3¤&#182;è
{
        signed char i=0;
        unsigned char len=0;
        unsigned char buf[12];
        if(dat<0)
        {
                dat=-dat;
                *str++='-';
                len++;
        }
        do
        {
                buf[i++]=dat%10;
                dat/=10;
        }
        while(dat>0);
        len+=i;
        while(i-->0)
        {
                *str++=buf[i]+'0';
        }
        *str='\0';
        return len;
}
void showoprt(unsigned char y,unsigned char type)    //&#212;&#203;&#203;&#227;·&#251;&#207;&#212;ê&#190;£&#172;&#207;&#212;ê&#190;&#212;ú×&#238;×ó2à
{
        switch(type)
        {
                case 0cdShowstr(0,y,"+"); break;
                case 1cdShowstr(0,y,"-"); break;
                case 2cdShowstr(0,y,"*"); break;
                case 3cdShowstr(0,y,"/"); break;
                default:break;
        }
}
void reset()
{
        num1=0;
        num2=0;
        step=0;
        LcdFullClaen();
}

void Numkeraction(unsigned char n)       //êy×&#214;&#188;ü°′&#207;&#194;
{
        unsigned char len=0;
        unsigned char str[12];
        if(step>1)
        {
                reset();
        }
        if(step==0)
        {
                num1=num1*10+n;         
                len=LongToString(str,num1);   
                LcdShowstr(16-len,1,str);       //&#212;úμú&#182;tDD×&#238;óò2à&#207;&#212;ê&#190;êy×&#214;1
        }
        else
        {
                num2=num2*10+n;
                len=LongToString(str,num2);
                LcdShowstr(16-len,1,str);       //&#212;úμú&#182;tDD×&#238;óò2à&#207;&#212;ê&#190;êy×&#214;2
        }
}

void Oprtkeyaction(unsigned char type)   //&#212;&#203;&#203;&#227;·&#251;&#188;ü°′&#207;&#194;
{
        unsigned char len=0;
        unsigned char str[12];
        if(step==0)
        {
                len=LongToString(str,num1);
                LcdAreaClean(0,0,16-len);         //μúò&#187;DD2&#191;·&#214;&#199;&#229;&#198;á£&#172;×&#214;·&#251;×ó2à2&#191;·&#214;
                LcdShowstr(16-len,0,str);         //μúò&#187;DD&#207;&#212;ê&#190;êy×&#214;1
                showoprt(1,type);                 //&#212;&#203;&#203;&#227;·&#251;&#207;&#212;ê&#190;&#212;úμú&#182;tDD×ó2à
                LcdAreaClean(1,1,14);             //&#199;&#229;&#198;á&#207;&#212;ê&#190;&#198;áμú&#182;tDD&#214;D&#188;&#228;1~14&#206;&#187;á&#244;&#207;&#194;0oí15&#207;&#212;ê&#190;&#206;&#187;
                LcdShowstr(15,1,"0");             //μú&#182;tDD×&#238;óò2à&#207;&#212;ê&#190;×&#214;·&#251;0
                oprt=type;
                step=1;
        }
}

void GetResult()
{
        unsigned char len=0;
        unsigned char str[12];
        if(step==1)
        {
                step=2;
                switch(oprt)
                {
                        case 0:result=num1+num2;break;
                        case 1:result=num1-num2;break;
                        case 2:result=num1*num2;break;
                        case 3:result=num1/num2;break;
                        default:break;
                }
                len=LongToString(str,num2);
                showoprt(0,oprt);
                LcdAreaClean(1,0,16-1-len);
                LcdShowstr(16-len,0,str);           //&#189;&#171;μú&#182;tDD&#207;&#212;ê&#190;êy&#190;Yò&#198;μ&#189;μúò&#187;DD
               
                len=LongToString(str,result);
                LcdShowstr(0,1,"=");                //μú&#182;tDD×&#238;×ó2à&#207;&#212;ê&#190;=
                LcdAreaClean(1,1,16-1-len);
                LcdShowstr(16-len,1,str);           //μú&#182;tDD&#207;&#212;ê&#190;&#189;á1&#251;
        }
}


void configTimer0(unsigned int ms)
{
        unsigned long tmp=0;
        tmp=32768000/12;
        tmp=(tmp*ms)/1000;
        tmp=65536-tmp;
        tmp = tmp + 28;
        T0RH=(unsigned char)(tmp>>8);
        T0RL=(unsigned char)tmp;
        TMOD&=0xF0;
        TMOD|=0x01;
        TH0=T0RH;
        TL0=T0RL;
        TR0=1;
        ET0=1;
}

void interruptTime() interrupt 1
{
        TH0=T0RH;
  TL0=T0RL;
        keyscan();
}



计算器.zip

55.22 KB, 下载次数: 287

好懒~~不想说~~~
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表