(16)趣味单片机新玩法-自己动手做个简单计算器

电子爱好者的乐趣,想啥做啥,;不受拘束的想象力加上强大的动手能力,我们几乎能做绝大部分东西,下面我们来一起简单的”小试牛刀“,做个计算器耍耍。


使用到的东西元器件:4*4矩阵键盘,1602液晶模块,arduino uno开发板,220Ω电阻

1602液晶模块连接注意的引脚:
VCC: 液晶模块供电正极
LED+:背光灯正极连接电源正极VCC
LED-:背光灯负极通过220Ω限流电阻连接负极GND
VO:设置液晶偏置电压连接至GND
RW:读写模式引脚,我们这里只要写,所以R/W接GND
GND:液晶模块供电负极

我们来看下实际运行效果:

矩阵键盘A,B,C,D分别代表 +,-,X,/; " * "代表清除," # "号代表" = "

代 码 部 分:

#include 
#include  
#include 

LiquidCrystal lcd(13, 12, 11, 10, 9, 8);

long first = 0;
long second = 0;
double total = 0;

char customKey;
const byte ROWS = 4;
const byte COLS = 4;

char keys[ROWS][COLS] = {
  {'1','2','3','+'},
  {'4','5','6','-'},
  {'7','8','9','*'},
  {'C','0','=','/'}
};
byte rowPins[ROWS] = {7,6,5,4}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {3,2,1,0}; //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS); 

void setup()
{
  lcd.begin(16, 2);               // start lcd
  for(int i=0;i<=3;i++);
  lcd.setCursor(0,0);
  lcd.print("Hello");
  lcd.setCursor(0,1);
  lcd.print("calc");
  delay(4000);
  lcd.clear();
  lcd.setCursor(0, 0);
}


void loop()
{

  customKey = customKeypad.getKey();
  switch(customKey) 
  {
  case '0' ... '9': // This keeps collecting the first value until a operator is pressed "+-*/"
    lcd.setCursor(0,0);
    first = first * 10 + (customKey - '0');
    lcd.print(first);
    break;

  case '+':
    first = (total != 0 ? total : first);
    lcd.setCursor(0,1);
    lcd.print("+");
    second = SecondNumber(); // get the collected the second number
    total = first + second;
    lcd.setCursor(0,3);
    lcd.print(total);
    first = 0, second = 0; // reset values back to zero for next use
    break;

  case '-':
    first = (total != 0 ? total : first);
    lcd.setCursor(0,1);
    lcd.print("-");
    second = SecondNumber();
    total = first - second;
    lcd.setCursor(0,3);
    lcd.print(total);
    first = 0, second = 0;
    break;

  case '*':
    first = (total != 0 ? total : first);
    lcd.setCursor(0,1);
    lcd.print("*");
    second = SecondNumber();
    total = first * second;
    lcd.setCursor(0,3);
    lcd.print(total);
    first = 0, second = 0;
    break;

  case '/':
    first = (total != 0 ? total : first);
    lcd.setCursor(0,1);
    lcd.print("/");
    second = SecondNumber();
    lcd.setCursor(0,3);

    second == 0 ? lcd.print("Invalid") : total = (float)first / (float)second;

    lcd.print(total);
    first = 0, second = 0;
    break;

  case 'C':
    total = 0;
    lcd.clear();
    break;
  }
}

long SecondNumber()
{
      while( 1 )
      {
        customKey = customKeypad.getKey();
        if(customKey >= '0' && customKey <= '9')
        {
          second = second * 10 + (customKey - '0');
          lcd.setCursor(0,2);
          lcd.print(second);
        }

        if(customKey == '=') break;  //return second;
      }
     return second; 
}

代码解释:
我们这里用了arduino自带的液晶库#include 和按键库#include
这样我们只要将重心挪到计算器核心的算法开发上就好了。

定义四线驱动1602的引脚:

LiquidCrystal lcd(13, 12, 11, 10, 9, 8);

按键行和列符号定义:

char keys[ROWS][COLS] = {
  {'1','2','3','+'},
  {'4','5','6','-'},
  {'7','8','9','*'},
  {'C','0','=','/'}
};

按键行和列引脚定义:

byte rowPins[ROWS] = {7,6,5,4}; 
byte colPins[COLS] = {3,2,1,0}; 

按键符号与行列引脚关联:

Keypad customKeypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS); 

第一个部分运算字符输入处理:

  case '0' ... '9':
    lcd.setCursor(0,0);
    first = first * 10 + (customKey - '0');
    lcd.print(first);
    break;

加法处理部分:

  case '+':
    first = (total != 0 ? total : first);
    lcd.setCursor(0,1);
    lcd.print("+");
    second = SecondNumber();
    total = first + second;
    lcd.setCursor(0,3);
    lcd.print(total);
    first = 0, second = 0;
    break;

减法处理部分:

case '-':
    first = (total != 0 ? total : first);
    lcd.setCursor(0,1);
    lcd.print("-");
    second = SecondNumber();
    total = first - second;
    lcd.setCursor(0,3);
    lcd.print(total);
    first = 0, second = 0;
    break;

乘法处理部分:

  case '*':
    first = (total != 0 ? total : first);
    lcd.setCursor(0,1);
    lcd.print("*");
    second = SecondNumber();
    total = first * second;
    lcd.setCursor(0,3);
    lcd.print(total);
    first = 0, second = 0;
    break;

除法处理部分:除法里面还做了除0非法操作

  case '/':
    first = (total != 0 ? total : first);
    lcd.setCursor(0,1);
    lcd.print("/");
    second = SecondNumber();
    lcd.setCursor(0,3);

    second == 0 ? lcd.print("Invalid") : total = (float)first / (float)second;

    lcd.print(total);
    first = 0, second = 0;
    break;

清除计算处理:

  case 'C':
    total = 0;
    lcd.clear();
    break;

另外还有第二个数据字符输入处理:

long SecondNumber()
{
      while( 1 )
      {
        customKey = customKeypad.getKey();
        if(customKey >= '0' && customKey <= '9')
        {
          second = second * 10 + (customKey - '0');
          lcd.setCursor(0,2);
          lcd.print(second);
        }

        if(customKey == '=') break;  //return second;
      }
     return second; 
}

我们输入第一个数据字符串后,如果检测到有输入运算符,那么就直接进入到第二个数据字符串里面,一直到有输入“=”符号,输出计算结果,并跳出当前计算;注意到每个数据字符串里面还做了数据转换,将字符转换为十进制数。

大家可以思考下?

我们看到里面的数据定义都是long型的,如果超过long型所能表达的最大数据会出现什么情况?又该如何处理?大家可以尝试去完善下。

另外我们这里面基本上都是调用arduino的库函数在处理,如果放到51单片机上或者其它单片机上,那么又该如何操作?这些函数大家都可以大胆的去尝试实现。

你可能感兴趣的:((16)趣味单片机新玩法-自己动手做个简单计算器)