LPC1114实战例程:从最小系统到UART、PWM与避坑指南
简介面向嵌入式初学者的LPC1114开发资源围绕NXP Cortex-M0内核微控制器整理了可直接导入MDK工程的例程与配套教程覆盖GPIO控制、I2C/SPI/UART通信、ADC、PWM、NTC测温等常见外设应用场景适合从零开始搭建学习路径。压缩包共658个文件约4.79MB主体为C源文件、头文件、MDK工程文件uvproj/uvopt、编译生成文件axf/hex及备份另含少量PDF说明与工程截图文件分类清晰便于对照编译产物与源码理解开发流程。已有456人学习。读者可基于例程快速掌握外设初始化与中断配置逻辑并通过μVision调试器在线观察运行状态示例工程涵盖旋转编码器、RGB灯、按键中断、GPS等具体应用能够帮助初学者通过改引脚、调时序、看调试信息逐步积累实际开发经验为后续独立设计温度监测或定时控制类项目打下基础。1. LPC1114 的实际例程和教程别把它当成 STM32 的廉价替代品很多刚接触 LPC1114 的开发者第一反应是“这不过是个 Cortex-M0 内核的小单片机照着 STM32 的思路写总没错”。实际跑起来才发现LPC1114 的时钟树、引脚复用和 Flash 烧写方式都有自己的一套脾气尤其当你拿到一块最小系统板想点亮一颗 LED 却卡在 GPIO 配置上时就知道“实际例程”和“官方手册”之间差了不止一层窗户纸。这篇笔记要解决的就是这个问题LPC1114 到底怎么上手、例程怎么抄、参数怎么调、哪些坑是新手必踩的。我会从最小系统搭建讲到外设驱动再给出可以直接复刻的工程骨架适合那些手里已经有一块 LPC1114 板子、却对着数据手册无从下手的从业者也适合想从 8 位机跳到 32 位机但不想被复杂库函数劝退的人。这里没有玄学只有按着引脚电平去验证的实打实步骤。2. 先从最小系统说起LPC1114 的时钟、电源和启动选择2.1 为什么 LPC1114 的“最小系统”比 STM32 多一个注意事项LPC1114 是 NXP 的 Cortex-M0 低功耗芯片内部主频最高 50MHz但默认出厂时用的是内部 RC 振荡器频率精度不高。很多教程例程直接在 main 函数里初始化 GPIO不配置系统时钟结果定时器、串口波特率全偏。我一般拿到新板子第一件事就是看芯片顶部的丝印确认后缀是 FHN33 还是 FBD48因为引脚数量和封装不同最小系统的晶振接法也有区别。对于 LPC1114FHI33/QFP33 这类常用封装外部晶振不是必须的因为内部 RC 可以跑但是如果你要用 USB 或者精准波特率就得外接 12MHz 晶振并通过 PLL 倍频到 48MHz 或 50MHz。这里有个反直觉的点LPC1114 的 PLL 输入频率并不是随便给的数据手册里明确要求外部晶振频率必须在 10MHz 到 25MHz 之间很多人用 8MHz 晶振去倍频结果 PLL 锁定失败却查不到原因。2.2 最小硬件的连接清单电源、复位、下载接口LPC1114 的电源域分 VDD(3.3V) 和 VDDA(模拟电源)两者电压必须一致否则 ADC 采样会漂移。我的最小系统做法是VDD 和 VDDA 都接 3.3V每个电源引脚旁边放一个 100nF 去耦电容另外在 VDD 总线上再加一个 10uF 钽电容。复位引脚 RESET 内部有上拉但强烈建议外接 10k 上拉电阻到 3.3V同时并联 100nF 电容到地这样能避免下载器复位时的毛刺导致进入 ISP 模式失败。下载接口有两种常见方式一种是 4 线 SWDSWDIO、SWCLK、VCC、GND用 CMSIS-DAP 调试器就能连另一种是串口 ISP通过 UART0 的 TXD/RXD 引脚进入 Bootloader。ISP 模式需要把 P1.4 引脚ISP 使能脚拉低后再复位上电这个细节很多教程都没写清楚导致有人以为芯片坏了其实是没进入 ISP 状态。引脚功能连接建议P1.4ISP 使能10k 上拉下载时拉低复位P0.4SWDIO直接连调试器可串 100R 保护P0.5SWCLK直接连调试器可串 100R 保护RST复位10k 上拉 100nF 到地2.3 用 KEIL 建一个最简工程只有启动文件和时钟初始化实际例程的第一步不是写 main而是建一个能编译通过的裸机工程。我常用 KEIL MDK因为 NXP 官方库和启动文件在 KEIL 下最容易集成。工程里必须包含两个文件startup_LPC11xx.s启动文件和 system_LPC11xx.c系统时钟初始化。这两个文件可以从 NXP 官网的 LPCOpen 例程包复制但要注意版本——LPC1114 和 LPC1112 的启动文件不完全通用因为 Flash 大小不同向量表偏移和散列文件也要对应。下面是我验证过的最小 main.c 框架它先读系统时钟频率再初始化 GPIO保证后续外设参数不出偏差#include LPC11xx.h void SystemInit(void) { // 在 system_LPC11xx.c 中已有实现这里重写是为了演示 LPC_SYSCON-SYSPLLCLKSEL 0x01; // 选择外部晶振作为 PLL 输入 LPC_SYSCON-SYSPLLCLKUEN 0x01; // 使能 PLL 更新 LPC_SYSCON-SYSPLLCLKUEN 0x00; // 先写 0 再写 1触发更新 LPC_SYSCON-SYSPLLCLKUEN 0x01; while (!(LPC_SYSCON-SYSPLLSTAT 0x01)); // 等待 PLL 锁定 } int main(void) { SystemInit(); // 点亮 PIO0_0 对应的 LED假设板子上 LED 接在这个脚 LPC_GPIO0-DIR | (1 0); LPC_GPIO0-DATA | (1 0); while (1); }代码里的 SystemInit 是个简化版真实工程里 system_LPC11xx.c 会通过 SystemCoreClock 变量告诉你当前时钟频率。注意SYSPLLCLKSEL赋值 0x01 表示选择 Main Oscillator如果你没有接外部晶振这里应该改成 0x00选择内部 RC否则程序会卡死在while (!(LPC_SYSCON-SYSPLLSTAT 0x01))。这个等待循环就是新手常说的“程序跑飞了”真相之一不是死循环问题而是 PLL 根本没锁定CPU 一直停在启动代码里。3. GPIO 例程的骨架从数据手册的引脚描述表到点亮 LED3.1 先看懂 LPC1114 的引脚复用寄存器没有 AFIO 表格直接看 IOCON用过 STM32 的人都知道有个 AFIO 或 GPIOx_AFRL 寄存器来配置复用功能LPC1114 没有这套东西它用 IOCON 寄存器组。每个引脚都有对应的 IOCON 寄存器地址在 LPC_IOCON 基地址上偏移比如 PIO0_2 的 IOCON 地址是 0x4004400C。IOCON 寄存器里几个关键位bit0 到 bit3 是 FUNC 字段选择引脚是 GPIO 还是 UART 还是 SPIbit6 是 MODE 字段选择上拉、下拉或高阻bit7 是 HYS 使能迟滞。如果不设置 IOCON默认引脚是带内部上拉的 GPIO 输入所以你想把它当输出时必须先把 FUNC 改成 0再把 DIR 寄存器设为输出。很多教程抄 STM32 的习惯直接操作 DIR 置位忘了改 IOCON结果发现引脚电平一点反应都没有其实就是内部上拉拉住了电平外部 LED 根本不分压。3.2 点亮 LED 的标准步骤配置 IOCON、方向、数据下面这段代码是从我的 LPC1114 实际例程里抽出来的专门操作 PIO0_0 作为推挽输出来驱动 LED。注意 LPC1114 的 GPIO 数据寄存器有两种访问方式一种是字节/半字访问的 DATA 寄存器但更常用的是DATA mask这种掩码方式这么做的好处是能快速翻转某个或多个引脚而不影响其他引脚。#include LPC11xx.h void LED_Init(void) { // 1. 配置 IOCON 引脚为 GPIO 功能内部无上下拉 LPC_IOCON-PIO0_0 0x00; // FUNC0 即 GPIOMODE0 无上下拉 // 2. 设置方向为输出 LPC_GPIO0-DIR | (1 0); } void LED_On(void) { LPC_GPIO0-DATA | (1 0); // 置高电平 } void LED_Off(void) { LPC_GPIO0-DATA ~(1 0); // 清低电平 }这里有个参数说明LPC_IOCON-PIO0_0是结构体访问方式如果你用的是旧版 CMSIS 头文件可能字段名是PIO0_0或PIO0_1具体要看LPC11xx.h里LPC_IOCON_TypeDef的定义。有些库函数版本把 IOCON 寄存器命名为REG或者直接给地址宏所以当你编译报错找不到PIO0_0成员时就得打开头文件确认一下字段名而不是盲目改类型。另外DATA寄存器是 32 位但 LPC1114 的引脚只有 0 到 11 这 12 个 GPIO 有效所以操作时只关心低 12 位其余位写入也无效读回可能为 0。3.3 按键输入例程内部上拉怎么开消抖怎么做按键是第二个必练例程。LPC1114 的 GPIO 输入默认是上拉但如果你想用外部上拉电阻或者完全依靠内部上拉就需要在 IOCON 里设置 MODE 字段为 10上拉或 00无上下拉。实际测试中内部上拉的阻值大约在 40k 到 80k 之间对于机械按键来说够用但如果你只接了一个按键到地不按的时候引脚读为高按下读为低。这里的关键是消抖硬件上可以加一个 100nF 电容并联在按键两端软件上可以用定时器做 10ms 延时重新读一次。下面是一个标准轮询例程的骨架uint32_t Read_Key(void) { // 假设按键接在 PIO0_1, 按下接地 if ((LPC_GPIO0-DATA (1 1)) 0) { delay_ms(10); // 简单延时消抖 if ((LPC_GPIO0-DATA (1 1)) 0) { return 1; // 确认按下 } } return 0; }注意这个例程里没有配置 IOCON因为 PIO0_1 默认就是 GPIO 输入加上拉直接检测电平没问题。但如果你把引脚配置成了漏极开路那就需要外部上拉电阻了。这个 mini 例程的价值在于LPC1114 的 GPIO 没有 EXTI 那样的外部中断功能它用的是 Grouped Interrupt也就是 GPIO 中断寄存器组配置起来比 STM32 复杂所以很多简单产品直接用轮询反正 M0 内核主频 50MHz轮询按键损耗的 CPU 时间可以忽略。4. UART 串口例程把 LPC1114 的调试信息打印出来4.1 UART0 的引脚映射不是所有 TX/RX 都天然可用LPC1114 的 UART0 有两组可选引脚一组是 PIO0_1/RXD 和 PIO0_2/TXD另一组是 PIO1_6/RXD 和 PIO1_7/TXD这需要你在 IOCON 里把引脚功能从 GPIO 改为 UART。很多人直接照着 STM32 的板子画原理图把 USB 转串口的 TX 接到了某个任意 GPIO然后在软件里硬绑定 UART0结果当然不通。正确做法是先查数据手册第 9 章“Pin description”表格看哪些引脚具备 UART0_TXD 功能。比如 PIO0_2 的 FUNC 设为 1 就是 UART0_TXDPIO0_1 的 FUNC 设为 1 就是 UART0_RXD。还要注意如果引脚同时具有 TDI 等调试功能则要避免冲突。4.2 波特率计算LPC1114 的 UART0 没有独立的时钟分频器吗有的它有一个小数分频器Fractional Divider可以用起来微调波特率。LPC1114 的 UART0 时钟来自 SystemClock 经过 UARTCLKDIV 分频后获得默认 UARTCLKDIV 为 1所以 UART 外设时钟就等于系统时钟。波特率计算公式是baud PCLK / (16 * (256 * DL DLM))其中 DLM 和 DL 是除数锁存寄存器注意 DL 是 8 位最大 255所以当 PCLK 是 48MHz想得到 9600 波特率除数是 48e6/(16*9600)312.5意味着 DL 溢出这时需要先设置 UARTCLKDIV 把 PCLK 降到合适范围比如 12MHz 再算。这里有个经典翻车案例有人想用 115200 波特率PCLK 48MHz除数 26.04取 26 后误差约 0.4%基本能用但如果系统时钟用的是内部 RC 振荡器误差可能到 2%丢字节会非常随机。void UART0_Init(uint32_t baudrate) { uint32_t uClk SystemCoreClock / 4; // 先用 4 分频把 PCLK 降到 12MHz 左右 LPC_SYSCON-UARTCLKDIV 4; uint32_t divisor uClk / (16 * baudrate); LPC_SYSCON-SYSAHBCLKCTRL | (1 6); // 使能 UART0 时钟门控 LPC_IOCON-PIO0_1 0x01; // RXD: FUNC1 表示 UART0_RXD LPC_IOCON-PIO0_2 0x01; // TXD: FUNC1 表示 UART0_TXD LPC_UART0-LCR 0x83; // 8 位数据1 停止位无校验使能除数锁存 LPC_UART0-DLM (divisor 8) 0xFF; LPC_UART0-DL divisor 0xFF; LPC_UART0-FDR 0x10; // 小数分频器设为默认值不做微调 LPC_UART0-LCR 0x03; // 关闭除数锁存进入正常模式 }这段代码里我把 UARTCLKDIV 设成 4是为了让 PCLK 从 48MHz 降到 12MHz这样 9600 和 115200 的除数都在 16 位可表示范围内。注意 FDR 寄存器默认值不一定合理如果你发现误差大可以查数据手册的分数分频表选择最接近的 MULVAL 和 DIVADDVAL 组合。还有一点LPC_UART0-LCR 访问顺序有讲究必须先使能除数锁存DLAB1才能写 DLM 和 DL写完再恢复否则写入无效。4.3 用串口中断接收不定长数据LPC1114 的 FIFO 和中断标志实际项目中串口接收不应该用 while 死等因为 LPC1114 的 UART0 有个 16 字节的 FIFO如果不在数据满之前取走就会溢出。我常用的做法是用 UART 中断在中断里读取 RBR 寄存器并把数据放到一个环形缓冲区。中断使能寄存器 IER 的 bit0 是 RBR 中断使能bit2 是接收超时中断使能。很多新手把这两个都打开了结果超时中断触发频繁干扰主程序。我的习惯是只开 RBR 中断关闭超时中断然后在应用层按帧间隔来判断一包数据是否结束。下面是一个中断接收的骨架volatile uint8_t uart_rx_buf[128]; volatile uint8_t uart_rx_head 0; volatile uint8_t uart_rx_tail 0; void UART0_IRQHandler(void) { uint8_t ch; if (LPC_UART0-IIR 0x04) { // 判断是否 RBR 接收中断 ch LPC_UART0-RBR; // 读数据同时清除中断标志 uart_rx_buf[uart_rx_head] ch; uart_rx_head % 128; } }这里有个细节读 RBR 寄存器会自动清除接收中断标志不需要像外部中断那样手动清零。但是如果你同时开启了错误中断那么还得检查 UART0-RSR 里面的 PE、FE、BI 位如果出现这几个位必须读一下 RSR 清标志否则中断会一直触发。我在调试某串口模块时就遇到过这种现象单片机接收数据正常但程序经常卡死最后发现是线路干扰导致帧错误中断持续触发UART0_IRQHandler 里只要判断 0x04 分支其它中断标志没处理于是死循环在中断里。解决方法是把错误检测加上uint8_t error_clear LPC_UART0-RSR; // 非阻塞读自动清错误标志5. 定时器和 PWM 例程用 SystemTick 和 CT32B0 产生精准延时5.1 LPC1114 有几种定时器SysTick、CT16B0/B1、CT32B0/B1 怎么选LPC1114 内部有系统滴答定时器 SysTick以及两个 32 位定时器 CT32B0、CT32B1还有两个 16 位定时器 CT16B0、CT16B1。SysTick 最适合做操作系统心跳但它只有 24 位而且嵌套中断优先级固定为最低。对于想要产生 PWM 输出控制 LED 亮度或者舵机的情况推荐用 CT32B0因为它是 32 位并且在匹配寄存器 MR0 到 MR3 可以配置为 PWM 模式。CT16B0 也可以做 PWM但周期受限于 16 位如果主频 48MHz最大周期是 65535/48MHz≈1.36ms连一个标准舵机的 20ms 周期都做不出来所以做舵机控制必须用 CT32B0这是个经常被忽略的选型要点。5.2 用 CT32B0 产生一个 1ms 中断的配置过程下面的代码演示了如何把 CT32B0 配置成周期 1ms 的定时器中断。LPC1114 的外设时钟默认来自主时钟但可以通过 SYSAHBCLKCTRL 位来控制每个外设的时钟门控所以要先打开 CT32B0 的时钟。匹配中断寄存器 IR 在匹配事件产生后会被置位需要在中断服务函数里写 1 清除这是与 UART 中断不同的地方。void CT32B0_Init(void) { LPC_SYSCON-SYSAHBCLKCTRL | (1 9); // 使能 CT32B0 时钟门控 LPC_CT32B0-TCR 0; // 先关定时器 LPC_CT32B0-PR SystemCoreClock / 1000 - 1; // 预分频到 1kHz LPC_CT32B0-MR0 1; // 匹配值计数器每计 1 次产生中断 LPC_CT32B0-MCR 0x03; // 匹配中断使能 匹配复位 TC LPC_CT32B0-TCR 0x01; // 启动定时器 NVIC_EnableIRQ(CT32B0_IRQn); // 使能 NVIC 中断 } void CT32B0_IRQHandler(void) { if (LPC_CT32B0-IR 0x01) { LPC_CT32B0-IR 0x01; // 写 1 清中断标志 // 这里放周期任务比如翻转 LED } }注意这里的预分频寄存器 PR 和匹配值 MR0 的配合我先把 PR 设为 SystemCoreClock/1000 - 1意思是把 48MHz 分频到 1kHz那么 TC 每加 1 就代表 1ms然后 MR0 设为 1这样每个计数周期触发一次中断。这种做法的好处是匹配值计算直观缺点是如果主频被修改这里的参数也要跟着改。更通用做法是 PR 设为 0MR0 设为 SystemCoreClock/1000这样精度更高但匹配值可能超过 16 位需要确认 CT32B0 是 32 位没问题。中断标志位 IR 必须写 1 清零这是 Cortex-M 系列外设里很常见的“写 1 清 0”规则和 GPIO 置位方式不同。5.3 用 PWM 控制 LED 亮度匹配寄存器通道怎么分配CT32B0 的 PWM 模式要把 MCR 配置为 0x02复位 TC 但不中断再设置 PWMR0 到 PWMR3 的引脚复用。常见做法是MR0 设定 PWM 周期MR2 用作占空比通道。注意 PWM 的引脚映射需要在 IOCON 里把引脚从 GPIO 切换到 CT32B0_MAT2 功能。比如 PIO0_1 的 FUNC2 就是 CT32B0_MAT2但 PIO0_1 同时也是 UART0_RXD所以同一个引脚不能同时用作 PWM 和串口设计电路时要提前避开。如果选 PIO1_0 作为 CT32B0_MAT2那么 FUNC 要设成 1。这些功能编号在数据手册“Pin description”表格里有明确列写实际使用前必须核对否则 PWM 信号死活出不来。另一个容易踩坑的是 PWM 初始化顺序要先设置周期 MR0再设置占空比 MR2最后把 TCR 置位启动如果顺序颠倒或先使能 PWM 输出再改占空比输出会出现一个不期望的高电平毛刺可能烧掉 LED。6. 避坑指南LPC1114 实际调试中的 5 个典型问题6.1 现象程序烧录进去后第一次运行正常复位后就不跑了原因启动文件里的 SystemInit 函数没有正确初始化 Flash 等待周期。LPC1114 在较高主频下需要配置 FLASHCFG 寄存器否则复位后 Flash 读取时序不匹配代码在启动阶段就进入 HardFault。解决在 SystemInit 函数末尾添加LPC_FLASH-FLASHCFG 0x0000303A;这是一个针对 50MHz 主频的典型配置值具体字段含义要参考手册中的 Flash Access Time 表。如果不想动启动文件也可以把 SystemCoreClock 设为 48MHz 以下降低闪存时序要求。6.2 现象串口打印出来的字符全是乱码用示波器看波形却是好的原因波特率误差超过 2%。内部 RC 振荡器在温度变化下会产生 1% 到 2% 的漂移而 UART 通信要求总体误差小于 2%两者叠加就容易出错。解决改用外部晶振或者使用 UART0 的分频器微调 FDR 寄存器。我一般把 FDR 的值设为 0x21也就是 MULVAL1、DIVADDVAL0这个组合适合大多数 48MHz 分频后的波特率。如果还乱码直接测量 UART0_TXD 引脚的实际波特率用示波器数单个 bit 宽度百兆采样率就能测准。6.3 现象GPIO 输出高电平但 LED 亮度很暗测电压只有 1.8V原因LPC1114 的 GPIO 输出驱动能力不是全推挽某些引脚默认是开漏模式。比如 PIO0_4 和 PIO0_5 默认是开漏因为它们是 I2C 专用的引脚如果不配置 IOCON 里的 OD 位无法正常输出高电平。解决在初始化代码里对 IOCON 寄存器写(value ~0x10)关闭开漏。检查自己用的引脚是不是具备开漏功能看数据手册里 IOCON 表中有没有标注“OD”字段。如果确认不是开漏再量一下 GPIO 到 VDD 之间是不是有上拉电阻被 PCB 设计意外焊上了。6.4 现象进入 ISP 模式失败串口工具显示无响应原因LPC1114 的 ISP 模式需要 P1.4 引脚在复位释放前保持低电平并且复位时间必须足够长。很多 USB 转串口模块的 DTR/RTS 引脚逻辑电平不稳定导致复位时序不对。解决手动做一个按键复位和跳线帽拉低 P1.4然后先按住 ISP 按键再按复位释放再点击串口发送“?”如果能返回同步字节说明进入成功。另一个隐藏原因是芯片的 UART0 TXD/RXD 引脚不在 PIO0_1/PIO0_2 上有些最小系统板把 ISP 引脚设计到了其它位置你需要看板子的原理图确认。6.5 现象ADC 采样值跳变严重几个通道之间互相干扰原因LPC1114 的 ADC 参考电压可以选择 VDD 或内部 1.8V 基准但内部基准噪声较大并且在多通道切换时需要足够采样时间。解决优先使用外部 3.3V 作为 VREF并在软件里设置 ADC 的采样时间为最大比如将 ADCON 寄存器里的 CLKDIV 设大一些确保每个采样时钟周期在 1us 以上。还可以在硬件上把 ADC 输入引脚旁边的 100nF 滤波电容加上避免相邻通道串扰。这个坑在测量电池电压时最常见尤其是输入源阻抗超过 10k 时ADC 内部的采样电容来不及充电。7. 从例程到产品做一个可以长期跑的双串口 Modbus 透传小模块当你能把 GPIO、UART、定时器例程都调通后最值得做的进阶项目是用 LPC1114 实现一个 Modbus RTU 主从透传模块。这个项目能把前面所有外设串起来UART0 接上位机UART1如果 LPC1114 有的话注意 LPC1114 实际上只有 UART0但可以用 CT16B0 模拟一个软串口接下位机定时器用来做 3.5 个字符时间的帧间隔判断。我用 LPC1114 做过一个类似的模拟项目 X上位机通过 Modbus 轮询多个温湿度传感器LPC1114 作为从机同时把数据从串口透传到蓝牙模块。原理很简单但工程性很强。一个关键技巧是利用 LPC1114 的 UART 接收超时中断来判断一帧 Modbus 数据是否结束Modbus 标准规定帧间隔为 3.5 个字符时间。在 9600 波特率下3.5 个字符约 3.6ms所以可以用 CT32B0 做一个 4ms 的定时器在收到第一个字节时启动之后每个字节到来时重置定时器定时器中断触发时认为一帧接收完成。这个做法避免了使用 UART 超时中断因为 LPC1114 的 UART 超时中断固定为 4.5 个字符时间和 Modbus 需要的不完全匹配。另一个进阶技巧是引脚重映射。如果你发现 PIO0_1/PIO0_2 被下载器占用可以把 UART0 的 TX/RX 映射到 PIO1_6/PIO1_7这样调试串口和下载接口就不会冲突。具体配置是 IOCON 里 PIO1_6 的 FUNC 设为 2PIO1_7 的 FUNC 设为 2。这个细节在画 PCB 时特别有用因为大多数板子把 SWD 用到了 PIO0_4/PIO0_5不会冲突但如果你用了 PIO0_1/PIO0_2就会在调试时没法同时看串口。我的习惯是设计电路时就把 UART0 默认引脚空出来把下载接口放在不与外设复用的一侧。关于代码可维护性我强烈建议不要直接修改寄存器来写整个工程而是把每一类外设封装成独立函数GPIO_Init、UART_SendChar、Timer_DelayMs。LPC1114 没有像 STM32 的 HAL 库那么完整但你可以自己写一套薄封装这样后续更换芯片时底层的寄存器操作只需要改一点点。我甚至会把SystemCoreClock的赋值放在一个单独文件里每次检查硬件配置时直接看这个文件而不是在 main 里翻逻辑。最后说一个血的教训我给某温控板做过一次固件升级因为改动了 SystemInit 里的 PLL 倍频值没有重新计算 UART 波特率除数导致同一块电路板下载后串口全部乱码。从那以后我每次改时钟配置都会在初始化函数里加一句printf_clock_config用串口输出当前的 SystemCoreClock确保外设时钟与自己预想一致。希望这些能帮你少走弯路也祝你的板子一上电就能出波形。本文还有配套的精品资源点击获取

相关新闻

Vue全局挂载实战:从原理到选型,彻底搞懂全局函数与变量

Vue全局挂载实战:从原理到选型,彻底搞懂全局函数与变量

1. 全局挂载这件事,到底在解决什么问题刚接触 Vue 那会儿,我最常干的一件事就是把一个工具函数从utils.js里import到每一个用到的组件里。三五个组件还好,等到项目里几十个组件都要用同一个格式化时间的方法时,每个文件顶部都挂着…

2026/10/15 12:44:11 阅读更多 →
Category底层原理全解析:从结构体到方法合并的完整链路

Category底层原理全解析:从结构体到方法合并的完整链路

去年面一家头部大厂的时候,面试官问了一个让我印象很深的问题:“你平时写分类写得很溜,那你说说,Category 的底层是怎么把方法加到类上去的?为什么它能‘覆盖’类里面原来的方法?”当时我虽然背过不少面经&…

2026/10/15 12:43:10 阅读更多 →
磁性材料与元件学习路线:从理论到实践

磁性材料与元件学习路线:从理论到实践

1. 磁性材料与元件学习路线概述从事磁性材料研发工作十年,我深刻体会到这是一门需要理论积累与实践验证并重的学科。刚入行时面对纷繁复杂的磁学参数和材料体系,也曾感到无从下手。本文将系统梳理磁性材料与元件的学习路径,重点解析核心知识框…

2026/10/15 12:43:10 阅读更多 →

最新新闻

TileLang:GPU异构计算的声明式分块编程范式

TileLang:GPU异构计算的声明式分块编程范式

1. TileLang不是新语言,而是GPU编程范式的底层重构最近在几个高性能计算开源项目里反复看到tilelang这个词,它既不像Rust那样有语法教程,也不像CUDA那样带完整IDE支持,甚至GitHub上连个独立仓库都没有——但它频繁出现在MLIR、LLV…

2026/10/15 13:26:57 阅读更多 →
Android OpenGL ES绘制圆形全攻略:从三角形扇到着色器工程实战

Android OpenGL ES绘制圆形全攻略:从三角形扇到着色器工程实战

简介:一份面向 Android 图形开发学习者的 OpenGL ES 圆形绘制示例工程。项目通过 OpenGL 实现了圆饼填充、圆环描边与点状圆圈的绘制,覆盖从顶点数据生成、着色器编写到渲染状态设置的完整流程。资源包共 567 个文件,以 xml 布局与资源、grad…

2026/10/15 13:26:57 阅读更多 →
MATLAB二维Delaunay网格生成:MESH2D轻量可控实战指南

MATLAB二维Delaunay网格生成:MESH2D轻量可控实战指南

简介:MESH2D是一款面向科研人员、工程仿真从业者及高校师生的MATLAB/Octave二维Delaunay网格生成工具,专为解决有限元分析、流体力学模拟、地形建模等场景中复杂几何区域的高质量三角剖分问题而设计。资源包共69个文件,含55个核心MATLAB函数&…

2026/10/15 13:26:57 阅读更多 →
SAP外部作业调度服务实战解析与优化

SAP外部作业调度服务实战解析与优化

1. 项目背景与核心价值在企业级应用环境中,SAP系统的批处理作业(Application Job)管理一直是运维工作的重点和难点。传统的手工调度方式不仅效率低下,还容易因人为失误导致作业执行失败或资源冲突。External Job Scheduling Servi…

2026/10/15 13:26:57 阅读更多 →
VMware桥接模式实现虚拟机远程登录与文件传输

VMware桥接模式实现虚拟机远程登录与文件传输

1. 项目概述:为什么桥接模式是远程协作的“隐形地基”VMware桥接网络模式,远程登录和远程传输文件——这三件事放在一起,不是偶然组合,而是实际工作中最常被卡住的“铁三角”。我带过不少刚接触虚拟化环境的开发者和运维新人&…

2026/10/15 13:26:57 阅读更多 →
UEFI DXE阶段驱动开发实战:协议、事件与调试

UEFI DXE阶段驱动开发实战:协议、事件与调试

简介:这份PPT资料围绕UEFI启动流程中的DXE(Driver Execution Environment)阶段展开,面向固件开发工程师、BIOS初学者及嵌入式系统学习者,帮助理解DXE阶段在系统初始化中的核心作用与运行机理。资源共1个pptx文件&#…

2026/10/15 13:25:56 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →