運用 A0上拉按鈕和 A1 A2下拉按鈕設計按鍵功能? ? ?加上獨特的算法檢測設計,先計算()內在計算乘除在計算加減的值在計算乘除優先級最后計算加減優先級
#include "stm32f10x.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>#define EXPR_MAX_LEN 64
#define UART_BAUDRATE 115200/* 全局變量聲明 */
char expr_buffer[EXPR_MAX_LEN] = {0};
char result_str[32] = {0};
volatile uint8_t expr_index = 0;
volatile uint8_t expr_ready = 0;
float calc_result = 0;
uint8_t result_available = 0;/* 函數原型聲明 */
void GPIO_Configuration(void);
void USART1_Init(void);
void USART1_SendString(char *str);
void ProcessExpression(void);
float EvaluateExpression(char *expr);
int GetOperatorPriority(char op);int main(void) {
// SystemInit();GPIO_Configuration();USART1_Init();USART1_SendString("Calculator Ready!\r\n");while(1) {/* 處理按鍵事件 */static uint8_t key1_state = 1, key2_state = 1, key3_state = 1;// KEY1 按下計算if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_SET && key1_state) {key1_state = 0;if(expr_ready) ProcessExpression();} else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_SET) key1_state = 1;// KEY2 發送結果if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) == Bit_RESET && key2_state) {key2_state = 0;if(result_available) USART1_SendString(result_str);} else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) == Bit_SET) key2_state = 1;// KEY3 清零if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2) == Bit_RESET && key3_state) {key3_state = 0;expr_index = 0;expr_ready = 0;result_available = 0;memset(expr_buffer, 0, EXPR_MAX_LEN);USART1_SendString("Cleared\r\n");} else if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2) == Bit_SET) key3_state = 1;}
}/* 處理接收到的表達式 */
void ProcessExpression(void) {expr_ready = 0;calc_result = EvaluateExpression(expr_buffer);if(isnan(calc_result)) {strcpy(result_str, "Error\r\n");} else {snprintf(result_str, sizeof(result_str), "Result: %.2f\r\n", calc_result);}result_available = 1;
}/* 支持多運算符和浮點數的表達式求值 */
float EvaluateExpression(char *expr) {float num_stack[EXPR_MAX_LEN] = {0};char op_stack[EXPR_MAX_LEN] = {0};int num_top = -1, op_top = -1;char *p = expr;float num = 0;int decimal = 0;float fraction = 1.0f;//進來保證不到最后一個字符不停止while(*p != '\0') {//如果是數字或者小數點就進行字符數字轉換成真正的數字的操作if(isdigit(*p) || *p == '.') {if(*p == '.') {decimal = 1;} else {if(decimal) {fraction *= 0.1f;num += (*p - '0') * fraction;} else {num = num * 10 + (*p - '0');}}p++;} //如果是符號就判斷這個elseelse {//將前面處理好的數字壓入數字堆棧,如果遇到兩次符號,也就是當+(..)就是(情況就會壓入零代表當前數字,那就不會在主機算區算錯因為0不管怎么樣都零if(num != 0 || decimal) {num_stack[++num_top] = num;num = 0; //如果遇到兩次符號,也就是當+(..)就是(情況就會壓入零代表當前數字decimal = 0;fraction = 1.0f;}//若果判斷到括號(那就記錄一下碰到了括號,這樣就會訂掉一次計算,因為字符加減乘除和括號都是字符,這樣加這一段可以防止誤判斷這里為計算時間上這里只是個括號if(*p == '(') {op_stack[++op_top] = *p;} //判斷括號里賣你是不是有數字計算op_stack[op_top] != '('這句就是判斷上一個符號如果還是)那就是括號里啥也沒有,那就不判斷計算else if(*p == ')') {while(op_top >= 0 && op_stack[op_top] != '(') {//那這一段只是處理)出現,代表此時的括號內算式已經結束,只需判斷前面括號內的結果誠意最后一個數字的結果//處理兩次符號區//如果遇到兩次符號,也就是當+(..)就是(情況就會壓入零代表當前數字/*輔助計算區*/char op = op_stack[op_top--];float b = num_stack[num_top--];float a = num_stack[num_top--];if(op == '+') num_stack[++num_top] = a + b;else if(op == '-') num_stack[++num_top] = a - b;else if(op == '*') num_stack[++num_top] = a * b;else if(op == '/') num_stack[++num_top] = a / b;/*輔助計算區*/}if(op_top >= 0) op_top--; // 彈出左括號} else {//時時刻刻在進行優先級判斷計算運算式得出結果,為什么這里只判斷后者與前者符號的差距呢,因為一個數字只要他前后符號優先級一樣那就不具備優先級計算1*2*6==6*1*2但1+2*8!=1*8+2//所以有了這一段那你不管是不是括號內算式都可以具有優先級計算 /* 主計算區*/while(op_top >= 0 && GetOperatorPriority(op_stack[op_top]) >= GetOperatorPriority(*p)) {char op = op_stack[op_top--];float b = num_stack[num_top--];float a = num_stack[num_top--];if(op == '+') num_stack[++num_top] = a + b;else if(op == '-') num_stack[++num_top] = a - b;else if(op == '*') num_stack[++num_top] = a * b;else if(op == '/') num_stack[++num_top] = a / b;}/*主計算區*/op_stack[++op_top] = *p;}p++;}}if(num != 0 || decimal) {num_stack[++num_top] = num;}while(op_top >= 0) {char op = op_stack[op_top--];float b = num_stack[num_top--];float a = num_stack[num_top--];if(op == '+') num_stack[++num_top] = a + b;else if(op == '-') num_stack[++num_top] = a - b;else if(op == '*') num_stack[++num_top] = a * b;else if(op == '/') {if(fabs(b) < 1e-6) return NAN;num_stack[++num_top] = a / b;}}return num_top >= 0 ? num_stack[num_top] : NAN;
}/* 獲取運算符優先級 */
int GetOperatorPriority(char op) {if(op == '+' || op == '-') return 1;if(op == '*' || op == '/') return 2;return 0;
}/* USART1中斷處理 */
void USART1_IRQHandler(void) {if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {char ch = USART_ReceiveData(USART1);if(ch == '\r' || ch == '\n') {expr_buffer[expr_index] = '\0';expr_ready = 1;expr_index = 0;} else if(expr_index < EXPR_MAX_LEN-1) {expr_buffer[expr_index++] = ch;}USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}/* 初始化USART1 */
void USART1_Init(void) {GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);// 配置TX(PA9)和RX(PA10)GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);USART_InitStructure.USART_BaudRate = UART_BAUDRATE;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure);USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);USART_Cmd(USART1, ENABLE);
}/* GPIO配置 */
void GPIO_Configuration(void) {GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// KEY1(PA0), KEY2(PA1), KEY3(PA2) 輸入GPIO_InitStructure.GPIO_Pin =GPIO_Pin_1 | GPIO_Pin_2;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;GPIO_Init(GPIOA, &GPIO_InitStructure);
}/* 串口發送字符串 */
void USART1_SendString(char *str) {while(*str) {USART_SendData(USART1, *str++);while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);}
}