我看到了论坛帖子和原理图。先说明一个关键问题,再结合手册逐条给出评审意见。
最重要的结论:选用的芯片 STC8H1K17-36I-TSSOP20 的 I/O 数量不够,这个设计跑不起来。
一、先说致命问题:I/O 引脚分配冲突
从原理图看,你的信号分配是:
| 信号 |
图中标注引脚 |
| MOT_IN2 |
P1.2 |
| MOT_IN1 |
P1.1 |
| IPROPI(电流检测) |
P1.0 |
| PWM_IN(接收机输入) |
P3.3 |
| TX / RX(串口) |
P3.1 / P3.0 |
问题 1:P3.0 与 P3.1 用于串口,会与 USB/ISP 下载冲突
按 STC8H 手册 TSSOP20 管脚说明中的“关于 I/O 的注意事项”:
- P3.0 和 P3.1 上电后状态为准双向口/弱上拉;
- 芯片上电时,若 P3.0 和 P3.1 同时为低电平,P3.2 会短暂切到双向口去读外部状态,判断是否进入软件模拟 USB 下载模式;
- 若不需要 USB 下载,P3.0/P3.1/P3.2 这 3 个 I/O 口不能同时为低电平,否则会进入软件模拟 USB 下载模式等待下载,无法运行用户程序。
你的 P3.0/P3.1 外接了 LAIL-PZ2.54 排针(TX/RX),如果排针上接了下载器、或者外部设备把这两脚拉低,上电就会卡在下载模式。建议下载排针与串口功能在 PCB 上做跳线/串阻,下载时断开外部电路。
问题 2:P3.2 完全空置,但它是下载判定的关键引脚
图中 P3.2 标为 ADC10/INT0/SCLK_4/SCL_4/PWMETI/PWMETI2,目前悬空。悬空输入是隐患(浮空引脚容易受干扰,且它参与下载模式判定)。P3.2 必须外部加固定上拉或下拉,不能浮空;若不想用,配置为推挽输出输出固定电平更稳妥。
问题 3:P1.0 既做 IPROPI 模拟量输入,又标了 PWM1P —— 需要确认用法
P1.0 = ADC0 / RxD2 / PWM1P,P1.1 = ADC1 / TxD2 / PWM1N。手册管脚表中:
- P1.0:PWM1P 为“PWM1 的捕获输入和脉冲输出正极”,I/O 类型;
- P1.1:PWM1N 为“PWM1 的脉冲输出负极”,类型为 O(纯输出)。
如果你用 PWM1 的 P/N 互补输出驱动 DRV8251 的 IN1/IN2,那 P1.1 作 PWM1N 是可以的,但 P1.0 上同时接了 IPROPI 模拟采样就会冲突——一个脚不能既做模拟输入又做 PWM 输出。电流采样必须另找 ADC 通道。
问题 4(最严重):STC8H1K17 只有 P1.0P1.7、P3.0P3.7、P5.4 这些脚,而 TSSOP20 封装实际引出的可用 I/O 约 16 个,你的设计已经用满甚至超了。
按手册 TSSOP20 管脚表,STC8H1K17-36I-TSSOP20 可用的引脚为:P1.2、P1.3、P1.4、P1.5、P1.6、P1.7、P5.4、P3.0、P3.1、P3.2、P3.3、P3.4、P3.5、P3.6、P3.7、P1.0、P1.1,共 17 个 I/O(8、9、10 脚为 Vcc/ADC_VRef+/Gnd)。图中 P1.3/P1.4/P1.5/P1.6/P1.7 全部打叉未用,P3.4/P3.5/P3.6/P3.7 也打了叉——这意味着你的可用引脚并不紧张,真正的问题是“打叉的脚没被用起来”,而关键功能却挤在了少数几个脚上。
建议重新分配:
- P1.0 → ADC0,专门做 IPROPI 电流采样(DRV8251 的 IPROPI 输出经 R1 910Ω + C1 10nF RC 滤波进 ADC,这个设计是对的);
- MOT_IN1/MOT_IN2 改用 P1.2、P1.3,把 P1.1 让出来;
- PWM_IN(接收机信号)建议用 P3.3,但要做下降沿/上升沿中断,而不是 ADC——你的接收机输出是 50Hz、20ms 周期的 PWM 脉宽信号,必须测脉宽;
- P1.1 留作串口2 TxD2 或下载保留。
二、逐条评审各电路模块
1. 电源部分(3V3 / 5V)
- U3 JW5026T6TRPB 是降压 DC-DC,输入 VM(电池),输出 5V,R4 11.2kΩ / R3 2.1kΩ 构成反馈分压,L1 4.7µH、C7 100nF(自举)、C8 10nF、C10 4.7µF、R5 100kΩ、C6 10nF —— 这是典型的 5V 降压外围,没问题;
- U4 TPS7A2030PDBVR 把 5V 降到 3V3 给 MCU,输出 C9 1µF、输入 C8 1µF,符合该 LDO 的推荐配置;
- 建议:MCU 的 Vcc 脚(第 8 脚)旁缺少本地去耦电容标注。你图中 C4 22µF + C5 100nF 接在 3V3 上是对的,但22µF 电解/陶瓷电容应靠近 U1 的 8 脚布置,100nF 尽量贴近 Vcc-Gnd 引脚,否则 ADC 精度会受电源纹波影响。
- ADC_VRef+(第 9 脚)必须接 3V3 或外部基准,不能浮空。手册明确:“如果芯片有 ADC 的外部参考电源管脚 ADC_VRef+,则一定不能浮空,必须接外部参考电源或者直接连到 VCC”。图中第 9 脚接了 ADC_VRef+ 标注,需确认实际连到 3V3,且建议在 9 脚就近加 100nF + 1µF 到地。
2. DRV8251 部分
- U2 DRV8251ADDAR,IN1/IN2 接 MOT_IN1/MOT_IN2,VREF 接 3V3,IPROPI 经 R1 910Ω 并联 C1 10nF 到地后送 MCU 的 IPROPI 脚;
- R1 910Ω 是 IPROPI 的电流标定电阻,DRV8251 的 IPROPI 输出电流与负载电流成比例(约 1/1000 级),乘以 R1 得电压。你 0.8A 堵转电流,按 DRV8251 手册 ITRIP 比例计算,910Ω 是否合适需要核算,但电原理上 RC 滤波是对的;
- 注意 C2 100nF + C3 47µF 接在 VM 与 GND 之间,这是 VM 电源旁路,正确。但 OUT1/OUT2 到电机的走线要粗,且 OUT 脚到 GND 最好各加 100nF~1µF 的尖峰吸收电容(靠近芯片),否则有刷电机的换向噪声会打穿芯片;
- DRV8251 的 PAD(散热焊盘)必须焊接到地平面并打过孔散热,0.8A 堵转时芯片会发热。
3. 电机控制逻辑
DRV8251 是 PH/EN 型或 IN/IN 型驱动(取决于 nSLEEP 模式)。从图中看 IN1/IN2 直接进,属于 IN/IN 控制:
- MOT_IN1=1,MOT_IN2=0 → OUT1 高、OUT2 低 → 正转;
- MOT_IN1=0,MOT_IN2=1 → 反转;
- MOT_IN1=MOT_IN2=0 → 滑行(coast);
- MOT_IN1=MOT_IN2=1 → 刹车(brake)。
实现“正反转 + 停”完全够用,不需要 PWM。但如果你要做调速,把 PWM 加到 IN1 或 IN2 上即可(此时另一个脚保持低)。
4. 接收机信号 PWM_IN
- 你用的是 50Hz / 20ms 周期、脉宽 1ms~2ms 的标准航模接收机信号;
- 这副信号必须用定时器捕获或外部中断 + 定时器测脉宽,绝不能用 ADC 采;
- P3.3 有 INT1 和 PWM4N_4 / PWM7_2 复用,用 INT1 下降沿中断 + 定时器 T0 记录时间差是最稳妥的做法(对 STC8H 来说,所有 I/O 都支持中断,手册第 15 章“所有的 I/O 口均可中断,不是传统外部中断”);
- P3.3 作输入前必须配置为高阻输入或准双向,且外部加上拉/下拉电阻。接收机输出是推挽的,一般高阻输入即可,但加上 10kΩ 下拉更抗干扰。
5. 串口部分
- P3.0 = RxD、P3.1 = TxD,用于和上位机通信,接 4 脚排针;
- P3.1/P3.0 上电必须是高电平才能正常跑用户程序(见问题 1)。排针上如果接了 USB 转串口模块,其 TXD 空闲为高,通常没问题;但若模块未上电,RXD 端可能被拉低,需注意;
- 建议在 P3.1(TX)上串 100Ω~330Ω 电阻,P3.0(RX)上串 1kΩ 电阻,防止下载时冲突。
6. 空置引脚
- 图中 P1.3
P1.7、P3.4P3.7 全打叉悬空。建议把未用 I/O 配置为准双向口并输出高电平(或设为推挽输出高),避免浮空引入干扰和额外功耗。手册 TSSOP20 管脚说明明确:“其余所有 I/O 口上电后的状态均为高阻输入状态,用户在使用 I/O 口前必须先设置 I/O 口模式”。
三、还缺的东西
- 没有下载/仿真接口的说明。TSSOP20 最小系统需要 P3.0/P3.1(串口下载)或 USB(P3.0/P3.1 是 USB D-/D+)。图中有个 LAIL-PZ2.54-4P 标注为 USB?如果是,USB D-/D+ 必须接 P3.0/P3.1,且要串 22Ω 电阻;如果它只是 UART 排针,那么下载只能靠串口。
- 没有复位电路。P5.4 与 nRST 复用,图中 P5.4 打叉,说明用了内部复位,这是可以接受的;但建议 P5.4 保留一个 10kΩ 上拉到 3V3,防止误复位。
- 没有看门狗。车规应用建议开启 WDT 并在主循环喂狗。
- 没有电机反电动势/过流保护。除了 IPROPI 采样,建议在 VM 处加 TVS 或自恢复保险丝。
四、代码框架建议(Keil C51)
如果确认用 P1.0 做 ADC0 采 IPROPI、P1.2/P1.3 驱动 MOT_IN1/MOT_IN2、P3.3 用 INT1 捕获接收机脉宽:
#include "stc8h.h"
#include <stdio.h>
#include <string.h>
#define MOT1 P12 /* MOT_IN1 */
#define MOT2 P13 /* MOT_IN2 */
volatile unsigned int rc_pulse = 1500; /* 接收机脉宽,单位 us */
/* 系统时钟 11.0592MHz 时的 1us 定时器初值(1T 模式) */
#define T0_1US (65536 - 100) /* 若为 12T 或其它频率需重算 */
void Timer0_Init(void)
{
AUXR |= 0x80; /* T0 为 1T 模式 */
TMOD &= 0xF0;
TMOD |= 0x01; /* 模式 1,16 位 */
TL0 = T0_1US & 0xFF;
TH0 = T0_1US >> 8;
TR0 = 1;
}
/* P3.3 = INT1,下降沿触发 */
void INT1_Init(void)
{
P3M0 &= ~0x08; /* P3.3 高阻输入 */
P3M1 |= 0x08;
IT1 = 1; /* 下降沿触发 */
EX1 = 1;
EA = 1;
}
void main(void)
{
unsigned int t_start = 0;
unsigned int width;
P1M0 &= ~0x0C; /* P1.2/P1.3 准双向输出 */
P1M1 &= ~0x0C;
P1M0 |= 0x0C;
P1M1 &= ~0x0C;
/* ADC 配置:ADC0 = P1.0,高阻输入 */
P1M0 &= ~0x01;
P1M1 |= 0x01;
ADC_CONTR = 0x80; /* 打开 ADC 电源 */
ADCCFG = 0x0F;
EADC = 1; /* 使能 ADC 中断 */
Timer0_Init();
INT1_Init();
while (1)
{
if (rc_pulse > 1500 + 50) {
MOT1 = 1; MOT2 = 0; /* 正转 */
} else if (rc_pulse < 1500 - 50) {
MOT1 = 0; MOT2 = 1; /* 反转 */
} else {
MOT1 = 0; MOT2 = 0; /* 停止/滑行 */
}
}
}
void INT1_ISR(void) interrupt 2
{
unsigned int now = (TH0 << 8) | TL0;
static unsigned int last = 0;
unsigned int dt;
if (last) {
dt = now - last;
if (dt > 800 && dt < 2200) {
rc_pulse = dt; /* 单位:us,需按定时器实际刻度换算 */
}
}
last = now;
}
说明:上面的定时器刻度换算需按你实际选择的系统时钟频率调整 T0_1US 值。STC8H 的 T0 在 1T 模式下每系统时钟计 1 次。若系统时钟 24MHz,则 1us = 24 个时钟,初值应为 65536 - 24。
另外,不需要把 ADC 采样放在中断里做,建议主循环轮询 IPROPI 值,超过阈值就关断电机。
五、总结优先级
- P3.0/P3.1 下载冲突(高优先,会导致上电不跑程序);
- P1.0 不能同时作 ADC 与 PWM1P(高优先,电流检测失效);
- ADC_VRef+ 必须接 3V3 并加滤波(中,否则 ADC 不准);
- PWM_IN 用中断捕获而非 ADC(中);
- 未用 I/O 设推挽输出固定电平(中,抗干扰);
- DRV8251 散热焊盘接地 + OUT 脚尖峰吸收电容(中,可靠性);
- 看门狗、复位上拉、串口串阻(低,但车规建议加)。
如果你能把 P1.2/P1.3 改成 MOT_IN1/MOT_IN2 并把 P1.0 独立出来做 ADC0,整体方案就基本成立了。
🔍 搜索 "STC 单片机 论坛 帖子"
⏱️ 查找用时 6.0s | 总回答用时 29.8s