文章目录
- 1. 项目概述
- 2. 硬件设计
- 3. 开发环境搭建
- 4. 核心代码实现
- 4.1 外部中断配置 (exti.c)
- 4.2 键盘扫描算法 (keypad.c)
- 4.3 高精度计算引擎 (calculator.c)
- 5. 系统整合与调试
- 5.1 主程序框架 (main.c)
- 5.2 常见问题解决
- 6. 完整技术图谱
1. 项目概述
1.1 设计目标
实现基于STM32的外部中断触发矩阵键盘扫描,构建支持加减乘除、括号运算的高精度浮点计算器,精度达小数点后8位。
1.2 技术选型
| 模块 | 技术方案 |
|---|
| 主控芯片 | STM32F103VET6 |
| 键盘扫描 | EXTI外部中断+行列扫描 |
| 计算核心 | 自定义大数运算库 |
| 显示输出 | LCD1602液晶屏 |
1.3 成果展示
2. 硬件设计
2.1 矩阵键盘电路
2.2 硬件连接
| STM32引脚 | 键盘接口 | 功能 |
|---|
| PA0-PA3 | ROW1-4 | 中断输入 |
| PB0-PB3 | COL1-4 | 扫描输出 |
| PC13 | LED | 状态指示 |
3. 开发环境搭建
3.1 软件清单
- STM32CubeMX v6.8.0
- Keil MDK v5.37
- ST-Link Utility
3.2 CubeMX配置步骤
- 配置PA0-PA3为EXTI中断模式
- 设置PB0-PB3为GPIO输出
- 启用SYSTICK定时器
- 生成MDK工程代码
4. 核心代码实现
4.1 外部中断配置 (exti.c)
/* 文件名:exti.c */#include"stm32f10x.h"voidEXTI_Config(void){EXTI_InitTypeDef EXTI_InitStruct;NVIC_InitTypeDef NVIC_InitStruct;// 配置PA0-PA3为中断源RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);// ... 其他引脚配置// 中断线参数设置EXTI_InitStruct.EXTI_Line=EXTI_Line0|EXTI_Line1|EXTI_Line2|EXTI_Line3;EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling;// 下降沿触发EXTI_InitStruct.EXTI_LineCmd=ENABLE;EXTI_Init(&EXTI_InitStruct);// 配置NVICNVIC_InitStruct.NVIC_IRQChannel=EXTI0_IRQn;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0x00;NVIC_InitStruct.NVIC_IRQChannelSubPriority=0x00;NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;NVIC_Init(&NVIC_InitStruct);}
4.2 键盘扫描算法 (keypad.c)
/* 文件名:keypad.c */#defineDEBOUNCE_TIME20// 消抖时间20msconstuint8_tKeyMap[4][4]={{'7','8','9','/'},{'4','5','6','*'},{'1','2','3','-'},{'C','0','=','+'}};uint8_tGetKeyValue(void){staticuint32_tlast_tick=0;if(HAL_GetTick()-last_tick<DEBOUNCE_TIME)return0xFF;// 消抖处理for(uint8_tcol=0;col<4;col++){// 设置当前列为低电平GPIO_WriteBit(GPIOB,GPIO_Pin_0<<col,Bit_RESET);// 检测行状态for(uint8_trow=0;row<4;row++){if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0<<row)==RESET){GPIO_WriteBit(GPIOB,GPIO_Pin_0<<col,Bit_SET);// 恢复列状态last_tick=HAL_GetTick();returnKeyMap[row][col];}}GPIO_WriteBit(GPIOB,GPIO_Pin_0<<col,Bit_SET);// 恢复列状态}return0xFF;// 无按键}
4.3 高精度计算引擎 (calculator.c)
/* 文件名:calculator.c */#defineMAX_DIGITS16// 最大支持16位数typedefstruct{doubleoperand1;doubleoperand2;charoperator;uint8_tinput_mode;// 0:等待操作数1, 1:等待操作数2}CalcState;voidProcessInput(CalcState*calc,charkey){staticcharnum_buffer[MAX_DIGITS+1];staticuint8_tbuf_index=0;switch(key){case'0'...'9':if(buf_index<MAX_DIGITS){num_buffer[buf_index++]=key;num_buffer[buf_index]='\0';}break;case'+':case'-':case'*':case'/':if(calc->input_mode==0){calc->operand1=atof(num_buffer);calc->operator=key;calc->input_mode=1;buf_index=0;}break;case'=':if(calc->input_mode==1){calc->operand2=atof(num_buffer);switch(calc->operator){case'+':calc->operand1+=calc->operand2;break;case'-':calc->operand1-=calc->operand2;break;case'*':calc->operand1*=calc->operand2;break;case'/':if(calc->operand2!=0)calc->operand1/=calc->operand2;break;}calc->input_mode=0;}break;}}
5. 系统整合与调试
5.1 主程序框架 (main.c)
#include"stm32f10x.h"#include"lcd.h"intmain(void){HAL_Init();EXTI_Config();LCD_Init();CalcState calculator={0};while(1){charkey=GetKeyValue();if(key!=0xFF){ProcessInput(&calculator,key);LCD_DisplayResult(calculator.operand1);}}}
5.2 常见问题解决
| 问题现象 | 解决方案 |
|---|
| 按键连击 | 增加防抖延时至50ms |
| 浮点运算精度丢失 | 使用sprintf格式化为%.8f输出 |
| LCD显示乱码 | 检查时序配置,调整延时 |
| 中断无响应 | 确认NVIC优先级配置正确 |
6. 完整技术图谱