#include <reg52.h> #include <intrins.h> // ??????? STC15 ??,?????? stc15.h ??? reg52.h // ????????????? // ?? STC15 ????? sfr AUXR = 0x8E; // ???? sbit clk = P1^3; sbit dio = P1^2; sbit P2_4 = P2^4; // ???????? // ???? void Delay_us(unsigned int i) { while(i--) _nop_(); } // I2C Start void I2CStart(void) { clk = 1; dio = 1; Delay_us(2); dio = 0; Delay_us(2); clk = 0; } // I2C Acknowledge void I2Cask(void) { clk = 0; Delay_us(5); while(dio); // ???? clk = 1; Delay_us(2); clk = 0; } // I2C Stop void I2CStop(void) { dio = 0; clk = 1; Delay_us(2); dio = 1; Delay_us(2); } // ?????? TM1637 void I2CWrByte(unsigned char oneByte) { unsigned char i; for(i = 0; i < 8; i++) { clk = 0; if(oneByte & 0x01) dio = 1; else dio = 0; Delay_us(3); oneByte >>= 1; clk = 1; Delay_us(3); } } // ?????? unsigned char code smg_code[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F}; // ?????? unsigned long pinlv = 0; unsigned long times = 0; unsigned int tick = 0; unsigned char mode = 0; // ???? void key() { if(P2_4 == 0) { Delay_us(10000); // ???? if(P2_4 == 0) { mode = (mode + 1) % 3; while(P2_4 == 0); // ?????? } } } // ??????? void SmgDisplay() { I2CStart(); I2CWrByte(0x40); // ???????? I2Cask(); I2CStop(); I2CStart(); I2CWrByte(0xC0); // ???0???? I2Cask(); if(mode == 0) { I2CWrByte(smg_code[pinlv / 10000]); I2Cask(); I2CWrByte(smg_code[(pinlv / 1000) % 10]); I2Cask(); I2CWrByte(smg_code[(pinlv / 100) % 10]); I2Cask(); I2CWrByte(smg_code[(pinlv / 10) % 10]); I2Cask(); } else if(mode == 1) { I2CWrByte(smg_code[pinlv / 100000]); I2Cask(); I2CWrByte(smg_code[(pinlv / 10000) % 10] | 0x80); I2Cask(); // ????? I2CWrByte(smg_code[(pinlv / 1000) % 10]); I2Cask(); I2CWrByte(smg_code[(pinlv / 100) % 10]); I2Cask(); } I2CStop(); I2CStart(); I2CWrByte(0x8F); // ???? I2Cask(); I2CStop(); } // ???0???(1ms??) void Timer0Init() { AUXR |= 0x80; // T0?1T?? TMOD &= 0xF0; // ????? TMOD |= 0x01; // 16???? TL0 = 0x20; TH0 = 0xD1; // 1ms @ 22.1184MHz TR0 = 1; ET0 = 1; EA = 1; } // ???1???(?????) void Timer1Init() { TMOD &= 0x0F; TMOD |= 0x50; // T1?????? TL1 = 0x00; TH1 = 0x00; TR1 = 1; ET1 = 1; } // ???0??????(1ms??) void timer0_ISR(void) interrupt 1 using 1 { static unsigned int cnt = 0; cnt++; if(cnt >= 1000) { TR1 = 0; pinlv = times * 65536 + TH1 * 256 + TL1; cnt = 0; times = 0; TH1 = 0; TL1 = 0; TR1 = 1; } } // ???1?????? void timer1_ISR(void) interrupt 3 using 1 { times++; } // ??? void main(void) { Timer1Init(); Timer0Init(); while(1) { key(); SmgDisplay(); } } 上面的代码只能让7SEG-MPX4-CC闪烁,无法正常显示相应的频率。面对这种情况,应该如何修改代码,使得数码管可以正确显示输入的频率
时间: 2025-07-14 14:39:45 浏览: 7
你提供的代码是基于 **STC15 单片机** 使用 TM1637 驱动的四位共阴数码管(7SEG-MPX4-CC)来显示频率。目前的现象是数码管只能闪烁而无法正常显示,这说明可能的问题在于:
1. **TM1637 通信时序不正确**
2. **数码管段码或位选设置错误**
3. **显示逻辑或刷新频率问题**
---
## ✅ 解决方案
我们主要从以下几个方面入手进行修改:
### 🔧 1. 确认 TM1637 通信协议是否正确
TM1637 的 I2C 是一种简化的同步串行接口,需要确保:
- Start/Stop 条件正确
- 数据在 `CLK` 上升沿被采样
- 每个字节发送后有一个 ACK 回应
### 🔧 2. 显示函数 SmgDisplay() 修改为支持 TM1637 正确地址和数据格式
TM1637 地址格式如下:
| 命令 | 含义 |
|------|------|
| `0x40` | 自动地址递增模式 |
| `0xC0` | 设置显示位置(从0开始)|
### 🔧 3. 数码管段码数组确认是否为共阴极
你的段码数组看起来是标准共阴段码,但需要确认硬件连接是否一致。
---
## ✅ 修改后的关键代码如下:
```c
// 正确的段码定义(共阴)
unsigned char code smg_code[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
// 显示数字 0~9
void SmgDisplay() {
unsigned char digit[4]; // 存放每一位要显示的数字
// 分解频率值到各个位数
digit[0] = (pinlv / 1000) % 10;
digit[1] = (pinlv / 100) % 10;
digit[2] = (pinlv / 10) % 10;
digit[3] = pinlv % 10;
// 发送命令:写入显示数据(自动地址加一)
I2CStart();
I2CWrByte(0x40); // 写入数据到 TM1637 RAM
I2Cask();
I2CStop();
// 发送命令:设置起始地址 C0H
I2CStart();
I2CWrByte(0xC0); // 起始地址 0
I2Cask();
// 写入4位数码管数据
for (int i = 0; i < 4; i++) {
I2CWrByte(smg_code[digit[i]]); // 写入段码
I2Cask();
}
I2CStop();
// 打开显示并设置亮度(0x8F 表示最高亮度)
I2CStart();
I2CWrByte(0x8F);
I2Cask();
I2CStop();
}
```
---
## 🛠️ 其他建议优化点
### 1. 延迟函数优化(避免使用 _nop_ 太多)
```c
void Delay_us(unsigned int us) {
while(us--) {
_nop_();
_nop_();
_nop_();
_nop_();
}
}
```
### 2. 按键消抖优化(增加延时)
```c
void key() {
static unsigned char key_flag = 0;
if(P2_4 == 0) {
Delay_us(10000); // 延时消抖
if(P2_4 == 0 && !key_flag) {
mode = (mode + 1) % 3;
key_flag = 1;
}
} else {
key_flag = 0;
}
}
```
---
## ✅ 总结修改内容
| 修改项 | 说明 |
|--------|------|
| `SmgDisplay()` 函数 | 更正为符合 TM1637 协议的数据格式与地址 |
| 段码数组验证 | 确保是共阴极段码,并与实际数码管匹配 |
| 按键处理 | 增加按键标志防抖 |
| 延迟函数 | 精准控制时序以满足 TM1637 通信要求 |
---
##
阅读全文
相关推荐



















