画电机驱动板这件事,我最早是打算用6个MOS管自己搭三相桥的。当时想得很简单:不就是六路PWM去推六个管子嘛。结果真到画原理图的时候才发现,栅极驱动不是接个三极管就完事的,高边MOS管浮地驱动靠什么供电、上下管怎么防直通、过流了怎么快速保护、三路电流采样放大器用什么样的方案,这些问题每一个都能让板子多烧几个版本。后来改成DRV8301,把这些底层问题打包给芯片处理,整个项目才真正跑起来。
这篇文章就围绕从原理图到PCB绘制DRV8301驱动板的完整过程展开,把关键器件怎么选型、每个模块怎么连线、SPI初始化代码怎么写、以及我实际调试时踩过的坑,都整理出来。准备画第一块电机驱动板的朋友,或者FOC算法已经写好但还在为功率板发愁的朋友,这篇文章基本就是照着抄作业的底稿。我自己用的是Altium Designer和立创EDA两个工具画过不同版本,原理图到PCB的流程在哪个工具里都差不多,文中不会绑定某个特定软件。
1. 为什么这块驱动板要选DRV8301:从手搓三相驱动到一体化方案
1.1 手搓三相驱动电路的真实成本
先说说我当时想自己搭方案时算的一笔账。
三相全桥需要6颗MOS管,这好办。但栅极驱动部分,低边MOS管可以直接用半桥驱动芯片,高边MOS管的栅极电压必须高于母线电压,这就绕不开自举浮地或者隔离电源。用自举方案要加自举电容、自举二极管,还要算高边PWM占空比不能太大,否则自举电容充不上电;用隔离电源方案,一个隔离模块几十块钱,BOM成本直接上去。
还没完。电机相电流是要做闭环的,FOC至少要两路电流采样,方波控制也最好三路都采。分立方案一般用运放搭差分放大电路,需要处理共模电压、偏置、滤波,调试起来又是一堆事。再加上过流保护,得自己弄比较器加基准源,或者依赖MCU的ADC快速判断,反应速度远不如硬件保护。
我那时候大概估算了一下,分立方案要额外加至少6到8颗有源器件,原理图复杂度翻倍,PCB布局面积变大,每个器件的寄生参数都会影响最终波形。最痛苦的还不是画板,是调试:某天波形突然抖了,你根本不知道是运放偏置漂了、电容老化了,还是PCB走线干扰。与其这样,不如选一颗集成度高的驱动芯片。
1.2 DRV8301内部到底帮你干了哪些活
DRV8301是TI推出的三相栅极驱动芯片,它把驱动板最核心的一层东西都做进去了。我按功能分块说一下:
- 三相半桥栅极驱动器:能直接驱动6颗N沟道MOSFET,内置电荷泵和自举管理逻辑,高边驱动不再需要你操心浮地问题。
- 三个电流检测放大器(CSA):专门为低边采样电阻设计,增益可以通过SPI配置成10、20、40、80 V/V,输出直接给MCU的ADC,省掉外部运算放大器。
- 内置Buck降压转换器:芯片内部有一个Buck控制器,可以从母线电压降压输出给MCU或逻辑部分供电,很多评估板上直接用它输出3.3V。
- SPI可配置保护:过流阈值、死区时间、电流放大器增益都可以通过寄存器配置,不用改PCB就能调整参数。
- 完整保护机制:PVDD欠压锁定、GVDD欠压锁定、MOSFET过流保护、芯片过热保护,故障状态通过nFAULT引脚和状态寄存器上报。
有了这些,原理图的核心部分就简化成“DRV8301 + 6颗MOS管 + 自举电容 + 采样电阻 + MCU”。我给的判断是:如果你的项目是PMSM或者BLDC驱动,母线电压在中低压范围,希望有一套可靠又容易调通的功率级,DRV8301这类芯片是比搭分立方案更务实的选择。
1.3 适合用DRV8301的项目画像与选型边界
DRV8301也不是万能的。我自己做过几个板子之后,对它的适用边界认识得更清楚。
适合它的场景很典型:24V、36V、48V电池供电的机器人关节、电动工具、水族水泵、无人机电调、伺服驱动器,功率从几十瓦到几百瓦都常见。这类应用通常用FOC算法,需要比较干净的电流采样信号和可靠过流保护,DRV8301刚好都满足。配合STM32F103或者F405这类MCU,画板难度和代码难度都处于“一个人搞定的范围”。
但如果你做的是很小的玩具电机,比如5V、12V电压、几安培电流,那用带MOSFET的集成电机驱动芯片更划算,没必要上一颗DRV8301加外部MOS管;反过来如果你做的是几千瓦的大功率驱动器,母线电压高、相电流大,DRV8301的栅极驱动能力和QFN封装散热能力就不太够,更适合用隔离型栅极驱动变压器方案、或者用Gate Driver IC加外部驱动级。
选型的时候还有一点要留意:DRV8301有不同后缀和车规版本,工作电压范围、封装、SPI寄存器定义可能存在差异。我用的多数是DRV8301标准版本,但每次拿到芯片我都会重新看对应型号的数据手册,而不是背参数。
2. 画原理图前先定架构:电源树、采样电阻与自举电容的选型逻辑
2.1 从PVDD开始的电源分配
画原理图第一步不是放芯片,而是把整块板的电源树画清楚。DRV8301驱动板上的电源需求大概是这样:
- 母线电源PVDD:这是整个功率级的输入,直接给三相半桥供电,也进DRV8301内部做栅极驱动和Buck的输入。母线电压决定了系统的功率上限。
- 栅极驱动电压GVDD:DRV8301内部从PVDD降压产生,大概是10V级别,用于给栅极驱动器和自举电路供电。这个电压不需要外部提供,但必须在外部接合适的去耦电容,否则驱动能力不够。
- 逻辑/控制电压:MCU、编码器、传感器需要的3.3V或5V,可以用DRV8301内置Buck输出,也可以用外部DC-DC。用内置Buck的话要算好反馈电阻,我一般习惯让Buck输出3.3V给MCU,因为这样MCU的ADC参考和DRV8301的逻辑电平是对齐的。
画一张电源分配草图,会很直观地看到每一路电压从哪来、要供给谁、去耦电容放哪里。这块不提前规划,后面画PCB的时候很容易出现MCU供电被功率回路干扰的问题。
2.2 电流采样电阻怎么选
电流采样是最容易拍脑袋但又不该拍脑袋的地方。DRV8301的电流放大器的输入是SP/SN差分对,采样电阻放在低边MOS管源极和GND之间,也就是低边采样方案。
采样电阻的阻值,直接影响满量程电流、采样电压和损耗,需要综合计算。核心公式是:
采样电阻压降 = 相电流 × 采样电阻阻值
DRV8301电流放大器的输入满量程一般在几百毫伏量级(具体看数据手册和寄存器配置),假设你希望峰值50A电流时采样电压不超过25mV,那么采样电阻阻值大约等于25mV / 50A = 0.5mΩ。反过来,如果电流小、想提高信噪比,可以用大一点的阻值。
但阻值越大,损耗越大,损耗公式是P = I²×R。我用一个表格估算一下不同阻值在不同电流下的情况:
| 采样电阻 | 电流30A时压降 | 电流30A时损耗 | 电流50A时压降 | 电流50A时损耗 |
|---|---|---|---|---|
| 0.2mΩ | 6mV | 0.18W | 10mV | 0.5W |
| 0.5mΩ | 15mV | 0.45W | 25mV | 1.25W |
| 1mΩ | 30mV | 0.9W | 50mV | 2.5W |
从这个表格能看出来,大电流场景用0.5mΩ甚至0.2mΩ比较合理,小电流场景可以用1mΩ或2mΩ来保证信号幅度。采样电阻要选合金材料、低温度系数的品种,引脚和焊盘要能承受对应功率的发热。
2.3 自举电容与栅极电阻的取值逻辑
DRV8301内部已经处理了高边驱动的大部分逻辑,但外部还是要接自举电容和自举二极管。自举电容的容值选择,要看高边MOS管的栅极总电荷Qg和PWM频率。
自举电容的作用是给高边MOS管的栅极充放电提供一个悬浮的电源。当低边MOS导通时,开关节点SH被拉到地,GVDD通过自举二极管给自举电容充电;当高边需要导通时,就靠自举电容里存的电荷去驱动高边栅极。容值太小,高边栅极电压会掉得厉害;容值太大,充电时间变长,高占空比会来不及补充。
我常用的经验是0.1uF到1uF之间,具体可以按这个估算:电容上的电荷量要远大于MOS管栅极总电荷,也就是C×ΔV大于Qg。比如MOS管Qg是50nC,自举电容电压变化允许0.5V,那么C至少要50nC / 0.5V = 100nF。实际因为还有漏电和损耗,我一般会放大2到3倍。电容要用X7R等温度特性稳定的陶瓷电容,耐压至少16V或25V。
栅极电阻的选择也类似。栅极电阻用来控制MOS开关的dv/dt和di/dt,阻值太大开关变慢损耗变大,阻值太小容易振铃甚至损坏栅极。10Ω到22Ω是比较常见的范围。如果想加快关断速度,可以在栅极电阻上并联一个二极管,让开通电流走电阻、关断电流走二极管。
2.4 不要忽略的去耦电容和逻辑电平问题
DRV8301的PVDD引脚、GVDD引脚、Buck输出引脚都要放去耦电容,而且去耦电容要靠近对应引脚放置,不能隔了很远再接地。这是因为去耦电容的作用是为高频开关电流提供低阻抗回路,放远了回路电感变大,高频噪声就会通过引脚串进去。
逻辑电平方面,DRV8301的IN1、IN2、IN3是PWM输入,一般兼容3.3V逻辑,SPI接口的SDO/SDI/SCLK/nSCS也是3.3V逻辑域。如果你用的MCU是5V供电,就需要加电平转换或者确认引脚是否容忍5V输入,否则长期工作可能损坏芯片引脚。
3. 原理图分块绘制:电源、三相桥、电流采样和SPI接口逐个落地
3.1 电源输入与滤波网络
画原理图的时候我从电源入口开始,这样思路比较清楚。PVDD入口处需要并联大容量电解电容和多个陶瓷电容,形成宽频带滤波。电解电容容量一般上百微法到几百微法,负责储能和低频纹波;陶瓷电容用0.1uF到10uF不等,负责滤除高频开关噪声。
DRV8301的PVDD引脚附近必须放一颗0.1uF陶瓷电容,才能保证芯片内部电路在高频开关时供电稳定。大电流母线上还要放一个或多个低ESR电解电容,并尽量靠近MOS管的漏极。很多初学朋友画板的时候习惯把大电容放在板边入口,结果功率环路过长,开关尖峰非常高。
GVDD引脚放4.7uF到10uF的去耦电容,这个电容太小会导致栅极驱动能力下降。Buck输出电容根据负载电流选,一般22uF陶瓷电容起步,如果MCU外设有电机编码器等传感器,可以加一颗100uF电解电容做余量。
3.2 三相桥栅极驱动与MOSFET外围
DRV8301的每一相输出有GH、GL、SH三个关键引脚,分别对应高边栅极、低边栅极和开关节点。以A相为例:
- GH_A通过一个栅极电阻接到高边MOS管的栅极。
- GL_A通过一个栅极电阻接到低边MOS管的栅极。
- SH_A接到高边MOS管的源极和低边MOS管的漏极连接点,这是半桥的中点,也就是电机相线输出。
- 自举电容连接在BST_A和SH_A之间,BST_A通过一个二极管接到GVDD。
- 采样电阻从低边MOS管的源极接到GND,SP_A和SN_A作为差分输入接到采样电阻两端。
MOS管的选择要和母线电压、相电流匹配。电压余量我一般留到1.5到2倍,比如48V母线选100V规格的MOS管;电流就看热耗散,不能只看额定电流,还要算导通损耗和开关损耗。
还有一个细节:GH到栅极的这一小段走线不要串电感元件,也不要在栅极回路里加磁珠。磁珠在高频下会引入阻抗,容易让栅极波形出现振铃。
3.3 电流采样放大器网络
DRV8301的电流采样放大器输出是SO_A、SO_B、SO_C,连接到MCU的ADC引脚。SO输出是模拟电压信号,建议在靠近MCU ADC引脚的地方加一级RC低通滤波,比如100Ω串联电阻加1nF电容,截止频率大概在1.6MHz左右,可以滤掉一部分开关噪声。
SP/SN差分输入引脚的走线,在原理图阶段就要有意识地安排成一对差分信号,而不是一根随便拉出去。采样电阻应该采用四线开尔文连接的思路:功率电流从电阻的大焊盘流过,而SP/SN信号线从电阻的内侧单独引出,避免覆盖到功率电流路径上的压降。这部分在原理图阶段看起来只是两根线,但到PCB阶段影响非常大。
在立创EDA或Altium Designer里,我给采样电阻做封装时,会专门用两个小焊盘来对应SP/SN,而不是直接连在大焊盘上。这样后面画PCB时才能保证开尔文连接不被破坏。
3.4 SPI配置接口与故障反馈回路
DRV8301的SPI接口有四根线:SCLK、SDI、SDO、nSCS,另外还有一个nFAULT开漏输出。nFAULT引脚我习惯接一颗10kΩ上拉电阻到3.3V,然后接到MCU的GPIO中断引脚。一旦芯片内部检测到过流、欠压、过热等异常,nFAULT会拉低,MCU就能立刻知道出事了。
SPI接口的芯片选择引脚nSCS我用MCU的普通GPIO控制,这样方便软件上通过拉低拉高产生片选时序。SCLK和SDI/SDO在闲置时最好有确定的电平,避免干扰导致误读写,可以在SCLK上加下拉电阻或者在代码里把SPI外设设为在片选拉高时才激活。
原理图阶段还有一件事值得提前做:把MCU的引脚分配表列出来。比如我用STM32F103C8T6的时候,三个PWM通道用TIM1的CH1、CH2、CH3及互补输出,SPI用SPI1的PA5、PA6、PA7、PA4作为片选,三个ADC通道用PA0、PA1、PA2。这些提前定好,画原理图时引脚不会乱,画PCB时走线也更顺畅。
我把DRV8301常见引脚整理成一个简化表格,方便画原理图时对照:
| 引脚功能 | 引脚名 | 连接目标 | 关键注意事项 |
|---|---|---|---|
| 电源输入 | PVDD | 母线电源、滤波电容 | 靠近芯片放0.1uF电容 |
| 栅极驱动电源 | GVDD | 去耦电容、自举二极管 | 4.7uF以上电容 |
| 高边栅极输出 | GH_A/B/C | 栅极电阻→高边MOS栅极 | 走线尽量短 |
| 低边栅极输出 | GL_A/B/C | 栅极电阻→低边MOS栅极 | 走线尽量短 |
| 开关节点 | SH_A/B/C | 高边源极、低边漏极、电机相线 | 自举电容回接点 |
| 自举电源 | BST_A/B/C | 自举二极管、自举电容 | 电容靠近芯片放置 |
| 电流采样输入 | SP_x/SN_x | 采样电阻两端 | 开尔文连接 |
| 电流放大器输出 | SO_x | MCU ADC | 加RC滤波 |
| SPI接口 | SCLK/SDI/SDO/nSCS | MCU SPI | 注意时序、片选 |
| 故障输出 | nFAULT | MCU GPIO中断 | 上拉电阻10kΩ |
4. PCB布局布线的实战原则:功率回路、采样走线与散热设计
4.1 功率回路要“小环”,不要“大圈”
PCB布局里最重要的一件事,是缩小功率换流回路的面积。三相桥的每个半桥都有一条关键的换流回路:母线输入电容经过高边MOS、开关节点、低边MOS再回到电容负极。这条回路在开关瞬间di/dt非常大,回路面积越大,寄生电感越大,关断时产生的电压尖峰就越高。
我前一版板子就是因为母线电容放得离MOS管太远,相线上测到的尖峰电压比母线电压高了将近一倍,后来把电容挪到靠近MOS管漏极和源极之间,尖峰马上降了下来。在实际布局时,我会把母线电容放在半桥电路的正上方或正下方,MOS管排列成一条线,栅极驱动芯片靠近它们,整个换流回路尽量重叠。
对于电流比较大的走线,可以用公式估算或经验值:外层1oz铜厚,10mil走线大约能过1A电流,20mil能过2A,但这是非常保守的经验值。功率路径我更推荐用大面积的铺铜或者加开窗镀锡,而不是用一根细走线扛电流。特别是MOS管源极到采样电阻的连接,必须用铺铜来减小电阻和电感。
4.2 栅极驱动、自举电容与走线寄生参数
栅极驱动信号GH、GL是高频开关信号,走的路径虽然电流不大,但阻抗要低、寄生电感要小。GH到栅极电阻之间、栅极电阻到MOS栅极之间,走线长度尽量控制在毫米级,不要绕来绕去。走线宽度建议在15mil以上,能铺铜更稳妥。
自举电容的位置很关键。我之前有一版设计,自举电容放在芯片同一侧偏远的角落,结果高边驱动波形明显塌陷。原因就是电容到芯片BST引脚、再到SH引脚的回路太长。后面改成把自举电容紧贴DRV8301的BST和SH引脚放置,同样占空比下波形立刻正常了。
还有一点,MOS管栅极和SH节点之间其实天然存在一个回路,如果栅极走线和源极走线围成的面积大,开关时会产生明显的振铃。所以布局要把高边MOS的栅极路径和源极路径靠近走,减小环路。
4.3 电流采样走线的开尔文连接
电流采样走线是信号完整性的重点。SP和SN是差分信号线,必须从采样电阻的专用采样焊盘上单独引出,并且尽量并行走线,中间可以隔地线或者保持紧耦合。它们要远离GH、GL这些开关节点,避免被开关尖峰耦合。
什么是开尔文连接?就是被测电压的引出点和流过电流的路径不是同一个接触点,避免接触电阻和走线电阻带来的压降误差。你可以这样理解:用万用表测电池电压,如果把表笔夹在通往负载的大电流线上,测到的电压会包含线缆自身的压降;必须用另一对细导线直接触到电池端子上测。采样电阻走线同理。
DRV8301的电流放大器是差分输入,共模抑制能力不错,但前提是SP和SN的走线阻抗尽量对称。如果一根长一根短,或者一根离开关节点近一根远,差分信号里就会混入不一样的噪声。我在画板时会在采样电阻下面尽量留一块完整地平面,SP/SN走线在上面走,形成良好的参考平面。
4.4 QFN封装底部散热设计与过孔阵列
DRV8301用的是QFN封装,底部有一个大焊盘,这个焊盘既是地连接,也是主要的散热通道。如果散热做得不好,芯片内部的热保护频繁触发,板子会莫名其妙停机。
PCB上对应底部焊盘的位置要开相同大小的铜皮区域,然后打一排过孔阵列到内层和底层铜皮。过孔孔径0.3mm左右,间距0.6到0.8mm,注意过孔间距太密会导致焊盘吸热太多、焊接困难。底层对应区域也做成一块大铜皮,不要在这个区域下面走敏感信号线,否则正好被芯片的发热和开关噪声干扰。
如果板子发热量很大,还可以考虑把底层铜皮扩大到一定面积后加螺丝孔固定散热片。我在做48V方案时,就在底层加了一块25平方厘米左右的铺铜区域,芯片温度比不加散热铜皮低了不少。
4.5 层叠设计与地平面处理
双面板能不能做DRV8301驱动板?能,但很痛苦。双面板没有完整地平面,功率回路和信号回路都靠走线连接,寄生参数比较严重。我第一版就是双面板,调试的时候电流采样噪声很大,后来改成四层板,噪声改善特别明显。
四层板我推荐“信号/功率层 + 完整地平面 + 电源/功能层 + 信号/控制层”的叠层组合。第二层做完整地平面,所有芯片的地引脚就近打过孔下去,功率地和控制地在采样电阻的接地点附近单点汇合。
很多朋友问功率地和控制地要不要分开。如果分开成两个地网络,必须在某个单点连起来,而且只能有一个点。这个点选在采样电阻的GND端比较合理,这样功率电流不会流经控制电路的地,控制地相对安静。但分开地网络也会带来麻烦:如果分地没处理好,地弹噪声反而更严重。所以我在实际项目里,如果功率不是特别大,还是倾向用完整地平面,靠布局和走线来控制噪声。
电源平面也要注意,PVDD和Buck输出这些有较大电流的电源走线尽量用铺铜,不要用细线。控制信号和功率信号在空间上分开,从电气上形成“高低压隔离”的概念,这里的隔离主要指爬电间距和电磁耦合,不是指安全隔离。安全隔离需要额外的隔离器件,不在这个板子的范围内。
5. 固件骨架:DRV8301的SPI配置与带死区PWM输出
5.1 DRV8301的SPI帧结构
DRV8301的SPI帧是16位,大致结构是1位读写标志、5位寄存器地址、10位数据。具体每一位的定义要以数据手册为准,但如果你拿到任何一个DRV8301的例程,底层逻辑基本都是这样。
写操作时,MCU把16位帧通过SDI发进去;读操作时,MCU同样发一个读命令帧,芯片在SDO上把对应寄存器的值移出来。所以读操作需要同时进行发送和接收。SPI模式方面,我见过不少例程用的是Mode 1(CPOL=0、CPHA=1),但不同版本和不同电路板可能不一样。如果读回来的寄存器值全是0xFF或者0x00,优先怀疑SPI模式配置和片选时序。
初始化前,我强烈建议先读一遍Status寄存器,看看上电后芯片处于什么状态。如果故障位已经置1,后面配置寄存器也可能不生效。
5.2 底层SPI读写函数
下面这段是STM32 HAL库风格的DRV8301 SPI底层读写函数。核心就是把16位帧拆成两个字节发送,并且片选信号在整帧传输期间保持低电平。
#define DRV8301_STATUS1_REG 0x00 #define DRV8301_STATUS2_REG 0x01 #define DRV8301_CONTROL_REG 0x02 #define DRV8301_GATE_CTRL_REG 0x03 #define DRV8301_OCP_CTRL_REG 0x04 #define DRV8301_CSA_CTRL_REG 0x05 static void drv8301_cs_low(void) { HAL_GPIO_WritePin(DRV_CS_GPIO_Port, DRV_CS_Pin, GPIO_PIN_RESET); } static void drv8301_cs_high(void) { HAL_GPIO_WritePin(DRV_CS_GPIO_Port, DRV_CS_Pin, GPIO_PIN_SET); } static uint16_t drv8301_spi_transfer16(uint16_t frame) { uint8_t tx[2]; uint8_t rx[2]; uint16_t result; tx[0] = (frame >> 8) & 0xFF; tx[1] = frame & 0xFF; drv8301_cs_low(); HAL_SPI_TransmitReceive(&hspi1, tx, rx, 2, 10); drv8301_cs_high(); result = ((uint16_t)rx[0] << 8) | rx[1]; return result; } static void drv8301_write(uint8_t reg, uint16_t data) { uint16_t frame = ((uint16_t)(reg & 0x1F) << 11) | (data & 0x3FF); drv8301_spi_transfer16(frame); }读操作类似,只是帧的读写位要置为读方向,同时SDI这边发0或者发无关数据。一般读函数我会封装成:
static uint16_t drv8301_read(uint8_t reg) { uint16_t frame = ((uint16_t)(reg & 0x1F) << 11); return drv8301_spi_transfer16(frame); }注意这只是一个框架,在实际工程里要把片选引脚、SPI句柄换成自己的定义。还有一点:DRV8301的片选信号在两次传输之间要保证有一定的高电平时间,太短的片选间隔可能导致寄存器写入不稳定。
5.3 初始化配置的关键寄存器
初始化配置主要是死区时间、过流保护阈值、电流放大器增益这几个。死区时间关乎上下管会不会直通,过流保护阈值决定最大允许电流,电流放大器增益影响ADC采样的分辨率。下面是我常用的一段初始化流程:
void drv8301_setup(void) { // 等待芯片上电稳定 HAL_Delay(10); // 先读一次状态寄存器,确认没有上电故障 uint16_t status1 = drv8301_read(DRV8301_STATUS1_REG); if (status1 & 0x0001) { // 最低位一般对应故障汇总,具体位定义以手册为准 } // 配置Gate Driver Control寄存器:死区时间、驱动电流 // 死区时间根据所用MOS管和PWM频率调整,常用几百ns到1us // 这里的0x0002是示意值,需对照寄存器位域逐位确认 drv8301_write(DRV8301_GATE_CTRL_REG, 0x0002); // 配置OCP Control寄存器:过流保护阈值、过流响应模式 // 阈值要结合采样电阻和电机峰值电流来选 drv8301_write(DRV8301_OCP_CTRL_REG, 0x0005); // 配置CSA Control寄存器:电流放大增益、采样保持等 // 增益选择:20V/V对应CSA_GAIN=某个编码,具体看手册 drv8301_write(DRV8301_CSA_CTRL_REG, 0x0002); // 配置完后再读一次状态,确认没有新故障 status1 = drv8301_read(DRV8301_STATUS1_REG); }这里我特别想强调:不要直接照抄寄存器数值。不同批次、不同后缀的DRV8301寄存器位定义可能有差异,而且每个人用的MOS管和采样电阻不一样,死区时间、过流阈值必须按自己的实际情况算。代码里的数值只是示范,真正调的时候,要拿数据手册对照每一位,把注释写清楚。
5.4 带死区的PWM输出配置
PWM输出一般用MCU的高级定时器来做互补PWM,STM32F103用TIM1,STM32F405可以用TIM1和TIM8。互补输出的意义在于:同一相的高边和低边PWM信号能够自动插入死区时间,防止上下管同时导通。
以STM32F103在72MHz主频下输出20kHz PWM为例,如果预分频设为1,那么计数器频率是36MHz,要得到20kHz的PWM,自动重装载值等于36MHz除以20kHz等于1800,所以ARR设置为1800减1。死区时间一般在几百纳秒到微秒之间,通过定时器的BDTR寄存器配置。
下面是简化的代码逻辑:
// 假设已配置TIM1_CH1为PWM1模式,且使能了互补输出 htim1.Init.Prescaler = 1; htim1.Init.Period = 1800 - 1; htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1; HAL_TIM_PWM_Init(&htim1); // 配置死区时间,例如1us,对应BDTR寄存器DTG值需要换算 TIM_BreakDeadTimeConfigTypeDef sDeadTimeCfg; sDeadTimeCfg.DeadTime = 72; // 示意值,需按时钟计算 sDeadTimeCfg.OffStateRunMode = TIM_OSSR_DISABLE; sDeadTimeCfg.OffStateIDLEMode = TIM_OSSI_DISABLE; HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sDeadTimeCfg); // 启动PWM和互补PWM HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);使能顺序也很重要:先初始化DRV8301的SPI配置,确认nFAULT没有报警,再使能PWM输出。如果先开PWM再去配置DRV8301,芯片在默认配置下可能死区时间不够,轻则波形不对,重则烧MOS管。
6. 上电调试实录:从nFAULT报警到电流波形毛刺的排查过程
6.1 上电前检查清单
板子焊好之后,不要直接插母线电源。我每次都会按下面的清单走一遍,看起来繁琐,但能省下后面一大半调试时间:
- 用万用表二极管挡测PVDD和GND之间是否短路,重点排查MOS管安装方向和采样电阻。
- 测3.3V或MCU供电网络对地阻抗,避免上电后烧MCU。
- 目视检查DRV8301 QFN封装有没有虚焊,特别是底部散热焊盘的过孔有没有透锡到背面。
- 用可调电源限流上电,比如先限流100mA,观察电流是否正常。如果上电瞬间电流就很大,立刻断电排查短路。
- 用示波器看GVDD电压是否正常,确认栅极驱动供电建立。
这一步做到位,很多低级问题就不会带到后面。
6.2 nFAULT被拉低时的排查分支
nFAULT拉低是最常见的“板子不工作”表现。它可能指向多种故障,不能只看外观。我的排查方法是:用MCU读Status1和Status2寄存器,把故障位解析出来。
- 如果看到PVDD欠压位置位,检查母线电压是否真正加到芯片PVDD引脚,可能是滤波电容虚焊或者走线不通。
- 如果看到GVDD欠压位,检查GVDD引脚上的电容是否正常,自举二极管是否装反。
- 如果看到过流或短路位,问题多半出在MOS管或者外部驱动回路,比如某一路GH/GL没有输出导致半桥直通。
- 如果看到过热位,先检查散热焊盘是否焊接好,再确认工作电流是不是真的超出设计范围。
还有一个实际经验:DRV8301在刚上电、还没配置寄存器时,某些版本会默认把nFAULT拉低,这不代表一定故障。所以代码里要先执行初始化流程,再读状态和故障引脚,避免被初始化前的假报警误导。
6.3 波形没出来?从GVDD到自举电压逐个查
如果nFAULT正常但电机不转,波形也没有,我一般按这个顺序检查:
先用示波器量GVDD,确认栅极驱动供电有了。然后量MCU输出的PWM到DRV8301的IN引脚,确认PWM信号真的进来了。接着量GH和GL引脚,看有没有对应的栅极开关波形。最后量SH节点和电机相线输出,确认半桥中点确实有电压输出。
有一次我的板子A相高边完全没有波形,低边正常。排查下来不是芯片坏,而是自举电容到BST_A和SH_A的回路中间焊盘开路了。因为自举电容没参与工作,高边栅极完全没有悬浮电源,自然输出不了波形。把电容重新焊接后高边波形恢复。
还有一个高频坑:PWM占空比设得太高,自举电容充电时间不够。比如占空比开到99%,高边长时间导通,低边导通时间极短,自举电容靠那点时间充不回来,高边栅极电压会慢慢掉。解决方法是限制最大占空比,比如不要超过95%,或者用可编程死区时间配合自举充电策略。
6.4 电流采样噪声大:不是换电容那么简单
电流采样波形毛刺大,是画驱动板的人几乎都会碰到的问题。我第一次画板时,SO引脚出来的波形在PWM开关沿附近全是毛刺,ADC采到的值完全没法用于FOC。当时第一反应是给SO加滤波电容,结果毛刺少了但信号也滞后了,动态响应变差。
后来发现问题的根源在布局:SP和SN走线绕了一大圈,还从GH走线旁边穿过,开关噪声直接耦合进采样回路。重新布局,把SP/SN按差分紧耦合走线、包地处理、远离开关节点之后,噪声大幅下降。所以遇到采样噪声,先查布局和走线,再考虑滤波。
如果走线已经改不了,也可以通过软件手段改善。比如FOC算法里在ADC采样时刻选择上,尽量避开PWM开关瞬间;或者在PWM中心对齐模式下触发采样,因为这个时刻电流纹波最小。这个技巧配合硬件布局,效果会好很多。
提示:先用低占空比单脉冲模式看SO波形,确认采样电阻上的压降确实存在并且方向正确,再去优化噪声和滤波。这样能分清是电路问题还是布局干扰问题。
6.5 一个很实用的调板小技巧
最后分享一个我在调DRV8301驱动板时经常用的小工具:强制六步换相逻辑。在还没跑FOC之前,我写了一个简单的方波控制程序,让MCU按固定的六步顺序输出PWM,一步一停。这样如果某一路MOS管接错或者器件有问题,会立刻在对应的相线上暴露出来。有了这个基础,再切到FOC闭环,调试难度会降低很多。
另外,给驱动板单独做一个测试工装也很有必要。用排针引出GVDD、三个SO、nFAULT、SPI信号,样机阶段焊接一个简单的测试小板,调试时把探头夹在对应的测试点上,会比直接去戳QFN引脚方便很多。这个习惯我保持到现在,每次画完板子都会留几个关键测试点,后面调试省下来的时间远超这些测试点占用的那点面积。