简介这是一套面向嵌入式初学者与单片机开发者的STM32 LCD实时波形绘制工程围绕3.5寸彩屏驱动、ADC信号采集与动态曲线刷新展开可用于数据采集可视化、课程实验和毕业设计原型验证。压缩包共136个文件、约3.08MB包含C/H源码、Keil工程与编译中间文件以及HEX、MAP、SCT等构建产物便于直接打开工程、对照外设初始化与显示逻辑进行学习。已有4531人学习下载。工程涉及GPIO时序、LCD初始化、RGB565像素格式、波形坐标缩放与缓冲区刷新并给出DMA传输和定时器配置思路读者可据此理解从模拟采样到屏幕绘制的完整链路也能按分辨率、点距和刷新率调整参数扩展到不同尺寸显示屏或加入触控等交互功能。1. 从一块只会刷字的 LCD到能跑起来的实时波形图去年有个做电源的同行发来一段视频示波器上是一条标准的正弦他板子上那块 320×240 的屏却画出一条锯齿状的“心电图”采样点明明是对的画出来就是抖。这类问题在 STM32 上做 LCD 实时绘制波形图时几乎躲不掉——显示刷新和采样节奏一旦对不上波形就会开始抖动。这个项目要做的事情很朴素用单片机的 ADC 连续采一段模拟信号把那串数字实时画成一条会向左滚动的曲线刷新要跟得上、画面不能闪、坐标要能读。适合手上已经有块带屏开发板、想从“点亮屏幕”往前走一步的人也适合要把某路电压、电流、传感器输出做成可视化监视界面的嵌入式开发。2. 工程骨架从引脚定义到屏幕点亮的分层结构拿到这类项目第一反应不应该是打开绘图函数而是先看它怎么把“采样”和“显示”这两件互不相干的事拆开。拆不干净后面一定会遇到采样被刷屏阻塞、刷屏被采样打断的死循环。2.1 接口选型并口 FSMC 与 SPI 屏的取舍波形绘制和刷图片、刷文字的负载模型完全不同。文字界面一秒钟改几十个像素SPI 屏跑 20MHz 也够波形是整列整列往上怼320 个点铺满一屏就是几万个像素的写入SPI 在小屏上勉强能看屏一大就开始撕。这个项目走的是并口屏路线靠 STM32 的 FSMC 外设把 LCD 当成一片外部 SRAM 来访问。写一个像素的成本就是一次内存写CPU 不参与移位、不等待总线空闲速度快一个量级。代价是引脚多16 位数据线加几根控制线二十多个 IO 就没了布线时要有心理准备。常见做法是把 FSMC 的地址线和 LCD 的 RS命令/数据选择脚挂在一起。以接到 A17 为例A17 拉低时访问的是命令寄存器拉高时访问的是显存数据口两个地址之间正好差1 17也就是 0x20000 字节/* lcd_port.h —— 把往屏上写一个字节这件事收敛到几个宏里 */ #define LCD_BASE_ADDR ((uint32_t)0x6C000000) /* FSMC Bank1 第 4 区的基地址 */ #define LCD_REG_ADDR (LCD_BASE_ADDR) /* A17 0写命令 / 读 ID */ #define LCD_RAM_ADDR (LCD_BASE_ADDR 0x20000) /* A17 1写显存数据 */ #define LCD_WR_REG(x) (*(volatile uint16_t *)LCD_REG_ADDR (x)) #define LCD_WR_DATA(x) (*(volatile uint16_t *)LCD_RAM_ADDR (x)) #define LCD_RD_DATA() (*(volatile uint16_t *)LCD_RAM_ADDR)这几个宏是整个显示层的地基。volatile不能省编译器看到“写了一个地址又读回来”会自作聪明地优化掉之前有人就是漏了这个关键字屏幕初始化一半就卡死查了两天。地址偏移量 0x20000 也不是随便写的它严格对应你实际接的那根地址线接 A16 就是 0x10000接错了现象是命令和数据全写进同一个寄存器屏幕要么全白要么全黑。2.2 目录分层驱动层、采样层、绘图层各管一摊这类工程最怕所有代码塞进main.c。项目按职责切了四层我按这个结构重排过一次改起来顺手很多目录职责典型文件bsp/lcd屏初始化、描点、区域填充、字符lcd.c/lcd_port.hbsp/adcADC DMA 配置、采样缓冲管理bsp_adc.capp/wave坐标映射、曲线绘制、滑动刷新wave.capp/ui网格、刻度、状态栏等静态元素ui.c分层的关键不在目录好不好看在于依赖方向单一wave.c只调lcd.c暴露的描点和填充接口绝不直接碰 FSMC 宏bsp_adc.c只负责往环形缓冲区里塞数据不关心这些数据最后画成什么。这样换一块屏只改lcd.c换一路信号源只改bsp_adc.c。血泪经验是别图省事在绘图函数里直接写LCD_WR_DATA等到要换屏或者加第二块屏时全项目搜索替换能耗掉一整天。2.3 底层驱动三个必须写对的函数不管上层多花哨最终都落到三个函数上设坐标、写颜色、批量填充。前两个是原子操作第三个决定刷新速度。/* 设置接下来要写入的显存窗口注意不同驱动 IC 的坐标指令不一样 */ static void LCD_SetWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { LCD_WR_REG(0x2A); /* 列地址设置 */ LCD_WR_DATA(x0 8); LCD_WR_DATA(x0 0xFF); LCD_WR_DATA(x1 8); LCD_WR_DATA(x1 0xFF); LCD_WR_REG(0x2B); /* 行地址设置 */ LCD_WR_DATA(y0 8); LCD_WR_DATA(y0 0xFF); LCD_WR_DATA(y1 8); LCD_WR_DATA(y1 0xFF); LCD_WR_REG(0x2C); /* 开始写显存 */ } void LCD_DrawPoint(uint16_t x, uint16_t y, uint16_t color) { LCD_SetWindow(x, y, x, y); /* 单点也走窗口代码复用别另开分支 */ LCD_WR_DATA(color); } /* 整块填充画网格背景、清屏都靠它比逐点快几十倍 */ void LCD_FillRect(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color) { uint32_t n (uint32_t)(x1 - x0 1) * (y1 - y0 1); LCD_SetWindow(x0, y0, x1, y1); while (n--) { LCD_WR_DATA(color); /* 窗口设好后地址自动递增不用重复设置 */ } }参数上有一点要注意LCD_SetWindow的结束坐标包含在窗口内所以填充像素数是(x1-x01)*(y1-y01)少加那个 1 会导致每一行少画一个点屏上出现一条斜的裂缝。这种 bug 特别隐蔽因为大部分区域看起来是对的。LCD_DrawPoint每次都重设一遍窗口单点调用没问题但如果一帧里循环调用几千次光是重复写 0x2A/0x2B 指令就吃掉可观的时间。真想提速后面第 4 章会换成按列批量写。3. 采样链路TIM 触发 ADC DMA 的三件套显示层能亮了接下来是数据从哪来。这一步的设计直接决定波形的“真不真”。3.1 轮询采样的三个致命问题新手最常写的采样是while(1)里开一次转换、等 EOC、读值、存数组循环往复。这套写法在做一个温度计的时候没问题做波形就废了第一个问题是采样率不受控。转换时间加上循环里的其他代码实际间隔忽长忽短画出来的正弦在时间轴上被随机拉伸压缩看起来就是抖。第二个问题是 CPU 被绑死一旦开始刷屏采样就停了波形上出现一段水平直线。第三个问题最要命——采样和刷屏互相打断你永远不知道下一个点对应的是哪个时刻。正确的做法是让硬件自己跑定时器按固定周期发触发信号ADC 收到触发就转换转换完 DMA 自动把结果搬进内存。全程 CPU 不参与采样率由定时器周期精确定义抖动降到时钟级别。3.2 定时器触发与 DMA 循环搬运的配置假设目标采样率 10kHz系统时钟 84MHz定时器预分频 84-1 得到 1MHz 计数频率自动重装值填 100-1更新事件频率就是 10kHz。这里的关键是把定时器的 TRGO 输出接到 ADC 的外部触发源上/* TIM3 作为采样节拍发生器只输出 TRGO不产生中断 */ static void SampleTimer_Init(uint32_t sample_hz) { uint32_t tim_clk 84000000UL; /* 按实际 APB1 定时器时钟填 */ uint32_t arr tim_clk / sample_hz; htim3.Instance TIM3; htim3.Init.Prescaler 84 - 1; /* 1MHz 计数 */ htim3.Init.CounterMode TIM_COUNTERMODE_UP; htim3.Init.Period arr - 1; /* 10kHz 更新事件 */ HAL_TIM_Base_Init(htim3); TIM_MasterConfigTypeDef mc {0}; mc.MasterOutputTrigger TIM_TRGO_UPDATE; /* 更新事件 → TRGO */ mc.MasterSlaveMode TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(htim3, mc); HAL_TIM_Base_Start(htim3); /* 只启动计数不开中断 */ }TIM_TRGO_UPDATE这一行是整个链路的开关配成TIM_TRGO_RESET或者干脆不配ADC 就永远等不到触发现象是缓冲区里全是 0屏上一条贴底的直线。当时为了这个配置项翻了一晚上参考手册。ADC 侧要关掉连续转换模式打开外部触发触发源选ADC_EXTERNALTRIGCONV_T3_TRGODMA 设为循环模式#define ADC_CH_NUM 1 #define ADC_FRAME_LEN 512 /* 半个缓冲区的帧数必须是 2 的幂 */ static volatile uint16_t adc_dma_buf[ADC_FRAME_LEN * 2 * ADC_CH_NUM]; void BSP_ADC_Start(void) { HAL_ADC_Start_DMA(hadc1, (uint32_t *)adc_dma_buf, ADC_FRAME_LEN * 2 * ADC_CH_NUM); /* 长度单位是传输次数 */ }HAL_ADC_Start_DMA的第三个参数容易翻车多通道扫描时它要填“总转换次数”单通道时填“采样点数”单位搞错的表现是 DMA 传了一半就停或者直接越界写穿后面的变量。判断方法很简单——在调试器里看adc_dma_buf是不是从头到尾都被刷新过。3.3 半满/全满中断把数据接进环形缓冲区DMA 循环模式下缓冲区永远在被覆盖你不可能等它填满再去读那样读到的一半是新数据一半是旧数据。标准解法是用半传输和传输完成两个中断各拿到半块缓冲区/* 半满前半块 [0, ADC_FRAME_LEN) 已就绪 */ void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc) { Ring_PushBlock((uint16_t *)adc_dma_buf[0], ADC_FRAME_LEN); } /* 全满后半块 [ADC_FRAME_LEN, 2*ADC_FRAME_LEN) 已就绪 */ void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) { Ring_PushBlock((uint16_t *)adc_dma_buf[ADC_FRAME_LEN], ADC_FRAME_LEN); }这两个回调在中断上下文里跑所以Ring_PushBlock里绝对不能有耗时操作只做拷贝和写指针更新。我一般把环形缓冲区设成 4 倍于一次显示需要的点数给主循环留出足够的余量刷屏偶尔慢一帧也不会丢数据。顺带说一句回调里如果发现写指针快追上读指针说明绘图跟不上采样这时候要么降采样率要么减少每帧绘制点数别硬扛。硬扛的结果是缓冲区被覆盖波形上出现莫名其妙的跳变看起来像信号本身的毛刺实际是软件在丢帧——这种“玄学”问题最后往往靠一个计数器就能定位。4. 绘图层核心ADC 数值到屏幕像素的完整换算链路数据进缓冲区了剩下的问题是怎么把它们变成像素。这一层是整个项目里最值得抠细节的地方。4.1 坐标映射量程、零点以及那个 ±112 位 ADC 的输出是 0~4095屏幕的 y 坐标是 0~239 且向下为正。最直觉的映射是y 239 - raw * 239 / 4095但这样写有两个问题整数除法的截断误差会让曲线出现阶梯而乘除法顺序不对还会溢出。/* raw: 0~4095y_top/y_bot: 绘图区上下边界y_top 数值更小 */ static inline uint16_t adc_to_px(uint16_t raw, uint16_t y_top, uint16_t y_bot) { uint32_t span y_bot - y_top; /* 绘图区高度 */ /* 先乘后除中间结果最大 4095*239 ≈ 98 万32 位放得下 */ uint32_t scaled (uint32_t)raw * span / 4095U; return (uint16_t)(y_bot - scaled); /* 反向ADC 越大y 越小越靠上 */ }这里刻意用了“先减后映射”的写法。为什么要用y_bot - scaled而不是直接y_top (span - scaled)因为当raw 0时前者给出y_bot后者可能因为中间截断差一个像素导致 0V 对应的基线在两次编译之间上下跳一格看着就像零点漂移。做电参数监测的同事对这个 ±1 像素特别敏感因为他要靠这条线的位置去读电压值。实际产品里还要加两件事一是量程可配把4095换成ADC_FULL_SCALE宏配合前端的电阻分压比算真实电压二是零点偏移让波形可以围绕屏幕中线上下摆动而不是永远贴着底边。4.2 三种画法对比打点、连线、列扫描把相邻两个采样点连起来有三种常见写法性能差得很远画法做法优点缺点打点法每个采样点画一个像素实现最简单采样密时点连不成线出现断点连线法相邻两点之间补竖线曲线连续视觉最好每点要算插值多几次循环列扫描法一列只取该列内的最大最小值画竖条速度快密度高时有包络感丢失细节不适合低频信号这个项目用的是连线法本质就是把两个 y 之间的空档填满/* 在固定列 x 上把 y0 到 y1 之间的像素全部点亮 */ static void draw_vseg(uint16_t x, uint16_t y0, uint16_t y1, uint16_t color) { uint16_t y_start, y_end; if (y0 y1) { y_start y0; y_end y1; } else { y_start y1; y_end y0; } /* 一次设窗口然后连续写比逐点快 5 倍以上 */ LCD_SetWindow(x, y_start, x, y_end); for (uint16_t y y_start; y y_end; y) { LCD_WR_DATA(color); } }注意循环条件是y y_end窗口高度是y_end - y_start 1。这个细节错了会少画一个像素在斜率平缓的波形上表现为一条虚线感很强的曲线。列扫描法在高采样率场景下确实更快因为一列只写一次窗口把所有 y 都塞进一个连续写入里。但它有个前提一列里必须只有少量点。如果你的采样率是屏幕宽度的几十倍那一列会挤进几十个点画出来是一条粗带子看不出波形形状——这时候要么开启包络显示只画最大最小值要么把时间轴拉长别指望在一个像素列里塞进全部信息。4.3 滑动窗口刷新让波形“走”起来静止画一屏很简单难的是让它动起来。直接每帧清屏重画320×240 全屏填充一次大概要几毫秒画面会明显闪。项目用的是滑动窗口方案#define WAVE_X0 0 #define WAVE_X1 319 #define WAVE_Y0 20 #define WAVE_Y1 219 static uint16_t prev_y 0; /* 上一列的 y用于连线 */ static uint16_t cur_x 0; /* 当前绘制列 */ /* 每来一个新采样点调用一次 */ void Wave_PushSample(uint16_t raw) { uint16_t y adc_to_px(raw, WAVE_Y0, WAVE_Y1); if (cur_x WAVE_X0) { prev_y y; /* 换行时重置避免和上一行末端连线 */ } else { draw_vseg(cur_x, prev_y, y, WAVE_COLOR); } /* 关键把 x-1 列的旧像素擦掉再画新点形成左移效果 */ draw_vseg(cur_x, WAVE_Y0, WAVE_Y1, WAVE_BG); /* 先清空这一列 */ draw_vseg(cur_x, prev_y, y, WAVE_COLOR); /* 再画新段 */ prev_y y; cur_x; if (cur_x WAVE_X1) { cur_x WAVE_X0; /* 回到行首进入下一屏 */ } }这段代码里有个顺序问题必须先清列再画反过来会把刚画的点擦掉。第一次写的时候顺序搞反屏上干干净净什么都没有还以为驱动挂了。更成熟的做法是用“整屏左移 右侧补新列”每帧把显存里的内容整体左移一个像素然后在最右边一列画新数据。左移能用 DMA 或者按行memcpy加速但要占用额外的一块内存做中转RAM 紧张的型号玩不起。项目最后选择的是上面这种“逐列覆盖”逻辑简单代价是每列要写两次——一次背景色、一次前景色实际上相当于每次重画了两列。提示如果屏支持横屏滚动指令部分驱动 IC 有可以直接用硬件滚动CPU 完全不参与是这类需求里性价比最高的方案值得先翻一眼驱动手册再决定要不要写软件实现。5. 避坑与排查波形抖动、屏幕撕裂、数据错位的成因这个项目真正耗时间的不是写代码是排查。下面这几条都是实际踩过的按“现象 → 原因 → 解决”整理。5.1 显示侧闪烁、撕裂、残影现象一曲线边缘有明显锯齿抖动一帧一帧地跳。原因不是采样问题是每帧清屏重画导致的画面刷新不同步。整屏填充和曲线绘制之间存在一段时间差眼睛能捕捉到中间状态。 解决办法是改成局部刷新只重画变化的那一列或者用双缓冲——在内存里画好一帧再一次性刷到屏上。双缓冲对 RAM 要求高320×240×2 字节就是 150KBF1 系列扛不住F4 带外部 SRAM 才有戏。现象二屏幕最右边一列总是花的像被撕开。原因是绘图区宽度和屏幕实际宽度没对齐WAVE_X1填了 319 但显存窗口设置时又多画了一列写到了无效地址。这种撕裂在滑动刷新时特别明显因为每次换行都会重新踩一遍。 解决办法是把绘图区边界统一成宏并且和LCD_SetWindow的边界检查绑死越界的写入直接在驱动层拦掉。现象三波形后面拖着一条淡色的影子。残影通常是背景色不对。擦旧数据时用的是WAVE_BG但这个宏和初始化时清屏用的颜色不是同一个值两次写入留下了细微色差在低色深屏上表现为暗影。统一成一个宏就没有了。5.2 采样侧跳变、毛刺、数据整体错位现象四波形上每隔一段就出现一个尖刺频率还很规律。原因多半是 ADC 的采样时刻和开关电源、PWM 输出撞在了一起。定时器触发采样时如果没有避开功率器件开关的瞬间耦合进来的干扰就会被当成信号采下来。 解决办法是调整定时器的触发相位或者在 ADC 输入前加 RC 低通滤波。软件上的补救是对连续 N 个点做中值滤波但要清楚这会牺牲响应速度别在需要看真实毛刺的场合用。现象五整条波形整体偏移电压值对不上万用表。不是映射算错了是 ADC 参考电压和实际供电不一致。很多人默认VREF 3.3V直接算实际板子上是 3.28V 或者更低误差在满量程时能到几十毫伏。解决方式是用万用表量一下 VREF 引脚把常量改准或者用内部参考电压通道做校准。5.3 运行侧HardFault、DMA 覆盖、栈溢出现象六跑几分钟突然死机调试器停在 HardFault。这类问题最像黑匣子。常见原因有两个一是 DMA 缓冲区长度参数填错写穿到了后面的全局变量二是中断回调里调用了带阻塞的 HAL 函数比如在HAL_ADC_ConvCpltCallback里调HAL_Delay。 排查手段很土但有效把栈使用情况打印出来把 DMA 缓冲区前后各加一个魔数做哨兵跑一段时间后检查魔数有没有被改。我一般是先在HardFault_Handler里把 LR 和栈指针存到全局变量让调试器能看出错在第几层调用。注意中断里做的每一件事都要能在几十微秒内结束。宁可在回调里只置一个标志位把真正的处理丢到主循环也别图省事在中断里刷屏。6. 二次开发把这块屏改成你自己的数据监视器代码跑通之后绝大多数人的下一步都不是继续优化波形而是想把它改成能看自己那路信号的工具。这里给两条最常走的改造路线。6.1 换信号源与加通道换信号源其实只动bsp_adc.c里的通道配置和adc_to_px的量程宏。如果你要看的是 0~30V 的电源输出前端分压比是 10:1那么ADC_FULL_SCALE就该从 4095 换算成 30.0映射函数里多乘一个系数即可/* 把 raw 映射成真实电压mV再映射到像素 */ static inline uint16_t mv_to_px(uint32_t mv, uint16_t y_top, uint16_t y_bot) { const uint32_t V_MAX_MV 30000; /* 满量程 30V */ uint32_t span y_bot - y_top; if (mv V_MAX_MV) mv V_MAX_MV; /* 超量程钳位别让曲线冲出绘图区 */ return (uint16_t)(y_bot - mv * span / V_MAX_MV); }加第二通道的思路也一样但要注意两路信号要在同一个时间基准上画否则两条曲线对不齐。做法是让 ADC 扫描两个通道DMA 交错搬运缓冲区里[ch0, ch1, ch0, ch1...]排列绘图时按步长 2 取数。别用两个独立定时器各触发一路那样相位关系没法保证。6.2 加游标测量与触发功能真正好用的监视器不能只会画还得能读。加一条竖直游标和一条水平游标交叉点显示当前电压值和时间位置实现上就是两个全局坐标加按键或触摸事件去改它们绘制时把那一行一列反色。触发功能稍微复杂一点设定一个阈值和边沿方向缓冲区里找到第一个满足条件的点然后以这个点为基准对齐显示。这样波形就不会在屏幕上左右乱飘看起来稳定得多。实现顺序是先在数据里做查找找到后再决定这一帧从哪个点开始画。改造项改动量主要风险换量程/换信号源小只改宏分压比和参考电压算错加第二通道中改 DMA 与绘图两路时间不同步加游标/触发大涉及 UI 与状态机按键响应拖慢主循环改到这里我最想说的一条经验是每次改动之后别急着接真实信号先拿一块已知的方波或者直接用函数发生器跑一遍看基线位置、幅度、周期对不对三个都对上再去测实际电路。之前有次改完量程直接上电测波形看着挺像样结果读数整整差了一倍最后发现是分压电阻算错了白白怀疑了两天硬件。从那以后我每次动映射相关的代码都强制走一遍“方波验证”这一步慢一点但省心。希望这些能帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
APK修改工具怎么选?按层拆解三套工具链与完整重打包链路 简介:面向Android开发与逆向学习者的APK修改工具专题资料,围绕APK包结构、修改流程与常用工具展开,适合希望理解应用组成、进行个性化定制或研究应用逻辑的初中级读者。资源以zip压缩包分发,整体约28.58MB,文件计数显示… · 2026/11/4 7:54:38
三维光子晶体实现跨维度手性传输突破 1. 三维光子晶体中的跨维度手性传输突破去年冬天,当大多数物理学家还在为二维拓扑材料中的边界态争论不休时,南京大学的研究团队已经在实验室里捕捉到了电磁波在三维光子晶体中完成"维度跃迁"的奇妙现象。这项发表在《科学进展》上的工作&… · 2026/11/4 7:54:38
HACS极速安装六法:5分钟完成Home Assistant插件商店部署 1. HACS 极速版不是官方版本,但它是真实存在的高效实践路径 “HACS 极速版”这个说法在Home Assistant社区里没有官方定义——Home Assistant Community Store(HACS)本身只有一个主线版本,由开源团队持续维护,当前稳定… · 2026/11/4 7:54:38
Hermes Agent 配置与定制完全指南:5 步装好你的 AI 代理 Hermes Agent 配置与定制完全指南:5 步装好你的 AI 代理
刚装好的 AI 代理不好用:对话不记上下文,开发项目里又总想执行高危命令,每轮响应还慢、还贵。根源往往不在模型,而在配置。Hermes Agent 是一个会自我进化的开… · 2026/11/4 11:22:16
基于Springboot教学资料管理系统【附源码+文档】 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 11:22:16
基于Springboot校园外卖服务平台【附源码+文档】 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 11:22:16
基于Springboot问卷调查管理系统【附源码+文档】 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 11:22:16
字节跳动联合港大推出 Mini-o3!专治 AI 视觉推理 “没耐心”,训练 6 轮能推理几十步 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 11:22:16
基于Springboot火锅店管理系统【附源码+文档】 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 11:21:14
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38
AI辅助技术栈评估:提升研发决策效率60% 1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年… · 2026/11/4 0:00:17
从生成Token到直接决策:Jev如何重塑AI Agent工程实践 1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你… · 2026/11/4 0:00:17
32G统一内存跑大模型:内存账、TPS实测与端云分流 想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统… · 2026/11/4 0:00:17
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38