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.mzph.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; 设置过期时间的时候可以追加一…