#include <STC15F2K60S2.H> #include <intrins.h> // ???? sbit clk = P1^3; sbit dio = P1^2; // ???? void Delay_us(unsigned int i) { for(; i > 0; i--) _nop_(); } // I²C Start void I2CStart(void) { clk = 1; dio = 1; Delay_us(2); dio = 0; } // I²C Acknowledge void I2Cask(void) { clk = 0; Delay_us(5); while(dio); // ???? clk = 1; Delay_us(2); clk = 0; } // I²C Stop void I2CStop(void) { clk = 0; Delay_us(2); dio = 0; Delay_us(2); clk = 1; Delay_us(2); dio = 1; } // ??????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 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(P24 == 0) { Delay_us(2000); // 2ms ??? if(P24 == 0) { mode = (mode + 1) % 3; while(P24 == 0); // ???? } } } // ???? void SmgDisplay(void) { I2CStart(); I2CWrByte(0x40); // ???????? I2Cask(); I2CStop(); I2CStart(); I2CWrByte(0xC0); // ????? I2Cask(); if(mode == 0) // Hz?? { 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) // kHz??,???? { 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???(????1?) void Timer0Init() { AUXR |= 0x80; // T0 ?1T?? TMOD &= 0xF0; // ????? TMOD |= 0x01; // T0 ???1(16????) TL0 = 0x20; TH0 = 0xD1; // ???? 1ms TR0 = 1; // ?? T0 ET0 = 1; // ???? EA = 1; // ????? } // ???1???(??????,P3.5) void Timer1Init() { TMOD &= 0x0F; // ????? TMOD |= 0x50; // T1 ??????(??1) TL1 = 0x00; TH1 = 0x00; TR1 = 1; // ?? T1 ET1 = 1; // ?? T1 ?? } // ???0??????(?1ms????) void timer0_ISR() interrupt 1 { static unsigned int cnt = 0; cnt++; if(cnt >= 1000) // 1?????? { TR1 = 0; // ???? pinlv = times * 65536 + TH1 * 256 + TL1; cnt = 0; times = 0; TH1 = 0; TL1 = 0; TR1 = 1; } } // ???1??????(????) void timer1_ISR() interrupt 3 { times++; // ?????? } // ??? void main(void) { Timer1Init(); // ??? T1 ????(P3.5) Timer0Init(); // ??? T0 ???? while(1) { key(); SmgDisplay(); } } 修改上述代码使得7SEG-MPX4-CC可以通过STC15W4K32S4的P3.5正常点亮
时间: 2025-07-04 16:14:45 浏览: 11
为了使7SEG-MPX4-CC数码管通过STC15W4K32S4的P3.5正常点亮,我们需要分析并修改代码以适配新的单片机型号,并确保驱动逻辑与硬件一致。
---
### ✅ 修改目标
1. **适配新单片机型号**:从 `STC15F2K60S2` 改为 `STC15W4K32S4`。
2. **确认 I²C 引脚是否正确映射**(如 P1^3 和 P1^2 是否可用)。
3. **确保定时器配置兼容新芯片**。
4. **检查中断号和寄存器是否匹配新芯片手册**。
5. **确保 P3.5 用于外部计数输入(T1)功能**。
---
### ✅ 修改建议与代码说明
#### 1. 更换头文件
```c
#include <STC15W4K32S4.H>
```
#### 2. 确保 I²C 使用的引脚仍然有效(比如P1^3、P2)
若P1.3和P1.2仍可用,则无需更改。否则需更换到其他GPIO。
#### 3. 定时器部分适配
##### STC15系列中:
- T0/T1 的中断号不变,仍然是 `interrupt 1` 和 `interrupt 3`。
- 寄存器名称基本保持一致。
#### 4. 外部计数器使用 P3.5(T1)
在STC15W4K32S4中,P3.5确实是定时器1的外部计数输入端口(T1),所以不需要更改硬件连接。
---
### ✅ 修改后的完整代码如下:
```c
#include <STC15W4K32S4.H>
#include <intrins.h>
// I2C引脚定义(假设使用P1^3和P1^2)
sbit clk = P1^3;
sbit dio = P1^2;
// 微秒延时函数
void Delay_us(unsigned int i)
{
for(; i > 0; 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 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(P24 == 0)
{
Delay_us(2000); // 去抖动
if(P24 == 0)
{
mode = (mode + 1) % 3;
while(P24 == 0); // 等待释放
}
}
}
// 数码管显示函数
void SmgDisplay(void)
{
I2CStart();
I2CWrByte(0x40); // 设置数据写入地址
I2Cask();
I2CStop();
I2CStart();
I2CWrByte(0xC0); // 地址0xC0开始写数据
I2Cask();
if(mode == 0) // Hz模式
{
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) // kHz模式
{
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; // 清除低4位
TMOD |= 0x01; // 设置为16位定时器模式
TL0 = 0x20;
TH0 = 0xD1; // 1ms @ 22.1184MHz
TR0 = 1; // 启动定时器0
ET0 = 1; // 使能定时器0中断
EA = 1; // 开总中断
}
// 定时器1初始化(外部计数器)
void Timer1Init()
{
TMOD &= 0x0F; // 清除高4位
TMOD |= 0x50; // T1 设置为计数器模式(方式2)
TL1 = 0x00;
TH1 = 0x00;
TR1 = 1; // 启动定时器1
ET1 = 1; // 使能T1中断
}
// 定时器0中断服务程序(1ms一次)
void timer0_ISR() interrupt 1
{
static unsigned int cnt = 0;
cnt++;
if(cnt >= 1000) // 1秒后读取计数值
{
TR1 = 0;
pinlv = times * 65536 + TH1 * 256 + TL1;
cnt = 0;
times = 0;
TH1 = 0;
TL1 = 0;
TR1 = 1;
}
}
// 定时器1中断服务程序(溢出处理)
void timer1_ISR() interrupt 3
{
times++; // 计录溢出次数
}
// 主函数
void main(void)
{
Timer1Init(); // 初始化外部计数器T1(P3.5)
Timer0Init(); // 初始化定时器0
while(1)
{
key(); // 检测按键切换显示模式
SmgDisplay(); // 刷新数码管显示
}
}
```
---
### ✅ 代码解释
- **I2C通信模拟**:使用P1^3和P1^2模拟I²C协议,控制TM1637驱动数码管。
- **定时器0**:每1ms触发一次中断,累计到1秒后读取T1的计数值。
- **定时器1**:设置为外部计数器模式,P3.5作为输入频率测量端。
- **SmgDisplay**:根据当前模式(Hz/kHz)显示相应频率值。
- **key()**:切换显示模式。
---
### ✅ 相关问题
阅读全文
相关推荐














