51单片机 带修改错误功能的计算器

utilities.h
#ifndef UTILITIES_H_INCLUDED
#define UTILITIES_H_INCLUDED

typedef unsigned char uchar, BYTE, uint8;
typedef unsigned int uint, WORD, uint16;
typedef unsigned long ulong, DWORD, uint32;
typedef char int8;
typedef int int16;
typedef long int32;
typedef unsigned char * uchar_p;
typedef unsigned int * uint_p;
typedef unsigned long * ulong_p;
typedef char * char_p;
typedef int * int_p;
typedef long * long_p;

#endif // UTILITIES_H_INCLUDED

keyBoard.c

#include <reg52.h>
#include "utilities.h"

sbit KEY_OUT_3 = P2^0;
sbit KEY_OUT_2 = P2^1;
sbit KEY_OUT_1 = P2^2;
sbit KEY_OUT_0 = P2^3;
sbit KEY_IN_0 = P2^4;
sbit KEY_IN_1 = P2^5;
sbit KEY_IN_2 = P2^6;
sbit KEY_IN_3 = P2^7;

uchar code keyCodeMap[4][4] = { //矩阵按键编号到标准键盘键码的映射表
    {0x31, 0x32, 0x33, 0x26}, //数字键1、数字键2、数字键3、向上键
    {0x34, 0x35, 0x36, 0x25}, //数字键4、数字键5、数字键6、向左键
    {0x37, 0x38, 0x39, 0x28}, //数字键7、数字键8、数字键9、向下键
    {0x30, 0x1B, 0x0D, 0x27}  //数字键0、ESC键、  回车键、 向右键
};
uchar pdata keyState[4][4] = {  //全部矩阵按键的当前状态
    {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1}
};

extern void keyAction(uchar keyCode);

void keyDriver() {
    uchar i, j;
    static uchar 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 (keyState[i][j] != backup[i][j]) {
                if (keyState[i][j] == 0)
                    keyAction(keyCodeMap[i][j]);
                backup[i][j] = keyState[i][j];
            }
}

void keyScan() {
    static uchar i = 0;
    static uchar keyBuf[4][4] = {
        {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},
        {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}
    };
    uchar j;

    keyBuf[i][0] = (keyBuf[i][0] << 1) | KEY_IN_0;
    keyBuf[i][1] = (keyBuf[i][1] << 1) | KEY_IN_1;
    keyBuf[i][2] = (keyBuf[i][2] << 1) | KEY_IN_2;
    keyBuf[i][3] = (keyBuf[i][3] << 1) | KEY_IN_3;
    for (j=0; j<4; j++) {
        if (keyBuf[i][j] == 0x00)
            keyState[i][j] = 0;
        else if (keyBuf[i][j] == 0xFF)
            keyState[i][j] = 1;
    }
    switch (i) {
        case 0: KEY_OUT_0 = 1; KEY_OUT_1 = 0; break;
        case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
        case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
        case 3: KEY_OUT_3 = 1; KEY_OUT_0 = 0; break;
        default : break;
    }
    i = ++i & 0x03;
}




digitalTube.c
#include <reg52.h>
#include "utilities.h"

uchar code LEDChar[] = {  //数码管显示字符转换表
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
uchar LEDBuff[6] = {  //数码管显示缓冲区
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};

void showNumber(ulong num) {
    char i;
	uchar buf[6];

    for (i=0; i<6; i++) {
        buf[i] = num % 10;
        num /= 10;
    }
    for (i=5; i>0; i--) {
        if (buf[i] == 0)
            LEDBuff[i] = 0xFF;
        else
            break;
    }
	for (; i>=0; i--)
	    LEDBuff[i] = LEDChar[buf[i]];
}

void LEDScan() {
    static uchar i = 0;
    P0 = 0xFF;
    P1 = (P1 & 0xF8) | i;
    P0 = LEDBuff[i];
    if (i < 5)
        i++;
    else
        i = 0;
}


timer.c
#include <reg52.h>
#include "utilities.h"
#define TIMER0
#define TIMER0_MOD1

#if defined (TIMER0)
uchar T0RH = 0;
uchar T0RL = 0;

#if defined (TIMER0_MOD1)
void setTmr0(uint ms) {
    ulong tmp;
    tmp = 11059326 / 12;
    tmp = tmp * ms / 1000;
    tmp = 65536 - tmp;
    tmp += 28;
    T0RL = tmp;
    T0RH = tmp>>8;
}
#endif // defined
#endif // defined



calculator.c
/**********************************************************
    加减乘除计算器,能实现连续的运算,并且提供修改功能:
    对于算符来说,以最后输入的算符为准。
    测试样例:
    12 + 256 * 9 - 53 / 2
    3 + - * 5
    6 + - 2 / * 7

***********************************************************/
#include <reg52.h>
#include "utilities.h"

sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;

extern uchar T0RH;
extern uchar T0RL;
extern uchar LEDBuff[6];
extern uchar code LEDChar[];
extern void showNumber(ulong num);
extern void LEDScan();
extern void keyScan();
extern void keyDriver();
extern void setTmr0(uint ms);

void keyAction(uchar keyCode) {
    static ulong result = 0Lu;
    static ulong number = 0Lu;
    static uchar opPre = 0x26;
	static bit preIsOp = 0;

    if (keyCode >= 0x30 && keyCode <= 0x39) {           //数字键
        number = number * 10 + keyCode - 0x30;
        showNumber(number);
        preIsOp = 0;
    }
    else if ((keyCode >= 0x25 && keyCode <= 0x28) || keyCode == 0x0D) {      //上下左右,加减乘除;回车键,相当于等于键
        if (!preIsOp) {
            switch (opPre) {
                case 0x26: result += number; break;
                case 0x28: result -= number; break;
                case 0x25: result /= number; break;
                case 0x27: result *= number; break;
                case 0x0D: result = number; break;
                default: break;
            }
            number = 0;
            showNumber(result);
        }
        opPre = keyCode;
        preIsOp = 1;
    }
    else if (keyCode == 0x1B) {     //ESC键
        number = 0Lu;
        result = 0Lu;
        showNumber(0Lu);
        preIsOp = 0;
    }
    else {
        preIsOp = 0;
    }
}

void interruptTmr0() interrupt 1 {
    TH0 = T0RH;
    TL0 = T0RL;
	LEDScan();
	keyScan();
}

void main() {
    EA = 1;
    ENLED = 0;
    ADDR3 = 1;
    TMOD = 0x01;
    setTmr0(1);
    TH0 = T0RH;
    TL0 = T0RL;
    ET0 = 1;
    TR0 = 1;
    LEDBuff[0] = LEDChar[0];
    while (1) {
        keyDriver();
    }
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值