AUXR equ 8EH ORG 0000H LJMP main ORG 0023H LJMP RSU ORG 0100H main: MOV P0,#11H MOV P2,#88H MOV R0,#0 MOV R1,#0 MOV R2,#0 MOV SCON,#50H ;8位数据, ,晶振频率11.0592MHz,波特率9600 ANL AUXR,#0BFH ;定时器1时钟为Fosc/12,即12T ANL AUXR,#0FEH ;串口1选择定时器1为波特率发生器 MOV TMOD,#20H ;设定定时器1为8位自动重装方式 MOV TL1,#0FDH ;设定定时初值 MOV TH1,#0FDH ;设定定时初值 CLR ET1 ;禁止定时器1中断 SETB TR1 ;启动定时器1 SETB EA ;开启总中断允许 SETB ES ;开启串口中断 SJMP $ ;等待中断 RSU: CLR RI ;中断服务子程序 MOV A, SBUF MOV R3, A ANL A, #0FH MOV DPTR, #TAB0 MOVC A, @A+DPTR MOV P0, A MOV A, R3 SWAP A ANL A,#0FH MOV DPTR, #TAB2 MOVC A,@A+DPTR MOV P2, A RETI TAB0: DB 11H,0D7H,32H,92H,0D4H,98H,18H,0D3H,10H,90H,50H,1CH,39H,16H,38H,78H TAB2:DB 88H,0EBH,4CH,49H,2BH,19H,18H,0CBH,08H,09H,0AH,38H,9CH,68H,1CH,1EH END 根据以上代码编写正确程序接受由PC机通过串口助手向单片机发送的从00到99的一个字节的压缩BCD数据,并将数据在数码管上正确显示(例如输入04个位是4十位是0)。且单片机向PC机发送数据,按键S1控制数码管从00到99加计数循环显示,按下按键S2将当前显示的数字发送到串口调试助手的接收缓存区。
时间: 2025-07-01 15:33:38 浏览: 6
### 优化后的单片机程序设计
以下是一个基于用户需求的单片机程序优化方案,包括串口中断处理逻辑、按键扫描部分的具体实现以及数码管显示控制。代码使用C语言编写,并假设单片机为常见的8位微控制器(如51系列)。
#### 1. 程序框架与功能模块划分
程序分为以下几个主要模块:
- **串口中断接收模块**:用于接收PC机发送的压缩BCD数据。
- **数码管显示模块**:将接收到的数据或加计数结果在数码管上正确显示。
- **按键扫描模块**:实现S1和S2按键的功能控制。
- **串口发送模块**:当按下S2时,将当前数字发送到串口助手。
#### 2. 具体实现代码
```c
#include <reg52.h>
sbit S1 = P3^0; // 定义按键S1
sbit S2 = P3^1; // 定义按键S2
unsigned char currentNumber = 0; // 当前显示的数字
unsigned char receiveBuffer = 0; // 接收缓冲区
// 数码管段码表
const unsigned char codeTable[] = {
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90
};
// 初始化串口
void UART_Init() {
TMOD = 0x20; // 设置定时器模式为方式2
TH1 = 0xFD; // 波特率设置为9600bps
SCON = 0x50; // 8位数据,1位停止位,允许接收
TR1 = 1; // 启动定时器1
EA = 1; // 开启总中断
ES = 1; // 开启串口中断
}
// 数码管显示函数
void Display_Number(unsigned char num) {
unsigned char tens = num / 10; // 十位
unsigned char units = num % 10; // 个位
P0 = codeTable[tens]; // 显示十位
P2_7 = 0; // 选择十位数码管
delay(5); // 延时
P0 = codeTable[units]; // 显示个位
P2_7 = 1; // 选择个位数码管
delay(5); // 延时
}
// 按键扫描函数
void Key_Scan() {
if (!S1) { // 检测S1按键
while (!S1); // 消抖
currentNumber++; // 加计数
if (currentNumber > 99) { // 循环显示
currentNumber = 0;
}
}
if (!S2) { // 检测S2按键
while (!S2); // 消抖
SBUF = currentNumber / 10 + '0'; // 发送十位
while(TI == 0); // 等待发送完成
TI = 0;
SBUF = currentNumber % 10 + '0'; // 发送个位
while(TI == 0); // 等待发送完成
TI = 0;
}
}
// 串口中断服务程序
void Uart_ISR() interrupt 4 {
if(RI) { // 接收中断
RI = 0; // 清除接收标志
receiveBuffer = SBUF; // 读取接收数据
currentNumber = ((receiveBuffer >> 4) * 10) + (receiveBuffer & 0x0F); // 解析压缩BCD
}
}
// 延时函数
void delay(unsigned int time) {
unsigned int i, j;
for(i = 0; i < time; i++) {
for(j = 0; j < 120; j++);
}
}
void main() {
UART_Init(); // 初始化串口
while(1) {
Key_Scan(); // 扫描按键
Display_Number(currentNumber); // 显示当前数字
}
}
```
#### 3. 关键点说明
- **串口中断处理逻辑**:通过串口中断接收来自PC机的压缩BCD数据,并将其解析为十进制数值[^1]。压缩BCD数据中,高4位表示十位,低4位表示个位。
- **数码管显示控制**:使用查表法获取对应数字的段码值,并通过分时复用技术交替显示十位和个位数字[^2]。
- **按键扫描实现**:通过检测S1和S2的状态实现加计数循环显示及当前数字发送功能。为了消除按键抖动,加入简单的消抖处理[^3]。
- **串口发送模块**:当按下S2时,先发送当前数字的十位字符,再发送个位字符。确保数据以ASCII格式发送到串口调试助手[^4]。
####
阅读全文
相关推荐


















