ARM开发(9)基于STM32的简单四则运算计算器
生活随笔
收集整理的這篇文章主要介紹了
ARM开发(9)基于STM32的简单四则运算计算器
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
基于STM32的簡(jiǎn)單四則運(yùn)算計(jì)算器
一 計(jì)算器原理:
1.1 本實(shí)驗(yàn)實(shí)現(xiàn)基于STM32的簡(jiǎn)單四則運(yùn)算計(jì)算器 1.2 實(shí)驗(yàn)思路:理解計(jì)算器原理(按鍵掃描,字符實(shí)時(shí)顯示,運(yùn)算表達(dá)式計(jì)算,浮點(diǎn)數(shù)轉(zhuǎn)字符串,字符串結(jié)果顯示) 1.3 開(kāi)發(fā)環(huán)境 : MDK5 庫(kù)函數(shù)版本開(kāi)發(fā) JLINK仿真 STM32F103VBT6芯片二 實(shí)驗(yàn)步驟:
2.1 key.h代碼:
2.2 key.c代碼(按鍵掃描函數(shù)):
#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; DD 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; áDGPIO_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) // 有按鍵按下了{(lán)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; // 長(zhǎng)按鍵處理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 // 沒(méi)按鍵按下{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); //動(dòng)態(tài)規(guī)劃四則運(yùn)算過(guò)程 extern double displaynum(char str[],int len); //四則運(yùn)算結(jié)果函數(shù) extern void float_to_str(char *str,double num); //雙精度化為字符串函數(shù) extern u8 str_to_ma(char st); //字符轉(zhuǎn)為數(shù)碼管段選碼值 extern char key(u8 c); //判斷按鍵掃描值是否是四則運(yùn)算符或者0~9字符 #endif2.4 calcalator.c代碼(計(jì)算器運(yùn)算)
#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)// 動(dòng)態(tài)規(guī)劃四則運(yùn)算過(guò)程 { 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)// 四則運(yùn)算結(jié)果函數(shù) {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;elsefst[i] = fst[i - 1];}ans = Jud(str,0, len - 1); return ans;} void float_to_str(char *str,double num)// 雙精度化為字符串函數(shù) {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)// 字符轉(zhuǎn)為數(shù)碼管段選碼值 {if(s=='.')return 0x10;else return seg88Code[s-'0'];}2.5 main.c代碼(具體實(shí)現(xiàn)計(jì)算器四則運(yùn)算):
#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)// 判斷按鍵掃描值是否是四則運(yùn)算符或者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<n;q++){dnum[q]=str_to_ma(str[q]);}DisplayOn(1);Displayy(dnum,n);delay_ms(1000);DisplayOn(0); } } }三 接線測(cè)試:
3.1 與板子接線測(cè)試效果良好,基本四則運(yùn)算結(jié)果較好,唯一缺點(diǎn)對(duì)tm1629a的顯示不是很好,因?yàn)閿?shù)碼管排列順序不是順序,可以在上面修改,基本思路是這樣。總結(jié)
以上是生活随笔為你收集整理的ARM开发(9)基于STM32的简单四则运算计算器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: vue仿移动端京东搜索历史自适应长度超两
- 下一篇: Fedora Linux在Lenovo