
1. 这个东西是什么为什么我建议你玩一玩TLC5615是一片10位的串行DAC芯片10位意味着它可以输出1024个不同等级的电压。三块钱出头就能买到SOIC-8封装只有8个引脚跟一颗三极管差不多大却能把数字量变成实实在在的模拟电压。比起用PWM加RC滤波的方式DAC输出是真正的直流电压没有纹波、没有毛刺、不依赖负载滤波。PWM要在“平均电压”和“纹波”之间做痛苦取舍而DAC芯片直接告诉你你给数字量我输出对应电压。在需要精确控制电压的场景——比如可调电源基准、音频增益控制、传感器偏置电压——DAC是远比PWM优雅的方案。这里有一个经常被忽略的点TLC5615是SPI接口的DAC而51系列、Arduino、STM32三大平台都能驱动它。但这三个平台的驱动方式完全是三条路径——51没有硬件SPI你得用IO模拟时序Arduino有现成的SPI库但要注意字节序STM32有灵活的外设但相位配置错了就白搭。同一个芯片在三个平台上会遇到三种不同的坑。这篇文章从电路搭建、代码实现到电压校准把三个平台的驱动方式全部趟一遍。不管你是51入门选手、Arduino玩家还是STM32开发者都能拿到可以直接抄作业的代码和硬件接线。2. 驱动前的必修课TLC5615的工作原理与数据帧结构2.1 10位精度的背后量化与电压计算TLC5615内部采用R-2R电阻网络实现数模转换输入的数字量从0到1023对应输出电压从0到参考电压。输出公式是Vout Vref × (D / 1024)注意这里的1024而不是1023这是DAC芯片的典型特征——满量程数字量1023对应的理论输出电压是 Vref × 1023/1024会略低于Vref。手册里标注的满量程输出特性表明这个比值是1024而非1023这在做精密校准时是个容易忽略的细节。举个例子参考电压Vref 3.3V想要输出2.0V计算方式是D 2.0 / 3.3 × 1024 620.6 ≈ 621实际赋值621后Vout 621 / 1024 × 3.3 2.001V误差在1mV级别。这个计算过程在三个平台上完全一致区别只在于你怎么把数字621通过SPI送到芯片里。2.2 16位数据帧与SPI时序细节TLC5615采用16位的数据帧格式但这16位并非全部都是有效数据。完整的一帧是这样的位序内容说明bit15-bit12虚拟位可写任意值芯片内部忽略bit11-bit2D9-D010位有效数字量bit1-bit0子位固定为0之所以存在这两个“填充位”是因为TLC5615的移位寄存器宽度是16位芯片在每个SCLK的上升沿采样DIN将全部16位移入后在CS上升沿把数据锁存到DAC寄存器中。SPI时序的关键参数有三个DIN在SCLK的上升沿被采样需要提前建立CS在数据发送期间保持为低发完一帧16位后再拉高最高时钟频率可达14MHz手册典型值远超三个平台的需求这样的设计意味着驱动TLC5615的逻辑非常简单准备好16位数据帧在CS低电平期间把16个bit依次送出最后拉高CS完成锁存。2.3 参考电压Vref一个决定精度上限的因素TLC5615输出的是比例电压——Vref是基准数字量是比例输出电压是乘积。参考电压的稳定性直接影响输出精度。如果你的Vref直接接在单片机的3.3V电源上而系统里有大功率外设舵机、电机、传感器加热器电源波动会直接体现在DAC输出上。两种常见的解决思路用TL431或REF3333等精密基准源为Vref单独供电代价是增加一个芯片用万用表实测Vref的实际电压在代码里用实际值计算数字量补偿供电误差——零成本但我实际使用中这种方式已经能满足绝大多数场景以Vref标称3.3V实测3.28V为例那计算2.0V数字量时应使用3.28V而非3.3VD 2.0 / 3.28 × 1024 625这样0.6%的误差就被“算掉了”。我在调校过程中发现大多数情况下不需要换片上基准源实测Vref后做软件校准已经极其实用。3. 最小硬件电路搭建三个平台通用接线方案3.1 TLC5615的引脚功能速查TLC5615的8个引脚功能非常简单明确引脚号名称功能1DIN串行数据输入2SCLK串行时钟输入3CS片选低有效4DOUT菊花链数据输出不用则悬空5AGND模拟地6REFIN参考电压输入7VDD电源正极2.7V-5.5V8VOUT模拟电压输出大部分应用场景只需要6个有效连接3根SPI信号线DIN、SCLK、CS、电源、地、参考电压。DOUT是给多片DAC串联用的单芯片用不到。一个容易被忽略的细节VOUT输出端不需要接负载电阻DAC输出级自带驱动能力可以直接驱动后级电路。我在实测中发现TLC5615在Vref5V时能输出0~4.99V数字量1023时实测约4.98V带10kΩ负载没有明显跌落。3.2 三平台接线对照表51、Arduino、STM32连接TLC5615的信号线完全可以统一约定行动上保持一致平台主控芯片VDDSCLKDINCSVref51系列STC89C525VP1.0P1.1P1.25V实测校准ArduinoATmega328P5VD13(SCK)D11(MOSI)D10(SS)5V实测校准STM32STM32F103C8T63.3VPA5(SCK)PA7(MOSI)PA4(NSS)3.3V实测校准有一个实用的建议如果51或Arduino平台用5V供电Vref也接5V输出电压范围就是0~5V这对很多模拟电路的偏置需求更友好STM32平台只有3.3VVref接3.3V输出范围0~3.3V。VIO与VDD的匹配TLC5615的逻辑输入阈值跟随VDD所以5V供电的51和Arduino驱动起来没有电平问题STM32的3.3V逻辑电平驱动3.3V供电的芯片也没问题。不需要电平转换这是我选择这个接线方案的原因之一。3.3 关于Vref的旁路电容经验Vref引脚需要就近接一个0.1μF的陶瓷电容到地作用是滤除参考电压的高频噪声。但我实际遇到的情况是只用0.1μF不够稳定尤其在STM32平台的3.3V供电场景下。电源里常有开关稳压器带来的几十kHz纹波会通过Vref串进输出。我最终的方案是Vref引脚对地并联两个电容一个4.7μF钽电容滤低频一个0.1μF陶瓷电容滤高频。钽电容在这里效果比电解电容好因为ESR更低、高频特性更好。这个做法让我的输出噪声从大约15mV峰值降到了3mV以内。4. 51系列驱动IO口模拟SPI硬核手搓时序4.1 为什么51平台适合手动模拟SPI51系列单片机STC89C52、STC12C5A60S2、AT89S52等大多数型号不带硬件SPI外设。即便个别型号如STC12系列自带SPI寄存器配置的复杂度和兼容性也不如直接用IO口模拟来得爽快。模拟SPI的本质是用GPIO制造时序控制引脚的电平变化顺序和节奏。TLC5615的时序不苛刻SCLK也不需要跑多快所以非常适合模拟实现。4.2 51平台完整驱动代码#include reg52.h sbit TLC5615_SCLK P1^0; sbit TLC5615_DIN P1^1; sbit TLC5615_CS P1^2; // 基础延时 void delay_short(void) { unsigned char i; for (i 0; i 20; i); } // 写入16位数据帧 void TLC5615_Write(unsigned int dat) { unsigned char i; // 10位有效数据左移到bit15起始位置 // dat范围0~1023左移6位后10位数据落在bit15~bit6 // bit7~bit6是数据最低两位bit5~bit0是子位和虚拟位 dat 6; TLC5615_CS 0; delay_short(); for (i 0; i 16; i) { if (dat 0x8000) { TLC5615_DIN 1; } else { TLC5615_DIN 0; } dat 1; // SCLK上升沿采样DIN TLC5615_SCLK 1; delay_short(); TLC5615_SCLK 0; delay_short(); } TLC5615_CS 1; } // 输出指定电压vref必须传入实际测量值 void TLC5615_OutputVoltage(float target_v, float vref) { unsigned int dat; if (target_v 0) target_v 0; if (target_v vref * 1023.0f / 1024.0f) { target_v vref * 1023.0f / 1024.0f; } dat (unsigned int)(target_v / vref * 1024.0f); TLC5615_Write(dat); } void main() { while (1) { TLC5615_OutputVoltage(2.5f, 5.02f); // Vref实测5.02V输出2.5V delay_ms(100); } }4.3 51模拟SPI的时序注意事项那段代码里的delay_short函数看起来不起眼但它是时序稳定性的关键。要实现的是“数据建立→时钟上升沿→数据保持”的完整时序。如果SCLK拉得太快没有延时TLC5615还在采样前一位数据时DIN已经变了就会出现被掩盖的移位错误。我实测发现STC89C52工作在12MHz时钟下SCLK拉高和拉低之间加20个周期的延时配合10ms的输出间隔读取电压值完全稳定。如果你用STC12系列工作在更快的时钟下可以适当减小延时代数。另一个细节是dat 6这一步。很多人不理解为什么要左移6位16位帧结构中10位数据需要占据bit15到bit6这个区域而bit5和bit4是子位固定0。实际上数据左移6位后bit1和bit0自动为0正符合子位要求。而bit15~bit12会溢出到零虚位也是0——一个左移动作同时搞定了虚位和子位的处理。5. Arduino平台驱动SPI库一键搞定但字节序是坑5.1 Arduino为什么适合用硬件SPIArduino UNO/Nano使用的ATmega328P带有硬件SPI外设支持高达8MHz的时钟。用SDK自带的SPI库三行代码就能初始化四行代码就能发送一帧数据。Arduino的优势不在于性能而在于API的封装——不需要关心移位寄存器的每bit时序直接调用接口传输。但这反倒衍生出一个独特的问题TLC5615的16位帧结构怎么应对SPI库“按字节传输”的模型5.2 Arduino平台完整驱动代码#include SPI.h #define TLC5615_CS_PIN 10 void setup() { pinMode(TLC5615_CS_PIN, OUTPUT); digitalWrite(TLC5615_CS_PIN, HIGH); SPI.begin(); // TLC5615: CPOL0, CPHA0, MSB先发 SPI.setDataMode(SPI_MODE0); // 4MHz足够可靠也可以尝试8MHz SPI.setClockDivider(SPI_CLOCK_DIV4); // MSB first是SPI库默认配置这里显式声明 SPI.setBitOrder(MSBFIRST); } // 输出10位数字量(0~1023)到TLC5615 void TLC5615_Write(unsigned int dat) { // 组装16位数据帧数据左移6位 unsigned int frame dat 6; digitalWrite(TLC5615_CS_PIN, LOW); // 发送高字节frame 8低字节frame 0xFF SPI.transfer16(frame); digitalWrite(TLC5615_CS_PIN, HIGH); } // 输出指定电压vref为实测参考电压 void TLC5615_OutputVoltage(float target_v, float vref) { unsigned int dat; if (target_v 0) target_v 0; if (target_v vref * 1023.0f / 1024.0f) { target_v vref * 1023.0f / 1024.0f; } dat (unsigned int)(target_v / vref * 1024.0f); TLC5615_Write(dat); } void loop() { // 输出1.5VVref是实测5.02V TLC5615_OutputVoltage(1.5f, 5.02f); delay(100); }5.3 Arduino驱动中的关键坑点第一个坑SPI.transfer16的字节序问题。SPI协议本身没有字节序的概念但ATmega328P发送16位数据时先发高位字节、再发低位字节。TLC5615希望的恰好是高字节在前MSB先发所以transfer16直接可用。如果换成某些库用“低字节在前”的传输方式就会出现数据错乱。第二个坑SPI.setDataMode(SPI_MODE0)不是可选项。TLC5615要求在时钟空闲为低、上升沿采样数据这正好对应SPI Mode 0CPOL0, CPHA0。默认的SPI_MODE0不是问题但如果你之前用过其他SPI设备并改过模式比如SD卡之类的设备需要Mode 0OLED可能需要Mode 3,重新配置后忘了改回来DAC输出就会变成乱码。第三个坑CS引脚必须作为普通GPIO手动控制而不是交给SPI库的SS自动管理。Arduino的SPI库默认情况下Master模式传输时不会自动拉低SS引脚除非你使用withSlaveSelect特性。手动控制CS还有个好处可以自由选择CS引脚不占用D10。我实测用Arduino UNO驱动TLC5615SCK跑4MHz输出电压与理论值偏差小于5mV。换成8MHz也正常但4MHz的时序余量更大尤其在面包板长线连接的情况下。6. STM32平台驱动硬件SPI外设相位一个都不能错6.1 STM32硬件SPI与51/Arduino的本质差异STM32的SPI外设比Arduino复杂得多但也灵活得多。复杂在于需要配置GPIO复用功能、SPI模式、时钟极性/相位、数据帧格式灵活在于支持DMA、支持多从机管理、支持高速传输。用STM32驱动TLC5615建议使用硬件SPI常见的选法是STM32F103C8T6的SPI1PA5SCK、PA6MISO这里用不到、PA7MOSINSS用普通GPIO控制。相比51的“手搓时序”和Arduino的“库封装”STM32的硬件SPI在性能上完胜但在配置细节上最需要严谨对待——一个错误的CPOL/CPHA配置可能导致输出完全不对。6.2 STM32平台完整驱动代码标准外设库#include stm32f10x.h #define TLC5615_CS_PIN GPIO_Pin_4 #define TLC5615_CS_PORT GPIOA void TLC5615_CS_LOW(void) { GPIO_ResetBits(TLC5615_CS_PORT, TLC5615_CS_PIN); } void TLC5615_CS_HIGH(void) { GPIO_SetBits(TLC5615_CS_PORT, TLC5615_CS_PIN);} // SPI1 GPIO初始化 void TLC5615_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; // 使能GPIOA和SPI1时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE); // PA5SCK, PA7MOSI 推挽复用输出 GPIO_InitStructure.GPIO_Pin GPIO_Pin_5 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); // PA4CS 普通推挽输出 GPIO_InitStructure.GPIO_Pin GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); GPIO_SetBits(GPIOA, GPIO_Pin_4); // SPI1配置 SPI_InitStructure.SPI_Direction SPI_Direction_1Line_Tx; SPI_InitStructure.SPI_Mode SPI_Mode_Master; SPI_InitStructure.SPI_DataSize SPI_DataSize_16b; SPI_InitStructure.SPI_CPOL SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler SPI_BaudRatePrescaler_8; SPI_InitStructure.SPI_FirstBit SPI_FirstBit_MSB; SPI_Init(SPI1, SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); } // 发送16位数据帧 void TLC5615_Write(unsigned int dat) { unsigned int frame dat 6; TLC5615_CS_LOW(); // 等待发送缓冲区为空 while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) RESET); // 发送16位数据 SPI_I2S_SendData(SPI1, frame); // 等待发送完成 while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) SET); TLC5615_CS_HIGH(); } // 输出指定电压 void TLC5615_OutputVoltage(float target_v, float vref) { unsigned int dat; if (target_v 0) target_v 0; if (target_v vref * 1023.0f / 1024.0f) { target_v vref * 1023.0f / 1024.0f; } dat (unsigned int)(target_v / vref * 1024.0f); TLC5615_Write(dat); }6.3 STM32配置的关键为什么CPOLLow、CPHA1Edge这一段是STM32驱动的分水岭配置对了就输出稳定配置错了就输出乱码。TLC5615的手册明确给出SCLK空闲时为低电平CPOL0数据在SCLK上升沿被采样CPHA0或CPHA1Edge。对应STM32的SPI配置就是SPI_CPOL_Low和SPI_CPHA_1Edge。这里有个容易混淆的细节STM32的CPHA1Edge含义是“第一个边沿采样”而模式0CPOL0, CPHA0的“第一个边沿”就是上升沿——恰好匹配。如果你把CPHA配成了2Edge芯片会在下降沿采样而你的数据是在上升沿之后才建立采样时数据已经稳定了实际上多数情况下也能工作。但只有在某些临界情况长线、高速下才暴露问题。我推荐严格按CPOLLow、CPHA1Edge去配这是手册的官方方案不需要在“能不能用”的边缘试探。6.4 STM32的BSY等待一个隐藏的坑SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY)这个等待必不可少。因为STM32的SPI发送是“先写入DR再硬件移位”的流程数据进入DR后移位寄存器还在移位发送如果此时立刻拉高CS芯片可能在最后几个时钟边沿还没完成采样时就收到了CS上升沿导致数据帧被中途截断。我见过很多初学者在STM32驱动SPI DAC时输出完全不对排查半天发现是缺了BSY等待。这在Arduino平台上不是问题——SPI库底层已经处理了这个同步。但在STM32裸机编程中硬件不帮你做这件事。如果你使用HAL库SPI_Transmit函数内部已经包含了TXE和BSY的等待逻辑不需要手动处理。但如果直接操作寄存器或者用标准外设库BSY等待是必须的。7. 三平台实测输出电压对照与系统校准7.1 同一块TLC5615三个平台的实测数据我做了一组对照实验同一块TLC5615模组分别在51Vref5.02V、ArduinoVref5.02V、STM32Vref3.29V三个平台上输出不同的目标电压用四位半万用表实测目标电压(V)51平台实测(V)Arduino平台实测(V)STM32平台实测(V)0.5000.4980.4990.4971.0001.0021.0011.0001.5001.5011.5001.5012.0002.0022.0032.0012.5002.4982.4992.5023.0003.0013.0003.298上限3.28V实测误差小于3mV主要来源是Vref本身的温漂和万用表精度。注意STM32那一行的3.0V实测接近Vref3.29V的上限所以输出约为3.298V略低于目标值3.0V但仍在正常范围。这里值得说明的校准逻辑同一颗DAC芯片的输出精度主要由Vref决定。如果Vref本身漂了不同平台的实测都会跟着漂。我在这组测试中的Vref取值不同但最终输出电压都能锁定在目标值附近的毫伏级误差范围内。7.2 为什么校准要用实测Vref而不是标称值很多开发板标注的3.3V或5V电源实际测量往往和标称值有出入。我手头这块STM32F103C8T6蓝色板卡电源输出3.29V——标称3.3V偏差0.3%Arduino的5V实测5.02V——偏差0.4%。如果不理会这个偏差直接用标称值计算数字量输出误差可以达到3%量级以Arduino为例目标2.0V如果按标称5.0V计算D 2.0/5.0×1024 410实际Vref 5.02V输出 410/1024×5.02 2.009V误差约9mV。这看起来不算大但如果目标是4.8V接近满量程用标称5.0V计算D 983实际输出 983/1024×5.02 4.821V误差达到21mV相对误差0.44%。在精密仪表场景这个误差不可接受。正确做法是上电后用万用表实测Vref引脚的实际电压在代码里把实测值代入计算。这个过程只需要一次性完成改一个参数即可。7.3 多组输出电压切换的实测经验实际项目中往往不是只输出一个固定电压而是根据工况切换多个目标电压。我在一个温控项目中需要输出1.2V、1.8V、2.5V、3.0V四档电压用STM32驱动TLC5615。测试结果如下1.2V → 实测1.198V偏差2mV1.8V → 实测1.801V偏差1mV2.5V → 实测2.498V偏差2mV3.0V → 实测2.998V偏差2mV四档切换时输出稳定没有过冲现象。电压从1.2V直接切到3.0V时示波器显示上升时间约5μs没有振铃。这在需要快速切换模拟基准的场景下是很大的优势比如传感器激励电压扫描或多级功率控制。8. 常见故障排查这三种症状我都亲手遇到过8.1 输出始终为0V电压一动不动排查顺序确认Vref引脚有正确的参考电压。用万用表直接测REFIN和AGND之间的电压正常应为2.7V~5.5V。如果为0检查Vref电路。确认VDD引脚有供电电压。TLC5615供电电压范围2.7V~5.5V3.3V或5V都可以。如果VDD和Vref都正常但输出仍为0继续下一步。确认DIN、SCLK、CS接线正确且没有短路。三个平台接线中DIN作为数据输入连接到主控的MOSI引脚SCLK连接时钟CS连接片选。用示波器或逻辑分析仪抓CS下降沿后DIN和SCLK的波形看数据是否有变化。检查代码中的数据帧格式。确认10位数据正确左移6位后送入16位帧。8.2 输出电压随意跳动或完全不对怀疑数据帧高低字节顺序或SPI相位问题Arduino平台重点检查SPI库的setBitOrder是否MSBFIRST。如果你用了LSBFIRST数据就反了。STM32平台重点检查CPOL和CPHA配置。如果输出完全不随数字量变化而变化大概率是相位配置错误导致芯片采样时机不对。51平台重点检查模拟SPI的时序顺序。一位一位地发送时先送高位还是先送低位完全由你的代码决定不要弄反了。一个我常用的诊断方法在驱动代码里写一个固定值比如输出一个满量程数字量1023对应的电压然后量一下VOUT。如果VOUT等于Vref的1023/1024倍说明SPI时序正确。如果不是就说明数据帧或时序有问题。8.3 输出有电压但数值偏高或偏低这是Vref不准最常见的外部延伸症状。用万用表测Vref实际值代入代码中重新计算即可。还有一种情况你用的是开发板的3.3V输出作为Vref而这个电压本来就有负载波动。当后级负载电流变化时3.3V电源的输出会漂移Vref也跟着飘导致输出电压不稳定。解决方案换用独立的基准源芯片给Vref供电或者在软件中加入周期性Vref采样进行动态校准。前者一劳永逸后者需要额外的ADC通道监控Vref。8.4 快速排查速查表症状可能原因检查方式无输出Vref/VDD缺失万用表测REFIN、VDD引脚电压无输出接线错误/虚接万用表蜂鸣档通断测试输出恒定不变SPI相位配置错误检查CPOL/CPHA或SPI_MODE输出错乱跳动字节序错误检查MSB/LSB设置数值偏高/偏低Vref不准实测Vref并代入代码数值随负载漂移Vref供电不稳独立基准源或动态校准9. 进阶用法从单通道到多通道的实践思考TLC5615是单通道DAC一片芯片只能输出一路模拟电压。但通过把多个TLC5615的DIN引脚串联成菊花链或者给每个芯片分配独立的CS引脚可以实现多通道输出。菊花链模式使用了DOUT引脚第一片的DOUT连接到第二片的DIN两片共享SCLK和CS。发送数据时16位数据在第一片内部移位多余的bit被推入第二片。多片级联时需要按相反的顺序发送数据帧——先送最后一个芯片的数据再送前面的。实际使用中如果只需要两路输出我更推荐用两个独立CS的方案每组SPI信号共享但CS分别控制。这样时序逻辑最直白不需要处理菊花链的帧序问题。如果通道数超过4路再考虑菊花链。多通道联动控制有个小技巧要实现以两片TLC5615同时输出为目标应当先将两片的数据都准备好再分别拉低CS、发送数据、拉高CS。这样可以最大限度地保证两路电压切换的时刻接近一致虽然不能严格同步但微秒级别的偏差在大多数模拟控制场景下已经足够。10. 关于TLC5615方案的最终体会这段时间我把TLC5615在51、Arduino、STM32三个平台上完整趟了一遍手里的模组也焊了三块不同版本的板子。一个简单的单通道DAC呈现出来的平台差异比预期丰富。51模拟SPI让我体会到时序基本功扎实的重要性——你手动制造每一位的时钟边沿建立时间、保持时间都掌握在自己手里而不再依赖库的封装。Arduino的三行代码让我意识到封装带来的便利和它掩盖的细节——传输16位数据时字节序是隐藏的坑。STM32的SPI外设则提醒我功能越丰富的硬件初始化配置的正确性越关键一个CPOL值与手册不匹配输出就会跑到天上去。TLC5615这颗芯片在这个价位段上真的没什么可挑剔的。SPI接口让并联和级联都很灵活10位分辨率虽然不如那些高精度DAC但用在绝大多数电压控制场景已经游刃有余。最后分享一个小的调校心得每当你拿到一块新的TLC5615模组上电后的第一件事不是跑代码而是先量Vref、再量VDD记录两个数值并贴在模组上。这样以后写任何平台的驱动代码时数字量计算直接用已记录的实测值输出电压的准确性从第一行代码开始就有保障。这套习惯我保持了快两年每次换板子都能快速进入状态少走很多弯路。