STM32簡易計算機設計

運用 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);}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/81454.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/81454.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/81454.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

sparkSQL讀入csv文件寫入mysql

思路 示例 &#xff08;年齡>18改成>20) mysql的字符集問題 把user改成person “讓字符集認識中文”

計算機視覺與深度學習 | Python 實現SO-CNN-BiLSTM多輸入單輸出回歸預測(完整源碼和源碼詳解)

SO-CNN-BiLSTM **一、代碼實現****1. 環境準備****2. 數據生成(示例數據)****3. 數據預處理****4. 模型構建****5. 模型訓練****6. 預測與評估****二、代碼詳解****1. 數據生成****2. 數據預處理****3. 模型架構****4. 訓練配置****5. 結果可視化****三、關鍵參數說明****四、…

Windows軟件插件-音視頻捕獲

下載本插件 音視頻捕獲就是獲取電腦外接的話筒&#xff0c;攝像頭&#xff0c;或線路輸入的音頻和視頻。 本插件捕獲電腦外接的音頻和視頻。最多可以同時獲取4個視頻源和4個音頻源。插件可以在win32和MFC程序中使用。 使用方法 首先&#xff0c;加載本“捕獲”DLL&#xff0c…

ios打包ipa獲取證書和打包創建經驗分享

在云打包或本地打包ios應用&#xff0c;打包成ipa格式的app文件的過程中&#xff0c;私鑰證書和profile文件是必須的。 其實打包的過程并不難&#xff0c;因為像hbuilderx這些打包工具&#xff0c;只要你輸入的是正確的證書&#xff0c;打包就肯定會成功。因此&#xff0c;證書…

CycleISP: Real Image Restoration via Improved Data Synthesis通過改進數據合成實現真實圖像恢復

摘要 大規模數據集的可用性極大釋放了深度卷積神經網絡(CNN)的潛力。然而,針對單圖像去噪問題,獲取真實數據集成本高昂且流程繁瑣。因此,圖像去噪算法主要基于合成數據開發與評估,這些數據通常通過廣泛假設的加性高斯白噪聲(AWGN)生成。盡管CNN在合成數據集上表現優異…

《Python星球日記》 第70天:Seq2Seq 與Transformer Decoder

名人說:路漫漫其修遠兮,吾將上下而求索。—— 屈原《離騷》 創作者:Code_流蘇(CSDN)(一個喜歡古詩詞和編程的Coder??) 目錄 一、Seq2Seq模型基礎1. 什么是Seq2Seq模型?2. Encoder-Decoder架構詳解1??編碼器(Encoder)2??解碼器(Decoder)3. 傳統Seq2Seq模型的局限性…

Android 性能優化入門(二)—— 內存優化

1、概述 1.1 Java 對象的生命周期 各狀態含義&#xff1a; 創建&#xff1a;分配內存空間并調用構造方法應用&#xff1a;使用中&#xff0c;處于被強引用持有&#xff08;至少一個&#xff09;的狀態不可見&#xff1a;不被強引用持有&#xff0c;應用程序已經不再使用該對象…

GCC 版本與C++ 標準對應關系

GCC 版本 與支持的 C 標準&#xff08;C11、C14、C17、C20、C23&#xff09; 的對應關系 GCC 版本與 C 標準支持對照表 GCC 版本默認 C 標準C11C14C17C20C23GCC 4.8C98? (部分支持)????GCC 4.9C98? (完整支持)????GCC 5.1C98?? (完整支持)???GCC 6.1C14??? …

5、事務和limit補充

一、事務【都是重點】 1、了解 一個事務其實就是一個完整的業務邏輯。 要么同時發生&#xff0c;要么同時結束。 是一個最小的工作單元。 不可再分。 看這個視頻&#xff0c;黑馬的&#xff0c;4分鐘多點就能理解到 可以理解成&#xff1a; 開始事務-----如果中間拋出異常…

一套基于 Bootstrap 和 .NET Blazor 的開源企業級組件庫

前言 今天大姚給大家分享一套基于 Bootstrap 和 .NET Blazor 的開源企業級組件庫&#xff1a;Bootstrap Blazor。 項目介紹 BootstrapBlazor 是一套基于 Bootstrap 和 Blazor 的開源&#xff08;Apache License&#xff09;、企業級組件庫&#xff0c;無縫整合了 Bootstrap …

mac-M系列芯片安裝軟件報錯:***已損壞,無法打開。推出磁盤問題

因為你安裝的軟件在Intel 或arm芯片的mac上沒有簽名導致。 首先打開任何來源操作 在系統設置中配置&#xff0c;如下圖&#xff1a; 2. 然后打開終端&#xff0c;輸入&#xff1a; sudo spctl --master-disable然后輸入電腦鎖屏密碼 打開了任何來源&#xff0c;還遇到已損壞…

RK3568-鴻蒙5.1與原生固件-扇區對比分析

編譯生成的固件目錄地址 ../openharmony/out/rk3568/packages/phone/images鴻蒙OS RK3568固件分析 通過查看提供的信息&#xff0c;分析RK3568開發板固件的各個組件及其用途&#xff1a; 主要固件組件 根據終端輸出的文件列表&#xff0c;RK3568固件包含以下關鍵組件&#x…

Java正則表達式:從基礎到高級應用全解析

Java正則表達式應用與知識點詳解 一、正則表達式基礎概念 正則表達式(Regular Expression)是通過特定語法規則描述字符串模式的工具&#xff0c;常用于&#xff1a; 數據格式驗證文本搜索與替換字符串分割模式匹配提取 Java通過java.util.regex包提供支持&#xff0c;核心類…

進程間通信--信號量【Linux操作系統】

文章目錄 并發編程相關基礎概念信號量深刻理解信號量使用共享資源的方式分塊使用共享資源的方式會出現的問題舉例子理解信號量的第二個特性---預定信號量要成為計數器面臨的問題 信號量相關操作接口--POSIX庫函數&#xff1a;sem_init庫函數&#xff1a;sem_destroy庫函數&…

謝賽寧團隊提出 BLIP3-o:融合自回歸與擴散模型的統一多模態架構,開創CLIP特征驅動的圖像理解與生成新范式

BLIP3-o 是一個統一的多模態模型&#xff0c;它將自回歸模型的推理和指令遵循優勢與擴散模型的生成能力相結合。與之前擴散 VAE 特征或原始像素的研究不同&#xff0c;BLIP3-o 擴散了語義豐富的CLIP 圖像特征&#xff0c;從而為圖像理解和生成構建了強大而高效的架構。 此外還…

HarmonyOs開發之——— ArkWeb 實戰指南

HarmonyOs開發之——— ArkWeb 實戰指南 謝謝關注!! 前言:上一篇文章主要介紹HarmonyOs開發之———合理使用動畫與轉場:CSDN 博客鏈接 一、ArkWeb 組件基礎與生命周期管理 1.1 Web 組件核心能力概述 ArkWeb 的Web組件支持加載本地或在線網頁,提供完整的生命周期回調體…

黑馬程序員C++2024版筆記 第0章 C++入門

1.C代碼的基礎結構 以hello_world代碼為例&#xff1a; 預處理指令 #include<iostream> using namespace std; 代碼前2行是預處理指令&#xff0c;即代碼編譯前的準備工作。&#xff08;編譯是將源代碼轉化為可執行程序.exe文件的過程&#xff09; 主函數 主函數是…

日語學習-日語知識點小記-構建基礎-JLPT-N4階段(22):復習

日語學習-日語知識點小記-構建基礎-JLPT-N4階段(22):復習 1、前言(1)情況說明(2)工程師的信仰2、知識點(1)復習(2)復習3、單詞(1)日語(2)日語片假名單詞4、對話練習5、單詞辨析記錄6、總結1、前言 (1)情況說明 自己在今年,在日本留學中,目前在語言學校,…

Docker配置SRS服務器 ,ffmpeg使用rtmp協議推流+vlc拉流

目錄 演示視頻 前期配置 Docker配置 ffmpeg配置 vlc配置 下載并運行 SRS 服務 推拉流流程實現 演示視頻 2025-05-18 21-48-01 前期配置 Docker配置 運行 SRS 建議使用 Docker 配置 Docker 請移步&#xff1a; 一篇就夠&#xff01;Windows上Docker Desktop安裝 漢化完整指…

Redis——緩存雪崩、擊穿、穿透

緩存雪崩 大量緩存數據在同一時間過期或者Redis故障宕機時&#xff0c;若此時有大量請求&#xff0c;都會直接訪問到數據庫&#xff0c;導致數據庫壓力倍增甚至宕機。 大量數據同時過期解決方案&#xff1a; 1、均勻設置過期時間&#xff1a; 設置過期時間的時候可以追加一…