ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

PIC集成可编程逻辑外设:CLC/CWG/NCO实战解析

PIC集成可编程逻辑外设:CLC/CWG/NCO实战解析 Microchip最近扩展PIC MCU产品线新闻稿里把“集成可编程逻辑Integrated Programmable Logic”当成了核心卖点来推。圈内不少人看到这个词的第一反应是PIC要开始跟FPGA抢饭碗了其实不是这里说的“可编程逻辑”指的是CLC、CWG、NCO这些以前容易被当作普通外设忽略的模块。真正值得关注的是这类硬件逻辑外设现在开始大规模出现在PIC主流系列上覆盖面越来越广MCU内部的硬件层终于开始承担更多“逻辑处理”的职责。这个方向对做电源控制、电机驱动、工业仪表、传感器接口的工程师特别友好。以前要在外面用74系列逻辑门或者一颗CPLD才能实现的逻辑功能现在MCU内部几个寄存器就配完了成本低、面积小、响应还快。这篇文章我就从这几个模块到底是什么、跟传统方案比优势在哪、实际操作过程中怎么配置、有哪些容易踩的坑一层层拆开讲。1. 集成可编程逻辑到底包含哪几个核心模块1.1 CLC一颗芯片里的“迷你逻辑门阵列”CLC全称Configurable Logic Cell可配置逻辑单元。你可以把它理解成MCU内部的一颗“迷你逻辑门阵列”每个CLC单元都能独立配置成AND、OR、NAND、NOR、XOR等常见组合逻辑功能输入源可以是引脚也可以是其他外设的信号。一个CLC通常有4个输入通道每个输入通道都可以在多个候选源里选择一个数据手册里会有一张完整的输入源映射表。输出可以连接到引脚也可以接到CWG、定时器、中断控制器或者其他CLC模块。多个CLC还能串联一个CLC的输出作为下一个CLC的输入这样就能拼出更复杂的组合逻辑。我举一个实际场景。以前做过一个设备两个安全门禁开关必须同时闭合才允许输出电机使能信号。这个判断如果用软件做就是在中断里读两个引脚再判断。但客户明确要求这个判断必须在硬件层面完成不能依赖程序跑飞时还正常执行。当时是在板子上加了一片74HC08与门芯片后来换成带CLC的PIC直接配一个CLC为双输入AND逻辑两个门禁信号进输出接电机使能。整个逻辑没有任何CPU干预程序就算跑飞只要引脚状态不满足输出永远是关断的。CLC的工作是纯组合逻辑不消耗CPU周期也没有指令周期延迟。信号从输入端到输出端的传播时间取决于芯片内部走线通常在纳秒级这在很多实时性要求高的场景里非常关键。1.2 CWG与PSMC面向电源控制的专用逻辑CWG全称Complementary Waveform Generator互补波形发生器。这名字听起来很学术其实就是为了开关电源和电机驱动设计的PWM控制模块。它接收一路PWM源信号然后生成一对互补输出信号带上可配置的死区时间、极性控制还支持故障自动关断。为什么这个模块对电源设计这么重要因为用PIC或者任何MCU做半桥、全桥驱动时上下两个MOSFET的驱动信号必须是互补的而且两个信号之间要有一段死区时间防止直通导通炸管。如果用软件在定时器中断里手动处理死区会受到中断响应时间、编译器优化、中断嵌套等因素干扰波形时序很难做稳。CWG直接在硬件层把死区插进去只要时钟稳定死区时间就是精确的。有个细节值得注意CWG还支持一个“Shutdown”引脚或者输入源接上比较器、外部故障信号或者CLC组合逻辑的输出。故障发生时无论PWM源信号处于什么状态CWG的一组输出都会立刻进入安全电平这个过程完全由硬件完成不需要CPU响应。PSMCProgrammable Switch Mode Controller在部分PIC系列上功能更强支持多相PWM、更复杂的关断状态、电流限制输入等但设计思路和CWG基本同源。做电源的工程师看到这两个外设应该会会心一笑以前要外部控制器或者专门驱动芯片才能解决的问题现在MCU内部就带了一套。1.3 NCO与ZCD频率合成和过零检测的硬件帮手NCO全称Numerically Controlled Oscillator数控振荡器。它的作用是用一个参考时钟生成频率可精确设定的脉冲信号或者方波信号。原理上有点像DDS直接数字频率合成的简化版NCO内部有一个加法器和一个累加器每个时钟周期把频率控制字加到累加器里累加器溢出时输出一个脉冲。通过调整频率控制字可以得到非常高分辨率的输出频率。ZCD全称Zero Cross Detection过零检测。它专门用来检测交流信号或者引脚上电压波形的过零点对可控硅调光、交流电机相位控制这些应用来说几乎是必备功能。以前实现过零检测要么用外部比较器要么用定时器不停地采样引脚电压都不够干净。ZCD集成在MCU内部之后配置一个寄存器就能等着过零中断产生。这组外设放一起看Microchip的思路就很清楚了CLC是核心逻辑引擎CWG/PSMC负责功率驱动相关控制NCO做频率源ZCD处理相位同步。这几样东西组合起来MCU的硬件外围能力被大大增强而不仅仅是多几个定时器、多几个PWM通道那么简单。2. 三种方案对比软件处理、外部逻辑芯片、集成可编程逻辑2.1 纯软件处理的问题出在哪很多人第一反应是逻辑判断用软件写不就行了实现同样的功能肯定代码量更少、更灵活。这话没错但前提是你能接受软件处理的副作用。软件处理信号的主要问题有两个慢和不确定。慢是指一条指令执行要几十纳秒再加上中断响应、现场保存、判断分支、输出翻转一个完整流程跑下来通常要几微秒。不确定是指中断有优先级、有关闭状态、有嵌套同一个事件在不同时刻到达CPU响应时间可能完全不一样。在电机控制、开关电源这些应用里硬件信号的变化速度往往远快于CPU的响应速度。比如一个过流保护信号理想情况是信号一翻转PWM在几百纳秒内就关断。软件中断来做哪怕你用的是64MHz主频的MCU从中断到PIN翻转也至少需要几百纳秒到几微秒。这段时间里MOSFET可能已经处于过流状态多扛一个开关周期就可能导致器件结温超标。软件轮询的方式就更糟了。循环里查询一个引脚还需要考虑循环周期内其他任务的影响时序完全没有保证。所以做实时控制多年的工程师看到“纯软件处理”这几个字都会本能地摇头。2.2 和外部逻辑芯片/CPLD方案对比既然软件不行那就上硬件。传统的硬件方案有两种小规模集成逻辑芯片74系列等和CPLD/FPGA。它们都能做到极快的响应速度和确定的时序但各有各的代价。74系列逻辑门的问题是不灵活。一片74HC08只能做与门功能固定想改逻辑只能改板子换芯片。而CPLD/FPGA虽然灵活但开发链路重得多要学HDL语言、要额外烧录器、要考虑启动配置、电源时序对很多MCU嵌入式项目来说属于过度设计。集成可编程逻辑正好落在中间地带的甜蜜点上它像逻辑芯片一样结构简单、响应快但又像CPLD一样可以软件重配置。关键它不需要额外的开发工具和编程流程使用MCU现有的编译调试链路就能完成配置和修改。2.3 一个案例看懂为什么需要硬件域保护用一个我实际做过的逆变器母线过流保护案例来说明。系统里有一个比较器当母线电流超过阈值时比较器输出从低变高。这个信号需要立刻关断PWM输出同时通知CPU记录故障。软件方案比较器输出翻转触发MCU中断中断服务程序里读比较器状态然后手动关PWM输出通道。从比较器翻转到PWM停止实测最快约11微秒这还是在中断里什么都没干的情况下。11微秒在开关电源领域是一个相当长的时间对一个高频工作的MOSFET来说足以让它进入危险区。外部逻辑方案比较器输出接一个与门PWM信号也接入与门比较器翻转时与门输出直接拉低PWM立即停止。这方案响应速度可以达到纳秒级但增加了一颗芯片和布线面积同时逻辑固化后期想改阈值动作或者增加联动逻辑只能重新画板。集成可编程逻辑方案比较器输出接CLCCLC输出接CWG的Shutdown输入CWG驱动的PWM在一两个内部时钟周期内关断速度接近外部逻辑芯片方案但完全不需要额外芯片。同时还可以配一个CLC中断通知CPU保存故障现场。整个保护链路全在MCU内部硬件上不需要改动逻辑还能随时用寄存器重新配置。这才是集成可编程逻辑真正的价值点把实时性要求高的安全链路留在硬件域把需要灵活配置和通知处理的功能交给CPU两边各干各的活。3. 实操指南用MCC五分钟跑通一个CLC逻辑3.1 准备清单工具、芯片和最小硬件要实际动手体验你需要准备几样东西。首先是MPLAB X IDEMicrochip官方免费IDE官网下载即可。然后是MCC插件新版叫MCC Melody在IDE的Tools菜单里可以直接安装。注意MCC和MCC Melody的界面布局有一些差异但配置CLC、CWG这类外设的核心流程是一致的。芯片选择上推荐从带CLC的PIC18 Q系列或者PIC16F13145系列入手。PIC18F26Q10、PIC18F47Q10都是经典选择型号后缀里的Q表示带可配置逻辑类外设资料齐全网上能找到不少参考设计。开发板如果有官方Curiosity系列最好没有的话自己焊一个最小系统也不难。硬件调试需要一台示波器或者逻辑分析仪。别省这一步CLC配置完成后到底发生了什么必须用波形来验证。我个人的做法是先用逻辑分析仪看时序确认逻辑关系正确后再用示波器看模拟域的信号质量。3.2 需求拆解双路门禁信号AND逻辑前面提到的门禁互锁例子很适合作为第一个实践项目。需求再明确一下两路门禁信号默认高电平门闭合时拉低。两个都闭合时输出使能为高否则输出为低。这个逻辑非常直观输入是两路低有效信号输出要在两个输入都为低的时候为高。用正逻辑描述就是输入A取反输入B取反两者相与。如果CLC输入本身支持反相配置直接在每个输入端选择“反向极性”然后逻辑函数选AND输出就是目标结果。相当于一个两输入与非门。3.3 MCC配置步骤从零到生成代码第一个坑在引脚选择。先看数据手册里的CLC输入源映射表不是所有引脚都能直连CLC。比如PIC18F26Q10上CLC1的输入0可能只能连接RA0、RB0等若干固定引脚。开头如果选错了引脚后面MCC里会发现输入源选项是灰色的。在MCC里新建一个CLC1模块后配置要点如下逻辑函数Logic Function下拉菜单里选择AND。每个CLC可以配成单输入、双输入、三输入或者四输入的不同逻辑表达式。如果选四输入MCC会显示四个输入通道供配置。输入源和极性。把Input Source分别设为需要的引脚如果信号是高有效极性保持正常如果是低有效选择反相。MCC界面上对应的选项通常是“Inverted”反向。输出连接。CLC1输出可以给到引脚也可以给内部外设。把输出引脚分配给一个空闲IO口即可比如RC2。仔细检查引脚管理器。在MCC的Pin Manager界面里确认配置为输入的两个引脚没有启用模拟复用功能。这一步容易漏后面启动代码会讲到为什么它这么关键。时钟配置。建议先把系统时钟配置好比如选内部振荡器8MHz。时钟会影响CWG死区时间和NCO频率的计算第一次练习固定下来更有利于验证。全部配置完成后点击Generate生成代码。MCC会把所有配置写入mcc_generated_files目录下的clc.c、pin_manager.c等文件中。3.4 生成代码解读寄存器层面发生了什么很多新手拿到MCC生成的代码直接烧进去能跑就完事。我不建议这样至少要能看懂变化的核心寄存器否则调试时完全无从下手。MCC生成代码里CLC1_Initialize()这个函数会写入几个关键寄存器。CLCxSEL0和CLCxSEL1负责选择四个输入通道对应的信号源每4位表示一个通道的源编号。CLCxCON负责选择逻辑函数模式、输出极性和使能位。如果启用了反相输入还要看CLCxPOL寄存器。以概念性示意代码为例看起来是这样void CLC1_Initialize(void) { // 选择输入源通道0接RA0通道1接RA1 CLC1SEL0 0x00; // 具体值需查数据手册输入源映射表 CLC1SEL1 0x01; // 配置为AND逻辑输出非反相使能CLC1 CLC1CON 0x03; // 通道0输入反向通道1输入反向输入低有效 CLC1POL 0x03; // 使能CLC1 CLC1CONbits.LCEN 1; }注意这里的数值只是示意图不同芯片的输入源编号不同务必以型号对应的数据手册为准。理解这个代码的含义比记住数值更重要它是把你想要的可编程逻辑翻译成了寄存器配置。主函数里只需要正常初始化然后就可以读CLC输出引脚的电平或者CLC模块的输出状态来判断门禁是否都闭合了。void main(void) { SYSTEM_Initialize(); while (1) { if (CLC1_IsOutputHigh()) { systemState.motorEnabled 1; } else { systemState.motorEnabled 0; } } }CPU只需要关心结果判断过程在硬件层面已经完成了。3.5 CWG配置示例带死区的互补PWMCLC跑通之后建议接着试一下CWG因为CWG能给你最直观的示波器波形反馈尤其是死区插入这个功能。配置思路是这样先把一个PWM定时器模块配置好输出基础PWM信号。然后在MCC里添加CWG1信号源选PWM模块的输出使能CWGA和CWGB两路互补输出设置死区时间。死区时间怎么算以系统时钟8MHz为例一个时钟周期是125ns。如果设置4个周期的死区就是500ns。MCC里如果可以直接填写时间值它会在背后自动换算成寄存器周期数如果只能填寄存器周期数就需要自己算死区时间除以时钟周期四舍五入取整。生成代码后用示波器接CWGA和CWGB两个引脚能看到两个波形是互补的中间有一段两边都为低的时间这就是死区。改变死区数值重新生成烧录可以观察到这段低电平时间随之变化。亲自做一遍对理解CWG工作机制特别有帮助。4. 实战进阶CLC、CWG、NCO组合的三种玩法4.1 玩法一CLCNCO组合生成可调频率方波NCO单独用可以生成一个精确频率的方波但如果你想在某个特定时间段才让这个方波输出或者想做一个门控信号单靠NCO不够灵活。NCO的输出接到CLC的输入端CLC的另一个输入端接一个使能信号把CLC配置为AND逻辑就能实现“使能有效时才输出方波”的效果。一个具体应用是模拟信号发生器里的频率键控。你可以在CPU里动态修改NCO的频率控制字同时用另一个引脚或者定时器信号通过CLC控制输出门控。频率切换和门控切换都在硬件里完成切换时刻的抖动远小于软件完全控制IO翻转的情况。NCO输出频率的计算公式是Fout Fclk × INC / 2^NN是累加器位宽。以20位NCO、时钟8MHz为例想得到1kHz方波INC 1000 × 2^20 / 8000000 ≈ 131。这个计算方式跟DDS基本一致记住这个公式很多场景都用得上。4.2 玩法二ZCDCWG把交流过零同步做实做可控硅调光或者交流固态继电器控制时过零检测和触发脉冲是两个核心环节。以前需要外部过零检测电路加定时器产生触发脉冲用PIC的ZCD和CWG可以省掉不少外围芯片。ZCD模块检测到交流电压过零后会产生中断CPU在中断里根据需要的触发角计算延迟时间启动一个定时器。定时器溢出后通过CWG产生一个窄脉冲作为可控硅的触发信号。ZCD负责“什么时候开始计时”CWG负责“触发脉冲长什么样”CPU只负责中间的延迟计算整个链路的实时性比纯软件实现要稳得多。实际做这个项目时有一个高频噪声问题值得注意交流波形的过零点附近往往不是干净的单次跳变而是一串毛刺ZCD可能产生多次误中断。部分PIC的ZCD模块内部有消隐窗口配置开启后可以过滤掉过零点附近的窄脉冲配置时留意这个选项。做任何与市电直接相关的调试务必使用隔离变压器或者隔离探头这是安全底线不能省。4.3 玩法三多个CLC级联做复杂组合逻辑单个CLC只能实现纯粹的组合逻辑函数虽然灵活但复杂度有限。好在多个CLC可以级联最后一个CLC的输入可以取前面CLC的输出这在MCC里是一个可选项。举个例子。需要实现“只有当A和B不同、且C为高时输出有效”可以用两级逻辑第一个CLC配成双输入异或门输入取A和B输出为D第二个CLC配成双输入与门输入分别取D和C输出到引脚。这样两个CLC就完成了一个三输入组合逻辑。级联时有一个经验注意每个CLC的输入源选择矩阵里是否能直接访问上一个CLC的输出。在设计阶段先翻一翻数据手册的外设互连表否则配置过程中可能发现某些CLC之间的互联通道不存在不得不调整逻辑方案或者换其他CLC编号。多层CLC级联的传播延迟会增加但在大多数低速控制场景下纳秒级的延迟增长完全不是问题。只有在GHz级别的高速数据通路或者雷达信号处理这类应用中才需要关注而这种场景本身也不会选一颗PIC来做。5. 踩坑实录五个常见问题与排查方法5.1 输入引脚不听话多半是模拟功能没关这是我在帮朋友调试项目时遇到最多的问题。CLC配置看起来完全正确输入引脚用万用表量有电平变化可CLC输出就是不动。翻代码后发现引脚初始化的时候ANSEL寄存器对应位还是1引脚被配置为模拟输入模式。在模拟模式下引脚的施密特触发数字缓冲器是断开的数字逻辑根本读不到引脚电平。MCC生成代码时通常会在Pin Manager里根据配置自动设置ANSEL但如果你直接在代码里改过寄存器或者手动添加了外设很容易漏掉这一项。排查方法是把CLC输入引脚对应的ANSEL位清零同时确保TRIS方向位为输入。如果不确定把两个相关寄存器都打印或者仿真器里看一遍几秒钟就能定位问题。5.2 中断反复进入或进不去查一下PEIE和中断标志位PIC16和PIC18系列的中断使能机制跟ARM Cortex系列有些不同。全局中断GIE是一个总开关外设中断还有一个PEIE位。在PIC16中PEIE位于INTCON寄存器里必须置1CLC、定时器、UART等一系列外设的中断才能上报给CPU。很多从ARM切过来的开发者配置了外设中断源也开了全局中断唯独忘了PEIE结果中断完全不触发。还有一种情况是中断标志位没有及时清除。比如CLC输出边沿触发了一个中断中断服务程序里没有清零PIR标志位CPU会立刻再次进入中断看起来就是“中断反复触发”。写中断服务程序时第一步先清标志位再处理业务逻辑养成这个习惯能省去很多莫名的调试时间。5.3 死区时间算不准先确认时钟配置死区时间的精度直接依赖系统时钟。CWG死区寄存器里保存的是一个时钟周期计数值如果你以为系统时钟是16MHz实际却被配置成了8MHz计算出来的死区时间会整整扩大一倍。MCC生成的代码会在系统初始化时配置振荡器但在调试过程中我建议先用示波器实测一下PWM引脚输出频率反推实际系统时钟是多少确认无误后再去核对死区值。不要理所当然地认为IDE里选的时钟一定生效如果芯片时钟切换位配置有误实际频率可能跟预期完全不一致。5.4 外设互连有坑CLC输入源不是万能路由每次写外设互连的选路时都要强调看数据手册的矩阵表。CLC的每一个输入端都有一个多路选择器这个MUX不是所有信号都能连通常只有有限的十几个来源。很多新手在MCC里发现想选的外部信号不在下拉列表里就开始怀疑工具坏了。应对办法是提前设计。决定用CLC做某个逻辑前先翻数据手册里的“CLCx Input Selection”表格确认需要的信号能进入指定的CLC通道。如果不行换一个引脚或者换一组CLC单元试试。部分特殊功能可以先用其他外设中转一下比如信号先进CWGCWG的输出再接CLC虽然多一级延迟但功能通常能拼出来。5.5 低功耗模式下逻辑外设到底还跑不跑如果你做的是电池供电设备需要在睡眠状态下保持某个逻辑判断持续有效这块要特别留意。很多PIC在进入SLEEP模式后主时钟会停掉依赖CPU主时钟的外设也会停止工作。但有一部分外设可以配置为使用独立时钟源在睡眠模式下继续运行。具体到CLC它的行为取决于输入端信号来源于哪个时钟域以及芯片自身的功耗管理设计。数据手册的低功耗章节会有“运行在睡眠模式下的外设”列表里面有明确说明。我在一个低功耗门禁项目里就踩过这个坑设备睡眠后门禁状态检测应该继续工作结果CLC输出一直保持睡眠前的电平后来查手册才发现需要把CLC的时钟源切换为LFINTOSC低速内部振荡器才能在睡眠模式下保持运行。配置这类功能时务必测试三种状态全速运行、睡眠、唤醒后恢复。每一个阶段都验证过信号路径才能放心交到生产环境。回到开头说的Microchip这次把集成可编程逻辑放到PIC产品线的宣传核心其实是在告诉嵌入式开发者MCU和逻辑芯片之间的边界越来越模糊了。CLC、CWG、NCO、ZCD这些模块组合起来已经能在芯片内部完成相当一部分过去必须由外部逻辑器件实现的活。我自己的体会是刚接触这些外设时容易低估它们的作用觉得“不过是多了几个寄存器功能”但真正在一个实时性要求高的项目里把它们用起来才发现硬件逻辑带来的稳定性和省心程度是纯软件方案很难追上的。最后再分享一个小技巧不要急着上手就配复杂逻辑先从最小的AND门跑通一个完整闭环拿示波器确认波形没有问题再逐步加CWG、NCO这些模块。你踩完一轮坑之后会发现这套“可编程硬件逻辑”的思路值得放进你的常规选型工具箱里。
返回列表