公司动态
Tiva™ C系列外设管理:PP与SR寄存器实战指南
1. 从寄存器手册到实战Tiva™ C系列外设管理的核心逻辑如果你和我一样长期泡在嵌入式开发的一线特别是基于ARM Cortex-M内核的MCU那你肯定对“外设管理”这四个字深有感触。它远不止是初始化几个时钟、配置几个引脚那么简单。一个健壮、可靠且易于维护的嵌入式系统其基石往往在于对外设状态的精准感知和对其生命周期的有效控制。今天我们就以德州仪器TI的Tiva™ TM4C1292NCZAD这款高性能微控制器为例深入聊聊它的“外设存在寄存器Peripheral Present”和“软件复位寄存器Software Reset”这两大家族。别被这些看似枯燥的寄存器地址和位域吓到它们实际上是你在进行系统设计、故障诊断和代码移植时手中最锋利的“手术刀”。为什么说它们重要想象一下你手头有一个项目前期用的是TM4C1292NCZAD它集成了丰富的以太网、USB和CAN外设。后来因为成本或功能调整需要换到同一系列但外设裁剪过的型号。如果你的代码里写死了“一定有USB”或“一定有2个CAN”那么移植过程将是一场灾难。反之如果代码在初始化前先通过查询PPUSB、PPCAN这类寄存器来动态判断硬件能力那么你的代码将具备出色的可移植性和健壮性。再比如某个GPIO端口因为外部干扰或软件bug进入了异常锁定状态常规操作无法恢复这时通过SRGPIO寄存器对其进行一次“定点清除”式的软件复位往往比重启整个芯片更优雅、更高效。这就是我们今天要拆解的核心如何利用芯片提供的这些“元信息”和“控制开关”写出更专业、更可靠的嵌入式固件。2. 系统控制模块芯片的“户籍管理处”与“急救中心”在深入每个寄存器之前我们得先搞清楚它们住在哪里以及这个“社区”的规则。在Tiva™ C系列微控制器中所有系统级别的控制和状态信息都归一个叫做“系统控制System Control”的模块管理。你可以把它理解为芯片内部的“户籍管理处”兼“急救中心”。这个模块有一个固定的“办公地址”0x400F.E000。我们讨论的所有PPxxx和SRxxx寄存器都坐落在这个基地址之上通过一个唯一的偏移量Offset来访问。例如USB外设存在寄存器PPUSB的偏移量是0x328那么它的完整地址就是0x400F.E000 0x328 0x400F.E328。这种设计非常规整方便我们用宏定义或结构体来映射。这些寄存器主要分为两大类它们的职责截然不同外设存在寄存器PP - Peripheral Present只读RO。它们是“户籍管理处”只负责记录信息不参与控制。上电复位后硬件会根据芯片的具体型号和配置自动写好这些寄存器的值。你的软件只能去“查户口”看看这个芯片“有没有USB模块”、“有几个ADC”。这为编写可移植的通用驱动库提供了硬件基础。软件复位寄存器SR - Software Reset读写RW。它们是“急救中心”的复位按钮。当某个外设如GPIO、DMA、定时器行为异常、卡死或者你需要将其恢复到一个绝对干净的初始状态时就可以通过操作对应的SR寄存器位对该外设实施一次“局部重启”而无需惊动CPU核心和其他正在正常工作的模块。这里有一个至关重要的编程习惯需要养成对于所有标记为“保留reserved”的位域必须进行“读-修改-写”操作时予以保留。手册中明确警告“Software should not rely on the value of a reserved bit.” 这意味着你不能假设这些位是0或1。正确的做法是先读取整个寄存器的值只修改你需要操作的那些位然后再写回去。这是为了兼容未来可能推出的新型号芯片这些保留位在未来可能会被赋予新的含义。如果你粗暴地直接写入一个值可能会在未来芯片上导致不可预知的行为。注意在操作SR系列寄存器时尤其要注意时序。手册中提到“There may be latency from the clearing of the SR bit to when the peripheral is ready for use.” 这意味着你清除复位位后需要等待几个时钟周期让外设内部逻辑稳定。更稳妥的做法是在清除复位位后去查询对应的“外设就绪Peripheral Ready”寄存器如果存在或者简单地插入一个短暂的延时如几个空操作指令__nop()再对该外设进行配置。3. 外设存在寄存器详解你的芯片“技能清单”外设存在寄存器是一组只读寄存器它们像一张清晰的“技能清单”如实反映了你手中这片TM4C1292NCZAD到底内置了哪些硬件资源。我们挑几个关键且常用的来详细解读。3.1 通信接口类外设查询PPUSB (0x328) - USB模块存在寄存器这个寄存器只有最低位Bit 0P0是有效的。复位后TM4C1292NCZAD的该位值为1表明芯片内部集成了USB控制器模块。这对于需要实现USB设备如自定义HID设备、CDC虚拟串口或USB主机功能的项目是前提条件。在软件初始化USB栈之前先判断此位是良好的习惯。PPCAN (0x334) - CAN控制器存在寄存器这个寄存器更有意思。它的Bit 0和Bit 1分别代表CAN模块0和CAN模块1。TM4C1292NCZAD的复位值是0x3二进制...0011这意味着它集成了两个独立的CAN控制器。这对于汽车或工业网络应用非常有用你可以用一个CAN通道连接动力系统另一个连接诊断或车身网络。如果你的代码设计为使用CAN1但在一个只有CAN0的简化型号上运行查询此寄存器就能提前规避运行时错误。PPEMAC (0x39C) - 以太网MAC存在寄存器Bit 0为1确认了TM4C1292NCZAD集成以太网MAC控制器。这是它区别于许多低端Cortex-M芯片的重要特征使其能够直接接入网络。但请注意这仅代表MAC层控制器存在物理层PHY是另一个模块由PPEPHY (0x330)寄存器指示。TM4C1292NCZAD的PPEPHY复位值为0意味着它不包含集成的以太网PHY。你需要外接一片PHY芯片如DP83848、LAN8720等并通过RMII或MII接口连接。这一点在硬件设计初期就必须明确。3.2 模拟与数据采集类外设查询PPADC (0x338) - ADC模块存在寄存器Bit 0和Bit 1分别对应ADC模块0和模块1。复位值0x3表明芯片有两个ADC模块。每个ADC模块通常可以配置多个采样序列和输入通道。查询此寄存器可以动态决定启用哪些ADC资源或者实现负载均衡。PPACMP (0x33C) - 模拟比较器存在寄存器Bit 0为1表示存在模拟比较器模块。手册还特别提示注意Analog Comparator Peripheral Properties (ACMPPP)寄存器会指示该模块内包含多少个比较器单元。这是一个很好的例子说明了“存在”和“能力”是两回事。PPACMP告诉你“有比较器”而ACMPPP则告诉你“有几个比较器各有什么特性”。完整的驱动需要查询这两类信息。3.3 存储与定时类外设查询PPEEPROM (0x358) - EEPROM存在寄存器Bit 0为1表示芯片集成了EEPROM。这对于需要存储少量掉电保存数据如校准参数、设备序列号、运行日志的应用非常方便无需外挂存储芯片。PPWTIMER (0x35C) - 宽位定时器存在寄存器Bit 0为1表示存在32/64位宽定时器模块0。有趣的是在TM4C1292NCZAD上此位复位值为0。这意味着这款芯片可能不包含宽位定时器或者该功能在特定封装/型号中被禁用。这是一个关键信息如果你计划使用宽位定时器来实现长时间精确计时必须在代码中检查此位否则就要准备备用方案如用多个32位定时器级联。PPPWM (0x340) 和 PPQEI (0x344)Bit 0分别指示PWM模块0和QEI正交编码器接口模块0的存在。它们在电机控制、位置检测等场景中是核心外设。3.4 其他专用外设查询PPCCM (0x374) - CRC模块存在寄存器Bit 0为1表示存在硬件CRC计算单元。在通信协议校验或数据完整性检查时使用硬件CRC比软件计算要快几个数量级且不占用CPU资源。PPLCD (0x390), PPPECI (0x350), PPFAN (0x354) 等这些寄存器指示了LCD控制器、PECI平台环境控制接口常用于CPU温度管理、风扇控制等更专用外设的存在性。在TM4C1292NCZAD上它们的复位值多为0意味着这些功能可能未被集成。这清晰地划定了芯片的能力边界。实操心得如何高效利用PP寄存器我通常会在系统初始化早期用一个结构体或数组一次性读取所有关心的PP寄存器值并保存起来。例如typedef struct { uint32_t usb; uint32_t can; uint32_t adc; uint32_t mac; uint32_t phy; // ... 其他 } PeripheralPresentMap_t; PeripheralPresentMap_t g_PeriphPresent; void System_PeriphPresentScan(void) { g_PeriphPresent.usb HWREG(SYSCTL_PPUSB); g_PeriphPresent.can HWREG(SYSCTL_PPCAN); g_PeriphPresent.adc HWREG(SYSCTL_PPADC); g_PeriphPresent.mac HWREG(SYSCTL_PPEMAC); g_PeriphPresent.phy HWREG(SYSCTL_PPEPHY); // ... }这样在后续的驱动初始化函数中我就可以通过查询g_PeriphPresent这个全局状态图而不是反复访问寄存器来做出决策。这不仅提高了效率也使代码逻辑更清晰。例如初始化网络时可以这样写void Ethernet_Init(void) { if ((g_PeriphPresent.mac 0x01) 0) { // 没有以太网MAC记录错误或进入备用模式 Log_Error(No Ethernet MAC present!); return; } if ((g_PeriphPresent.phy 0x01) 0) { // 没有内部PHY需要配置外部PHY的GPIO和复位引脚 External_PHY_Init(); } // 继续初始化MAC... }4. 软件复位寄存器实战精准的“外科手术”当外设出现“卡死”或状态异常时系统复位拉低NRST引脚是终极手段但杀伤范围太大会影响整个系统。软件复位寄存器则提供了对单个外设进行“精准手术”的能力。其操作遵循一个标准的两步流程我们以SRGPIO (0x508)为例详细拆解。4.1 软件复位标准流程解析手册对SR寄存器的操作描述非常清晰分为两步置位复位位软件将SR寄存器中对应外设的位写1。此时该外设被强制置于复位状态其内部所有寄存器恢复为复位默认值任何正在进行的事务被中止。清除复位位软件将同一位写0。复位信号释放外设开始从复位状态恢复。这个过程看似简单但有几个极易踩坑的细节延迟Latency手册明确警告从清除复位位到外设真正准备好被访问可能存在延迟。这是因为外设内部的时钟树、逻辑电路需要时间稳定。绝对不能在清除复位位后立即对其进行配置。就绪状态查询最可靠的做法是在清除复位位后去查询对应的“外设就绪PR - Peripheral Ready”寄存器如果存在。例如对GPIO端口A复位后应查询PRGPIO寄存器的Bit 0直到该位变为1表明GPIO端口A的寄存器阵列已可访问。无就绪寄存器时的策略并非所有外设都有对应的PR寄存器。此时通用的做法是插入一个保守的延时。这个延时可以通过循环执行一定数量的空操作指令__nop()或基于系统时钟的简单延时函数来实现。通常几个到几十个时钟周期就足够了。4.2 GPIO软件复位深度操作指南SRGPIO寄存器是一个控制力非常精细的寄存器它的每一位独立控制一个GPIO端口Port A到Port T取决于具体型号。TM4C1292NCZAD拥有多达18个GPIO端口A-T该寄存器的Bit 0到Bit 17分别对应Port A到Port R注意并非所有型号都包含全部端口需查数据手册。为什么需要对GPIO进行软件复位常见场景包括引脚配置锁死在配置GPIO复用功能AFSEL、数字使能DEN或上下拉PUR/PDR时如果遇到异常中断或竞争条件可能导致引脚控制寄存器处于不可更改的状态。中断标志卡死GPIO中断标志在RIS寄存器中有时在异常情况下无法通过写ICR寄存器清除。恢复默认状态在动态切换引脚功能比如从UART切换到GPIO输入时一个干净的复位可以确保所有相关寄存器DATA,DIR,AFSEL,PCTL,DEN,PUR/PDR,DR2R/DR4R/DR8R,SLR等都回到上电默认值避免残留配置干扰新功能。一个健壮的GPIO端口软件复位函数实现如下/** * brief 对指定GPIO端口进行软件复位 * param portIndex: GPIO端口索引 (0 for PA, 1 for PB, ... 17 for PR) * retval 0: 成功, -1: 失败端口不存在或复位后未就绪 */ int GPIO_PeripheralReset(uint8_t portIndex) { uint32_t srMask; uint32_t prMask; // 1. 参数检查确保端口索引有效TM4C1292最大支持到Port R if (portIndex 17) { return -1; // 无效端口 } // 2. 构造位掩码 srMask (1UL portIndex); // SRGPIO 的对应位 prMask (1UL portIndex); // PRGPIO 的对应位 // 3. 第一步置位复位位将外设置于复位状态 HWREG(SYSCTL_SRGPIO) | srMask; // 4. 短暂延时确保复位信号生效可选但建议有 __asm volatile (nop); __asm volatile (nop); // 5. 第二步清除复位位释放复位 HWREG(SYSCTL_SRGPIO) ~srMask; // 6. 等待外设就绪轮询 PRGPIO 寄存器 // PRGPIO 的对应位为1时表示该GPIO模块寄存器可访问 uint32_t timeout 1000; // 超时计数器防止死等 while ((HWREG(SYSCTL_PRGBPIO) prMask) 0) { if (--timeout 0) { // 超时复位可能失败 return -1; } } // 7. 复位成功后建议再插入少量延时让端口逻辑完全稳定 for (volatile int i 0; i 10; i) { __asm volatile (nop); } return 0; // 成功 }使用示例复位整个Port Fif (GPIO_PeripheralReset(5) 0) { // Port F 的索引是5 // 复位成功现在可以安全地重新配置PF0-PF7 GPIOPinTypeUART(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_1); // 将PF0, PF1配置为UART } else { // 复位失败需要记录错误或采取降级措施 Log_Error(GPIO Port F reset failed!); }重要提示在进行GPIO软件复位时该端口上所有引脚的功能将暂时失效。如果这个端口正控制着关键的外设如电机驱动、通信总线复位操作会导致通信中断或设备失控。因此务必在系统安全的状态下如设备待机、所有相关事务已停止执行此操作并评估其对系统整功能的影响。4.3 其他关键软件复位寄存器SRTIMER (0x504) - 定时器软件复位这是一个多位的寄存器Bit 0到Bit 7分别控制定时器模块0到7。你可以单独复位任何一个定时器而不影响其他定时器的运行。这在某个定时器因比较器/捕获器配置错误而卡住时非常有用。复位后定时器的计数器、匹配寄存器、控制寄存器等全部归零。SRWD (0x500) - 看门狗定时器软件复位看门狗本身是系统的“守护者”但有时也需要复位它例如在极低功耗模式下需要彻底关闭看门狗以省电退出时再重新初始化。操作SRWD寄存器可以复位看门狗模块。注意复位看门狗后必须按照正确的序列重新配置它否则可能立即触发复位。SRDMA (0x50C) - μDMA软件复位直接内存访问控制器是高性能数据搬运的核心。如果DMA通道描述符链混乱或传输引擎挂起可能导致数据丢失或系统停滞。通过SRDMA复位整个μDMA模块可以将其恢复到初始状态。警告复位前必须确保没有任何活跃的DMA传输否则会导致数据不完整。SREPI (0x510) - EPI接口软件复位外部并行接口用于连接高速外设如SRAM、LCD、FPGA。如果EPI总线出现时序冲突或FIFO溢出复位EPI模块是有效的恢复手段。SRHIB (0x514) - 休眠模块软件复位休眠模块负责极低功耗状态的管理和RTC。通常不建议在运行时复位它除非其配置完全混乱。复位会清除休眠模块的配置和可能存在的唤醒状态。实操避坑指南软件复位的副作用与顺序寄存器配置丢失软件复位会将被复位外设的所有寄存器恢复为复位默认值。这意味着你之前对该外设的所有配置时钟使能、中断设置、工作模式等都会丢失。复位操作后必须重新完整地初始化该外设。中断状态清除复位会清除所有挂起的中断标志并禁用该外设的中断。如果你的系统依赖该外设的中断复位后需要重新配置NVIC和中断使能。依赖关系某些外设间存在依赖。例如UART外设依赖于某个GPIO端口进行引脚复用。如果你复位了该GPIO端口UART的物理链路就断了。因此复位外设时要考虑其对上下游模块的影响。操作顺序在复位一个复合外设系统时例如复位以太网MAC前应先停止DMA传输和PHY建议遵循“先停止活动再复位先复位从属模块再复位主控模块”的原则。5. 综合应用构建一个健壮的系统初始化与恢复框架理解了PP和SR寄存器的原理后我们可以将它们组合起来构建一个更健壮的系统初始化和故障恢复框架。5.1 动态外设探测与初始化一个优秀的BSP板级支持包或HAL硬件抽象层不应该假设芯片的具体配置。利用PP寄存器我们可以实现动态探测和初始化。void System_PeripheralInitAll(void) { // 1. 扫描外设存在性 System_PeriphPresentScan(); // 调用前面定义的扫描函数 // 2. 根据存在性有条件地初始化 // 初始化系统时钟和内核外设这些通常总是存在 SystemClock_Config(); NVIC_Configuration(); // 3. 初始化GPIO假设所有GPIO端口都存在但实际也应查询PPGPIO // 注意TM4C的GPIO存在性通常由型号固定手册可能未提供PPGPIO寄存器。 // 更安全的做法是即使操作不存在的端口也不会导致硬件错误但代码会访问不存在的寄存器地址。 // 因此对于GPIO更依赖数据手册的型号信息。 // 4. 初始化通信接口 if (g_PeriphPresent.usb 0x01) { USB_Init(); } if (g_PeriphPresent.can 0x03) { // 检查是否有任意CAN模块 CAN_Init(0); // 初始化CAN0 if (g_PeriphPresent.can 0x02) { CAN_Init(1); // 如果CAN1存在也初始化 } } if ((g_PeriphPresent.mac 0x01) (g_PeriphPresent.phy 0x01)) { // 有MAC和内部PHY Ethernet_Init_InternalPHY(); } else if (g_PeriphPresent.mac 0x01) { // 只有MAC需外部PHY Ethernet_Init_ExternalPHY(); } // 5. 初始化模拟外设 if (g_PeriphPresent.adc 0x03) { ADC_InitAll(); } if (g_PeriphPresent.acmp 0x01) { ACMP_Init(); // 可以进一步查询ACMPPP寄存器获取比较器数量 } // 6. 初始化定时器、PWM等 // ... 类似逻辑 }5.2 外设故障诊断与恢复策略当某个外设功能异常时可以设计一个分层的恢复策略软复位外设首先尝试使用对应的SR寄存器复位该外设然后重新初始化。这能解决大部分由软件状态机错乱引起的故障。int UART_Recover(UART_Module_t uartNum) { // 假设UART0对应某个GPIO端口和UART模块这里简化处理 // 1. 停止当前UART操作禁用中断停止DMA UART_Disable(uartNum); // 2. 复位相关的GPIO端口如果UART引脚可重映射需根据实际情况选择端口 GPIO_PeripheralReset(GPIO_PORT_A); // 假设UART0 RX/TX在PA0, PA1 // 3. 复位UART模块本身TM4C的UART软件复位寄存器可能是SRUART需查手册 // HWREG(SYSCTL_SRUART) | (1 uartNum); // 短暂延时 // HWREG(SYSCTL_SRUART) ~(1 uartNum); // 等待PRUART就绪... // 4. 重新初始化GPIO和UART GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); UART_Init(uartNum, 115200); // 5. 重新使能中断/DMA UART_Enable(uartNum); return 0; }检查时钟与电源如果软复位无效检查该外设的时钟是否使能通过RCGCx、SCGCx、DCGCx寄存器以及其所在电源域是否正常。硬件检查如果软件层面均无效则可能是硬件问题如引脚损坏、外部器件故障等需要记录错误并进入安全模式或报警。5.3 调试技巧利用寄存器状态定位问题在调试复杂的外设问题时PP和SR寄存器也能提供线索。确认芯片型号与预期是否一致通过读取一系列PP寄存器可以生成一个芯片的“特征签名”与数据手册对比可以验证焊接的芯片型号是否正确或者检查芯片是否处于某种测试或限制模式。验证复位操作是否执行当你写入SR寄存器后可以立即回读该寄存器确认位值是否已被正确设置。在某些极端情况下如总线错误、写保护写操作可能未生效。配合就绪寄存器诊断在操作SR寄存器后持续轮询对应的PR外设就绪寄存器。如果长时间未就绪可能意味着该外设的时钟域有问题或者存在更深的硬件故障。6. 常见问题与排查实录在实际项目中围绕这些寄存器操作我踩过不少坑也总结了一些经验。问题1读取PP寄存器总是返回0是不是芯片坏了排查思路地址是否正确首先确认你访问的寄存器地址是否正确。基地址0x400F.E000加上偏移量。时钟是否使能访问系统控制模块本身可能需要系统时钟。但通常上电后系统控制模块的时钟是默认开启的。不过为了保险起见可以检查RCGC0寄存器中对应系统控制模块的位如果存在。总线访问权限在复杂的系统中如使用了MPU或处于非特权模式确保CPU对系统控制模块的地址空间有读取权限。芯片型号确认你手中的片型号确实支持你所查询的外设。TM4C1292NCZAD是高端型号功能齐全。但如果你用的是TM4C123系列很多外设如以太网、USB是不存在的PP寄存器读回0是正常的。问题2对某个外设执行软件复位后系统其他部分出现异常。可能原因与解决资源冲突你复位的外设可能正在被其他模块使用。例如你复位了一个正在被DMA使用的GPIO端口或者复位了一个正在提供时钟源的定时器。解决在复位前确保目标外设已停止所有活动禁用中断、停止DMA、关闭定时器等。依赖中断的服务挂起该外设可能正在服务一个系统关键的中断。复位会清除中断使能和标志导致该中断服务丢失。解决在复位前在合适的位置保存关键状态或确保系统能容忍该服务暂时中断。共享资源被重置有些外设共享内部资源如某些型号的ADC模块共享采样序列器逻辑。复位一个模块可能无意中影响了另一个。解决仔细阅读数据手册中关于“模块复位”的说明了解其影响范围。问题3按照两步法操作SR寄存器但外设似乎没有真正复位。排查步骤验证写操作在置位和清除复位位后分别读取SR寄存器确认值的变化符合预期。使用调试器观察内存窗口或直接打印寄存器值。检查就绪状态操作后立即查询对应的PR寄存器。如果PR位一直为0说明外设没有从复位状态中恢复。这可能是因为时钟未提供该外设的时钟门控在RCGCx,SCGCx,DCGCx中被禁用了。软件复位不会自动打开时钟。你需要确保在清除复位位前该外设的时钟是使能的。复位释放延迟不足在清除复位位后增加更长的延时例如循环100次__nop()再查询PR状态或进行后续操作。查阅勘误表TI的芯片有时会有勘误文档Errata其中可能描述了特定型号在软件复位操作上的异常行为及解决方法。问题4代码在不同型号的Tiva™芯片间移植外设初始化失败。解决方案这就是PP寄存器的核心价值所在。将你的初始化代码中所有对外设存在的“硬编码”假设改为通过PP寄存器动态判断。反面教材#define HAS_USB 1然后直接调用USB_Init()。正确做法在初始化函数开头if (HWREG(SYSCTL_PPUSB) 0x01) { USB_Init(); }。进阶做法将PP寄存器的查询结果作为编译时常量或运行时配置表驱动整个BSP的构建实现真正的“一次编写多处运行”。问题5操作保留位时如何正确进行“读-修改-写”这是一个基础但至关重要的操作。错误示例HWREG(SYSCTL_SRGPIO) (1 5);这会直接覆盖整个寄存器破坏其他位。 正确做法uint32_t regValue; regValue HWREG(SYSCTL_SRGPIO); // 1. 读 regValue | (1 5); // 2. 修改置位Bit5同时不影响其他位 HWREG(SYSCTL_SRGPIO) regValue; // 3. 写 // 清除该位时同理 regValue HWREG(SYSCTL_SRGPIO); regValue ~(1 5); HWREG(SYSCTL_SRGPIO) regValue;许多MCU的驱动库都提供了位带Bit-band操作或专门的置位/清除寄存器来简化这个过程但理解其底层原理是必要的。掌握Tiva™ TM4C系列微控制器的外设存在与软件复位寄存器就如同拿到了芯片内部的“管理员手册”。它让你写的代码不再是盲目地操作硬件而是能与芯片进行“对话”先了解其能力边界再施加精准的控制。这种动态探测和可控恢复的思想是构建高可靠、可移植嵌入式系统的关键。下次当你面对一个新的Tiva™项目时不妨从扫描这些PP寄存器开始让你的系统从第一行代码就充满智慧。