基于STM 32、矩阵键盘和独立键盘实现LCD显示的智能计算器(带括号的加减乘除运算、混合四则运算)——普中科技单片机开发试验仪嵌入式开发

0 引言

智能计算器是嵌入式开发的入门项目,本章使用STM 32芯片作为CPU,并将矩阵键盘和独立键盘作为输入外设,LCD1602作为显示屏,实现可输入的可视化智能计算器。

备注:最终生成的可执行HEX文件请点击这里

1 基本原理

该项目中会用到的设备有STM 32芯片、4X4矩阵键盘、8位独立键盘和LCD1602显示屏。在实际运用中,可根据具体项目要求对这些硬件进行替换,可根据自己的需求改变,但项目的整体思路应该是基本不变的。
项目首先输入待计算的表达式,使用矩阵键盘用来输入数字0-9,独立键盘(8位)输入加减乘除、括号、等号等运算符,并在显示屏LCD1602上实时显示待计算的表达式。当输入“=”号,表达式输入完成,开始计算结果。结果计算完成,即可显示到LCD屏上。

1.1 实验接线

该项目使用普中科技单片机开发试验仪作为硬件设备。具体接线如下:
其中,JP11接JP4矩阵键盘,JP8接JP5独立键盘在这里插入图片描述

2 程序要点

实验利用STM32F10 CPU插件实现扫描键盘数字输入和独立键盘运算符输入以及LCD显示的智能计算器,并实现能够括号运算,加减乘除四则混合运算等较复杂计算的智能计算器。
实验程序主要思路是:使用uvision MDK4编译环境,首先配置系统时钟、NVIC,启动GPIOA、GPIOB模式时钟,设置GPIO I/O口,将LCD1602输出口、矩阵键盘输入口和独立键盘输入口初始化。初始化LCD1602。使用矩阵键盘输入数字,独立键盘输入符号(包括括号等),输入“=”结束输入。如果有输入错误,则清屏,重新输入。输入结束后调用计算器算法calculate()函数,计算输入的表达式结果,再调用result2char()函数将计算结果转换为LCD屏显示的字符,并显示在LCD显示屏上。

2.1 程序流程图

在这里插入图片描述

3 项目效果

3.1 两位数加法运算

在这里插入图片描述

3.2 三位数除法运算

在这里插入图片描述

3.3 带括号运算的加减乘除四则混合运算

在这里插入图片描述

4 程序代码

4.0 程序框架和编译环境

使用uvision MDK4编译环境,使用的库函数较少。项目文件框架如下:
在这里插入图片描述
只需要把main.c替换成4.3的完整程序代码,再按上图配置lib函数,即可编译成功。
如果配置不便,可以直接下载使用文章首部的 .HEX文件 。将该.HEX文件直接烧录到单片机中即可使用。

4.1 main()主函数
main()
{
   
    j=1;
    #ifdef DEBUG
    //debug();  //在线调试使用
    #endif  
    RCC_Configuration();      //系统时钟配置函数 
    NVIC_Configuration();     //NVIC配置函数 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB1Periph_TIM2 | RCC_APB2Periph_AFIO, ENABLE);//启动GPIO模块时钟    
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);  //把调试设置普通IO口                           
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //所有GPIO为同一类型端口
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    //输出的最大频率为50HZ
    GPIO_Init(GPIOA, &GPIO_InitStructure);   //初始化GPIOA端口
    GPIO_Init(GPIOB, &GPIO_InitStructure);   //初始化GPIOB端口
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 |GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; //所有GPIO为同一类型端口
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;     //开漏输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    //输出的最大频率为50HZ
    GPIO_Init(GPIOB, &GPIO_InitStructure);   //初始化GPIOB端口
    GPIO_Write(GPIOA,0xffff);  //将GPIOA 16个端口全部置为高电平
    GPIO_Write(GPIOB,0xffff);  //将GPIOB 16个端口全部置为高电
    lcd_init();               // 初始化LCD
    delay(10);  

   while(1)              
   {
      
    //输入表达式:矩阵键盘输入数字,独立键盘输入符号               
      while(flag_buf==0 && flag_fuhao2==0 && flag ==0)
      {
   
          keydown();     //矩阵按键检测
          delay(20);
          duli_keyscan();  //独立按键检测
          delay(20);
          lcd_wcmd_4bit(0x01);//清除LCD的内容
          delay(2000);
          LCD();     //实时显示按键的表达式
      }
     //如果有输入数字,将其显示在LCD屏上
      if(flag_buf!=0)
      {
   
         dis1[j]=dis_buf+48;
      }
      //如果有输入符号,将其显示在LCD屏上
      else if(flag_fuhao2!=0)
      {
   
         dis1[j]=fuhao;
      }
      //清除flag值
      j++;
      flag_buf=0;
      flag_fuhao=0;
      flag_fuhao2=0;              
      if(flag==1)        
      {
                     
         calculate(); //计算表达式的值                    
         result2char();//将计算结果转化为字符串
         dis2[0]=61;  //输入“=”
         flag_fuhao=0;    //清空flag
         flag=0;
      }
      //如果有清屏指令,则清除屏幕,重新开始输入
      if(flag==2)   
      {
   
        flag=0;
        j=1;
        for(m=0;m<16;m++)
        {
   
           dis1[m]=32;
        }
        for(m=0;m<16;m++)
        {
   
           dis2[m]=32;
        }
        delay(2000);
        LCD();
      } 
   }
}
4.2 主要变量和函数
// 主要变量
typedef unsigned char BYTE;
typedef unsigned char BOOL; 
BYTE dis1[] = {
   "H               "};  //显示字符
BYTE dis2[] = {
   "                "};
BYTE dis_buf=0;            //显示缓存
BYTE temp;               //中间变量
BYTE key;                //键顺序码
BYTE fuhao=32; //存储符号
BYTE flag=0;  //判断是否结束
BYTE flag_buf=0; //缓存键值
BYTE flag_fuhao=0;//符号的flag
BYTE j,m,n;  //循环计数索引
int i=0;  //循环计数索引
int operand[15] = {
   0};                //数字数组,初始化
int  top_num = -1;  //数组末尾
BYTE oper[15] = {
   0};                  //操作符数组,初始化
int top_oper = -1;   //数组首部
BYTE* temp_p;                            // 数组指针
BYTE* str = dis1;//字符串指针
BYTE dest[15];//字符数组,存储结果

// 主要函数
void RCC_Configuration(void);//RCC初始化
void NVIC_Configuration(void);  //NVIC初始化
void NOP(void);     //延时周期
void Delay(vu32 nCount);   //延时程序
void delay0(BYTE x);      //延时子程序
void keyscan(void);      // 矩阵键盘扫描子程序
void duli_keyscan(void);    //独立按键扫描子程序
void keydown(void);       //判断键盘键是否按下
void calculate(void);         //判断键盘键是否按下
void result2char(void);   //计算表达式的值
void LCD(void); //LCD显示
int insert_operand(int *operand , int * top_num ,BYTE num);//数据压入数据栈 
int insert_oper (BYTE * oper , int *top_oper , char ch);//操作符压入符号栈
int compare(BYTE *oper , int *top_oper , BYTE ch);//比较操作服优先级
int deal_date(int *operand ,BYTE *oper ,int *top_num, int *top_oper);//进行数据运算
4.3 完整程序代码
(PS:实验代码有点长,其中有些注释不完整,但编译无错误。可结合以上的程序思路和主要变量、函数注释查看)
#include "stm32f10x_lib.h"
/********************************硬件接口定义*********************************/
#define RS  GPIO_Pin_1 //P2^6;             
#define RW  GPIO_Pin_2 //P2^5;
#define EN  GPIO_Pin_0 //P2^7;

/********************************宏定义*********************************/
#define    LCD_RS(x)  x ? GPIO_SetBits(GPIOB, RS): GPIO_ResetBits(GPIOB, RS)
#define    LCD_RW(x)  x ? GPIO_SetBits(GPIOB, RW): GPIO_ResetBits(GPIOB, RW)
#define    LCD_EN(x)  x ? GPIO_SetBits(GPIOB, EN): GPIO_ResetBits(GPIOB, EN)

/********************** 变量定义 ---------------------------*/
GPIO_InitTypeDef GPIO_InitStructure;     //GPIO
ErrorStatus HSEStartUpStatus;	
typedef unsigned char BYTE;
typedef unsigned char BOOL; 

BYTE dis1[] = {
   "H               "};
BYTE d
  • 28
    点赞
  • 205
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值