基于STM32的简单四则运算计算器
一 计算器原理:
1.1 本实验实现基于STM32的简单四则运算计算器
1.2 实验思路:理解计算器原理(按键扫描,字符实时显示,运算表达式计算,浮点数转字符串,字符串结果显示)
1.3 开发环境 : MDK5 库函数版本开发 JLINK仿真 STM32F103VBT6芯片
二 实验步骤:
2.1 key.h代码:
#ifndef __KEY_H
#define __KEY_H
#include"sys.h"
#define KEY_NULL 0 // no key
#define KEY_0 40 // value 0
#define KEY_1 41
#define KEY_2 42
#define KEY_3 43
#define KEY_4 44
#define KEY_5 45
#define KEY_6 46
#define KEY_7 47
#define KEY_8 48
#define KEY_9 49 //
#define KEY_POINT 50 // decimal point
#define KEY_OP_ADD 64 // '+' addition
#define KEY_OP_SUB 65 // '-' substract
#define KEY_OP_MUL 66 // '*' multiplication
#define KEY_OP_DIV 67 // '/' divide
#define KEY_EQU 81 // '='
void KEY_Init(void);//IO³õʼ»¯
void funcScanKey(void);
u8 Key_Read(void);
#endif
2.2 key.c代码(按键扫描函数):
#include "stm32f10x.h"
#include "key.h"
#include "delay.h"
typedef struct
{
u8 flagKeyDown:1;
u8 flagKeyRelease:1;
u8 flagKeyLong:1;
} TEMP_FLAGS_Type;
TEMP_FLAGS_Type tempFlags;
u8 specialKey;
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
GPIO_InitStructure.GPIO_Pin = KEY_OUT_PINS ;//0x7f ;//GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6;//ROWPINS; ÐÐ
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = KEY_IN_PINS ; //GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10| GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14;//COLPINS; ÁÐ
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_SetBits(GPIOE,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6);
GPIO_ResetBits(GPIOE, GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10| GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14);
}
static u8 Timer2of16ms = 0;
static u8 sourceKey = 0;
static u8 keyCol, keyRow;
u8 const keyTableMax = 7;
u8 const keyTableMaxCol = 8;
u16 const scanTable[keyTableMax] = { 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1};
u16 const scanTable2[keyTableMaxCol] = { 0x01, 0x02, 0x04, 0x08, 0x010, 0x20, 0x40, 0x80};
u8 const keyTable[keyTableMax][keyTableMaxCol] =
{
{ KEY_FUNC_UP, KEY_FUNC_DOWN, KEY_ABS_INC, KEY_ENTER, 0, KEY_Z_SET, KEY_Y_SET, KEY_X_SET},
{ KEY_SDM, 0, KEY_HA, 0, KEY_0, KEY_1, KEY_4, KEY_7},
{ KEY_FUNC_RARC, KEY_CLS, KEY_HALF, 0, KEY_POINT, KEY_2, KEY_5, KEY_8},
{ KEY_FUNC_LINE, KEY_FUNC_CIRCLE, 0, KEY_MM_INCH, KEY_SIGN, KEY_3, KEY_6, KEY_9},
{ KEY_CALL, KEY_TOOL, KEY_OP_ADD, KEY_OP_SUB, KEY_OP_MUL, KEY_OP_DIV, KEY_EQU, KEY_CLEAR},
{ KEY_OP_INV, 0, KEY_OP_SIN, KEY_OP_COS, KEY_OP_TAN, KEY_ARC, KEY_OP_SQRT, KEY_CALCU},
{ KEY_ZHUIDU, 0, 0, 0, 0, KEY_Z_ZERO, KEY_Y_ZERO, KEY_X_ZERO }
};
void funcScanKey(void)
{
u16 x ;
uint16_t tempdata;
static u16 keyDelay = 0;
static u8 keyRelDelay = 0;
static u8 row = 0;
u8 currKey,keyLongCnt;
Timer2of16ms ++;
if(Timer2of16ms >= keyTableMax)
Timer2of16ms = 0;
tempdata = GPIO_ReadOutputData(KEY_PORT) ;
tempdata &= ~KEY_OUT_PINS;
tempdata |= scanTable[Timer2of16ms ];
GPIO_Write(KEY_PORT, tempdata);
tempdata = 0;
x = tempdata;
tempdata = GPIO_ReadInputData(KEY_PORT) ;
tempdata &= 0x7f80;
tempdata >>= 7;
x = tempdata;
if(x>0) // 有按键按下了
{
currKey = x;
if((currKey != sourceKey) || (row != Timer2of16ms) ) // 按键判断
{
keyDelay = 0;
sourceKey = currKey;
tempFlags.flagKeyDown = 0;
tempFlags.flagKeyLong = 0;
row = Timer2of16ms;
keyLongCnt = 0;
return;
}
else
{
if((row != Timer2of16ms))
return;
keyDelay++;
keyLongCnt++;
if(keyDelay > 10)
{
keyRelDelay = 0;
if(tempFlags.flagKeyDown)
{
if(keyLongCnt >= 100)
{
specialKey = x;
tempFlags.flagKeyLong = 1; // 长按键处理
for(currKey = 0; currKey < keyTableMaxCol; currKey++)
{
if(x == scanTable2[currKey])
break;
}
keyCol = currKey; keyRow = row;
}
}
else
{
tempFlags.flagKeyDown = 1;
for(currKey = 0; currKey < keyTableMaxCol; currKey++)
{
if(x == scanTable2[currKey])
break;
}
keyCol = currKey; keyRow = row;
}
}
}
}
else // 没按键按下
{
if(row != Timer2of16ms)
return;
keyDelay = 0;
if(tempFlags.flagKeyLong)
{
keyRelDelay++;
if(keyRelDelay > 3)
{
tempFlags.flagKeyLong = 0;
tempFlags.flagKeyDown = 0;
tempFlags.flagKeyRelease = 0;
keyLongCnt = 0;
}
}
if(tempFlags.flagKeyDown)
{
keyRelDelay++;
if(keyRelDelay > 3)
{
tempFlags.flagKeyDown = 0;
tempFlags.flagKeyRelease = 1;
keyLongCnt = 0;
}
}
}
}
u8 Key_Read(void) //扫描得到按键值
{
if(tempFlags.flagKeyRelease)
{
tempFlags.flagKeyRelease = 0;
return keyTable[keyRow][keyCol];
}
else if(tempFlags.flagKeyLong)
return keyTable[keyRow][keyCol];
return KEY_NULL;
}
2.3 calcalator.h代码
#ifndef __CALCALATOR_H
#define __CALCALATOR_H
#include "sys.h"
extern double Jud(char str[],int begin, int end); //动态规划四则运算过程
extern double displaynum(char str[],int len); //四则运算结果函数
extern void float_to_str(char *str,double num); //双精度化为字符串函数
extern u8 str_to_ma(char st); //字符转为数码管段选码值
extern char key(u8 c); //判断按键扫描值是否是四则运算符或者0~9字符
#endif
2.4 calcalator.c代码(计算器运算)
#include "calcalator.h"
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
#include"math.h"
#include "sys.h"
int fst[1005];
u8 const seg88Code[17] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0X7C, 0x39, 0x5E, 0x79, 0x71,0x01};
double Jud(char str[],int begin, int end)// 动态规划四则运算过程
{
int i;
double k;
for(i = begin; i <= end; i++)
{
if(str[i]== '+' && fst[i] == fst[begin])
{
k = Jud(str,begin, i - 1) + Jud(str,i + 1, end);
return k;
}
}
for(i = end; i >= begin; i--)
{
if(str[i]=='-' && fst[i] == fst[begin])
{
k = Jud(str,begin, i - 1) - Jud(str,i + 1, end);
return k;
}
}
for(i = begin; i <= end; i++)
{
if(str[i] == '*' && fst[i] == fst[begin])
{
k = Jud(str,begin, i - 1) * Jud(str,i + 1, end);
return k;
}
}
for(i = end; i >= begin; i--)
{
if(str[i] == '/' && fst[i] == fst[begin])
{
k = Jud(str,begin, i - 1) / Jud(str,i + 1, end);
return k;
}
}
if(str[begin]=='(')
{
for(i = begin + 1; fst[i] >= fst[begin + 1]; i++);
k = Jud(str,begin + 1, i - 1);
}
else
{
char *p = str;
sscanf(p+begin, "%lf", &k);
}
return k;
}
double displaynum(char str[],int len)// 四则运算结果函数
{
int i;
double ans;
memset(fst, 0, sizeof(fst));
fst[0] = 1;
for(i = 1; i <= len - 1; i++)
{
if(str[i - 1]== '(')
fst[i] = fst[i - 1] + 1;
else if(str[i] == ')')
fst[i] = fst[i - 1] - 1;
else
fst[i] = fst[i - 1];
}
ans = Jud(str,0, len - 1);
return ans;
}
void float_to_str(char *str,double num)// 双精度化为字符串函数
{
int high;
double low,tp;
char *start=str;
int n=0;
char ch[20];
int i;
high=(int)num;
low=num-high;
while(high>0){
ch[n++]='0'+high%10;
high=high/10;
}
for(i=n-1;i>=0;i--){
*str++=ch[i];
}
num -= (int)num;
tp = 0.1;
*str++='.';
while(num > 1e-8){
num -= tp * (int)(low * 10);
tp /= 10;
*str++='0'+(int)(low*10);
low=low*10.0-(int)(low*10);
}
*str='\0';
str=start;
}
extern u8 str_to_ma(char s)// 字符转为数码管段选码值
{
if(s=='.')
return 0x10;
else return seg88Code[s-'0'];
}
2.5 main.c代码(具体实现计算器四则运算):
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "beep.h"
#include "key.h"
#include "keyled.h"
#include "calcalator.h"
#include"stdlib.h"
#include"stdio.h"
#include"string.h"
char key(u8 c)// 判断按键扫描值是否是四则运算符或者0~9字符
{
char ckey;
if(c>=40&&c<=49)
{
ckey=(char)(c-40+'0'); return ckey;
}
else if(c==50)
{
ckey='.'; return ckey;
}
else if(c==64)
{
ckey='+'; return ckey;
}
else if(c==65)
{
ckey='-'; return ckey;
}
else if(c==66)
{
ckey='*'; return ckey;
}
else if(c==67)
{
ckey='/'; return ckey;
}
else
return 'o';
}
int main(void)
{
u8 c,i,n,t,q;
double m;
char str[20];
char dispay_num[20];
u8 led_num[8]={0};
u8 dnum[20];
u8 const seg88Code[17] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0X7C, 0x39, 0x5E, 0x79, 0x71,0x01};
char ckey;
delay_init();
KEY_Init();
BEEP_Init();
Initial_LED();
while(1)
{
c=0;
i=0;
t=0;
m=0;
q=0;
while(1)
{
funcScanKey();
c=Key_Read();
if(c != KEY_NULL)
{
ckey=key(c);
if(ckey!='o')
dispay_num[i++]=ckey;
if(c>=40&&c<=49)
{
led_num[t++]=seg88Code[c-40];
}
else if ((c>=64&&c<=67)||c==81)
{
DisplayOn(1);
Displayy(led_num,t);
t=0;
delay_ms (1000);
DisplayOn(0);
if(c==81)
break;
}
delay_ms(10);
}
}
if(c==81)
{
int h;
h=(int)(i);
m=displaynum(dispay_num,h);
float_to_str(str,m);
n=strlen(str);
for(q=0;q
三 接线测试:
3.1 与板子接线测试效果良好,基本四则运算结果较好,唯一缺点对tm1629a的显示不是很好,因为数码管排列顺序不是顺序,可以在上面修改,基本思路是这样。