STM32 DMA通道优先级配置实战:优化多外设数据传输性能
最近在开发嵌入式系统时经常需要处理内存与外部设备如传感器、显示屏、通信模块之间的高速数据搬运。如果仅靠CPU通过软件循环来搬运数据会大量占用CPU时间导致系统整体性能下降实时性变差。这时DMA直接内存访问技术就成了提升效率的关键。本文将围绕STM32的DMA控制器特别是其通道配置中的“优先级”概念进行一次彻底的梳理和实战演示。无论你是刚开始接触STM32的新手还是已经用过DMA但对其优先级机制感到模糊的开发者都能通过本文理解其工作原理并掌握如何在实际项目中正确配置以优化数据传输流程。1. DMA核心概念与为什么需要优先级在深入配置之前我们必须先理解两个基础问题DMA是什么以及为什么它需要“优先级”管理。DMA是什么DMADirect Memory Access是一种允许特定硬件子系统直接读写系统内存而无需中央处理器CPU介入的技术。你可以把它想象成一个高效的“数据搬运工”。当外设如ADC转换完成、UART收到数据需要将数据存入内存或者内存中的数据需要发送给外设如通过SPI驱动显示屏时CPU只需告诉DMA搬运工任务的起点、终点和数量然后就可以去处理其他计算任务。DMA会独立完成整个数据块的搬运并在完成后通知CPU。这极大地解放了CPU提高了系统并行处理能力。为什么需要优先级在一个复杂的STM32应用中往往有多个外设同时需要DMA服务。例如一个系统可能同时在进行ADC以1MHz采样率持续采集传感器数据高实时性不能丢失。UART以115200波特率接收上位机指令中等实时性偶尔延迟可接受。SPI向OLED屏刷新局部画面低实时性但数据量大。如果这些请求同时到达DMA控制器该先处理谁如果处理不当高实时性的ADC数据可能因为等待SPI传输大量显示数据而被覆盖丢失导致系统功能异常。因此DMA通道优先级机制就是为了仲裁多个同时发生的DMA传输请求确保关键数据流不被阻塞满足系统的实时性要求。STM32的DMA控制器为每个通道都配备了可编程的优先级逻辑这是正确使用DMA进行多任务数据管理的核心。2. 环境准备与硬件模型说明为了清晰地演示优先级的影响我们需要设定一个具体的实验环境。本文的代码和思路基于意法半导体ST的STM32系列微控制器但其DMA优先级的概念在ARM Cortex-M内核的芯片中是相通的。2.1 硬件与软件环境MCU型号 以常见的STM32F103C8T6蓝桥杯、正点原子开发板常用为例它拥有2个DMA控制器DMA1, DMA2共12个通道DMA1有7个通道DMA2有5个通道。不同型号通道数和外设映射可能不同请务必查阅对应芯片的《参考手册》。开发环境 Keil MDK-ARM (uVision) 或 STM32CubeIDE。编程方式 本文采用标准外设库Standard Peripheral Library进行讲解因其寄存器操作直观易于理解原理。使用HAL库的开发者可以很容易地进行概念迁移。涉及外设 我们将使用两个外设来模拟竞争场景ADC1 用于模拟高优先级、周期性的数据采集通道1。USART1 用于模拟中等优先级、不定时的数据接收通道4。调试工具 串口调试助手、逻辑分析仪或示波器用于观察时序。2.2 实验场景设定我们构造一个简单的竞争场景任务A高优先级 ADC1使用DMA1的通道1以10kHz的速率连续采集并存入数组adc_buffer。每次传输半字16位。任务B低优先级 USART1使用DMA1的通道4在收到上位机发送的100字节数据包时通过DMA将数据存入数组uart_buffer。我们的目标是当USART1的DMA传输正在进行中时ADC的DMA请求到来。通过配置不同的优先级观察ADC数据是立即得到响应抢占还是必须等待USART1传输完成从而直观地理解优先级的作用。3. DMA优先级机制深度拆解STM32的DMA通道优先级并非简单的“谁先谁后”而是一个可配置的仲裁策略。理解其寄存器配置是灵活运用的前提。3.1 优先级等级在DMA_CCRx寄存器中由PL[1:0]位控制通道优先级。通常分为四个等级00: 低 (Low)01: 中 (Medium)10: 高 (High)11: 最高 (Very High)(部分型号支持)3.2 仲裁规则仲裁发生在两个时刻同时请求 当两个或多个配置好的DMA通道同时发出传输请求时仲裁器会比较它们的PL位。优先级高的通道先获得总线使用权开始传输。优先级相同的通道则硬件通道编号小的优先例如通道2优先于通道4。传输中被抢占 这是更关键的一点。STM32的DMA不支持传输过程中的抢占。这意味着一旦一个通道开始了传输比如正在搬运100个字节它就会持续占用数据总线直到本次传输可能是单次传输也可能是循环模式下的一次“轮回”完成。在此期间即使有更高优先级的通道发出请求也必须等待当前传输结束。传输完成后仲裁器会重新评估所有等待中的请求根据优先级决定下一个服务对象。3.3 关键配置项与误区传输模式 优先级行为与传输模式密切相关。单次模式 (Normal): 传输指定数量的数据后通道自动关闭。优先级影响下一次传输的启动顺序。循环模式 (Circular): 传输完指定数量数据后指针自动重置到起始地址循环进行。在循环模式下每次“循环结束”可以被视为一次传输完成点仲裁器可以在此点重新仲裁。但对于一次循环内的数据传输依然不可被抢占。数据宽度与突发传输 配置的源/目标数据宽度字节、半字、字以及是否使能突发传输会影响单次总线访问传输的数据量但不会改变“单次传输过程不可抢占”这一基本原则。误区纠正 “高优先级”不等于“实时抢占”。它保证的是在仲裁点的优先权而非打断正在进行的传输。这对于设计实时系统至关重要。4. 完整实战配置与验证优先级效果下面我们通过一个具体代码示例展示如何配置ADC和UART的DMA并观察不同优先级下的行为。4.1 外设与DMA通道初始化首先初始化ADC1和USART1并配置它们的DMA。// 文件 main.c #include stm32f10x.h #include stdio.h // 用于printf调试 #define ADC_BUFFER_SIZE 256 #define UART_BUFFER_SIZE 100 uint16_t adc_buffer[ADC_BUFFER_SIZE]; uint8_t uart_rx_buffer[UART_BUFFER_SIZE]; void DMA1_Channel1_IRQHandler(void) { if(DMA_GetITStatus(DMA1_IT_TC1)) { // ADC DMA传输完成中断 DMA_ClearITPendingBit(DMA1_IT_TC1); // 此处可以处理ADC数据例如计算平均值、设置标志位等 GPIOB-ODR ^ GPIO_Pin_0; // 翻转PB0灯指示ADC DMA传输完成 } } void DMA1_Channel4_IRQHandler(void) { if(DMA_GetITStatus(DMA1_IT_TC4)) { // UART DMA传输完成中断 DMA_ClearITPendingBit(DMA1_IT_TC4); // 处理接收到的UART数据包 GPIOB-ODR ^ GPIO_Pin_1; // 翻转PB1灯指示UART DMA传输完成 // 重新使能DMA接收准备下一个包单次模式需重新配置 DMA_Cmd(DMA1_Channel4, DISABLE); DMA_SetCurrDataCounter(DMA1_Channel4, UART_BUFFER_SIZE); DMA_Cmd(DMA1_Channel4, ENABLE); } } void ADC1_DMA_Init(void) { DMA_InitTypeDef DMA_InitStructure; ADC_InitTypeDef ADC_InitStructure; // 1. 开启时钟 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE); // 2. 配置ADC引脚 PA1 为模拟输入 GPIO_InitStructure.GPIO_Pin GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AIN; GPIO_Init(GPIOA, GPIO_InitStructure); // 3. 配置DMA1通道1 (ADC1对应通道1) DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)(ADC1-DR); // 外设地址ADC数据寄存器 DMA_InitStructure.DMA_MemoryBaseAddr (uint32_t)adc_buffer; // 内存地址 DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralSRC; // 方向外设-内存 DMA_InitStructure.DMA_BufferSize ADC_BUFFER_SIZE; // 传输数量 DMA_InitStructure.DMA_PeripheralInc DMA_PeripheralInc_Disable; // 外设地址固定 DMA_InitStructure.DMA_MemoryInc DMA_MemoryInc_Enable; // 内存地址递增 DMA_InitStructure.DMA_PeripheralDataSize DMA_PeripheralDataSize_HalfWord; // 16位 DMA_InitStructure.DMA_MemoryDataSize DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode DMA_Mode_Circular; // 循环模式 DMA_InitStructure.DMA_Priority DMA_Priority_High; // 【关键点】设置为高优先级 DMA_InitStructure.DMA_M2M DMA_M2M_Disable; // 内存到内存模式禁用 DMA_Init(DMA1_Channel1, DMA_InitStructure); // 4. 配置ADC1 ADC_InitStructure.ADC_Mode ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode DISABLE; // 单通道 ADC_InitStructure.ADC_ContinuousConvMode ENABLE; // 连续转换 ADC_InitStructure.ADC_ExternalTrigConv ADC_ExternalTrigConv_None; // 软件触发 ADC_InitStructure.ADC_DataAlign ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel 1; ADC_Init(ADC1, ADC_InitStructure); // 5. 配置ADC通道1采样时间 ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5); // 6. 使能ADC的DMA请求 ADC_DMACmd(ADC1, ENABLE); // 7. 使能DMA通道1的中断传输完成中断 DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); // 8. 使能DMA通道 DMA_Cmd(DMA1_Channel1, ENABLE); // 9. 使能ADC ADC_Cmd(ADC1, ENABLE); // 10. 校准并启动ADC ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); ADC_SoftwareStartConvCmd(ADC1, ENABLE); } void USART1_DMA_RX_Init(void) { DMA_InitTypeDef DMA_InitStructure; USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; // 1. 开启时钟 (DMA1时钟已开) RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); // 2. 配置USART1引脚 PA9-TX, PA10-RX GPIO_InitStructure.GPIO_Pin GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, GPIO_InitStructure); // 3. 配置USART1 USART_InitStructure.USART_BaudRate 115200; USART_InitStructure.USART_WordLength USART_WordLength_8b; USART_InitStructure.USART_StopBits USART_StopBits_1; USART_InitStructure.USART_Parity USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, USART_InitStructure); USART_Cmd(USART1, ENABLE); // 4. 配置DMA1通道4 (USART1_RX对应通道4) DMA_DeInit(DMA1_Channel4); DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)(USART1-DR); DMA_InitStructure.DMA_MemoryBaseAddr (uint32_t)uart_rx_buffer; DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralSRC; // 方向外设-内存 DMA_InitStructure.DMA_BufferSize UART_BUFFER_SIZE; DMA_InitStructure.DMA_PeripheralInc DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode DMA_Mode_Normal; // 单次模式 DMA_InitStructure.DMA_Priority DMA_Priority_Low; // 【关键点】设置为低优先级 DMA_InitStructure.DMA_M2M DMA_M2M_Disable; DMA_Init(DMA1_Channel4, DMA_InitStructure); // 5. 使能DMA通道4的中断 DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE); // 6. 使能USART1的DMA接收请求 USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE); // 7. 使能DMA通道 DMA_Cmd(DMA1_Channel4, ENABLE); } int main(void) { // 初始化系统时钟、NVIC、GPIO用于LED指示等 SystemInit(); // ... 初始化代码省略 ... // 配置NVIC使能DMA1通道1和通道4的中断 NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel DMA1_Channel1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority 0; NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel DMA1_Channel4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1; NVIC_Init(NVIC_InitStructure); // 初始化ADC DMA (高优先级循环模式) ADC1_DMA_Init(); // 初始化USART1 DMA RX (低优先级单次模式) USART1_DMA_RX_Init(); while(1) { // 主循环处理其他任务 // 可以通过串口打印状态或根据标志位处理数据 } }4.2 实验操作与现象分析烧录程序 将上述代码需补充完整的时钟和GPIO初始化编译后烧录到开发板。连接硬件 连接USB转串口线到USART1用逻辑分析仪或示波器探头连接两个LED引脚PB0和PB1。场景一无竞争 系统启动后ADC以高优先级循环采集PB0灯会以ADC_BUFFER_SIZE / 采样率的频率闪烁。此时USART1空闲。场景二制造竞争 通过串口调试助手一次性发送超过100字节的数据触发USART1 DMA接收。在发送瞬间USART1 DMA启动低优先级。观察现象如果ADC DMA优先级更高 在USART1 DMA传输100字节期间ADC DMA的请求会不断产生。但由于“传输中不可抢占”规则ADC DMA必须等待。只有当USART1 DMA单次传输完100字节后仲裁器才会重新裁决。由于ADC DMA优先级高它会立刻获得总线开始搬运累积的ADC数据此时PB0灯闪烁一次代表一次传输完成中断。之后USART1 DMA才能重新被使能准备下次接收。现象是UART接收期间ADC数据搬运可能被延迟但不会丢失因为ADC DR寄存器有数据且DMA请求被挂起。如果调整优先级 将USART1_DMA_RX_Init函数中的DMA_Priority改为DMA_Priority_High将ADC的改为DMA_Priority_Low。重复实验。你会发现当长数据包到来时USART1的DMA传输高优先级会持续进行ADC的传输完成中断PB0可能长时间不触发直到UART传输结束。这模拟了低优先级任务被“饿死”的风险。通过LED的闪烁时序和逻辑分析仪抓取的波形可以清晰看到不同优先级配置下总线使用权的分配差异。5. 常见问题与排查思路在实际使用DMA优先级时可能会遇到一些典型问题。问题现象可能原因排查思路与解决方案高优先级数据仍有丢失1. 源数据被覆盖如ADC DR寄存器在DMA读取前被新数据覆盖。2. DMA缓冲区溢出。3. 优先级理解错误高优先级通道的传输请求产生时低优先级通道的单次传输尚未结束导致高优先级请求被阻塞。1. 提高ADC DMA服务频率减少单次传输数据量Buffer Size或提高DMA总线带宽检查时钟配置。2. 使用双缓冲Double Buffer或循环缓冲区。3.核心分析低优先级任务的最长传输时间。确保高优先级任务的数据产生间隔 低优先级任务的最长单次传输时间。否则需重新设计架构如拆分低优先级的大数据量传输。多个同优先级通道响应顺序不符合预期未理解同优先级下的硬件通道号仲裁规则。记住规则同优先级下通道号小的优先Ch0 Ch1 ...。根据此规则规划外设到通道的映射。将最紧急的外设分配到编号更小的通道。配置了最高优先级但似乎无效1. 该型号可能不支持“Very High”优先级。2. 可能存在比DMA优先级更高的总线仲裁者如CPU的紧耦合内存访问。3. 中断被全局关闭。1. 查阅芯片《参考手册》确认优先级支持情况。2. 优化CPU代码减少对系统总线的长时间占用如密集的内存拷贝。3. 检查__set_PRIMASK()或相关中断控制位是否意外关闭了所有中断包括DMA传输完成中断。循环模式下低优先级任务完全得不到执行高优先级通道配置为循环模式且其单次循环传输时间过长持续占用总线。这是设计缺陷。避免让高实时性、高优先级的任务进行长时间、大数据量的循环DMA传输。可以将其改为由定时器触发的中断小批量DMA传输或使用双缓冲并在每次半满/全满中断时短暂释放总线。排查清单[ ] 确认DMA和外设时钟已使能。[ ] 确认DMA通道与外设的映射关系正确查数据手册。[ ] 确认DMA_Priority参数已按需设置。[ ] 确认传输模式Normal/Circular符合场景预期。[ ] 计算低优先级任务的最大阻塞时间评估高优先级任务是否能容忍。[ ] 使用调试器或IO翻转在DMA传输开始/完成中断中打点用逻辑分析仪观察实际时序。6. 最佳实践与工程建议合理运用DMA优先级能极大提升系统可靠性和性能。以下是一些工程经验总结6.1 优先级分配策略关键实时数据流赋予最高优先级 如高速ADC采样、电机控制的PWM更新、关键传感器的通信如SPI/I2C。数据丢失会导致功能失效或安全事故。中等优先级用于重要但不紧急的数据流 如通信接口UART, CAN的数据接收、中等速度的数据采集。允许一定延迟但不能无限等待。低优先级用于后台或大数据量搬运 如内存到内存的数据处理、显示屏的帧缓存更新、SD卡数据读写。这些任务可以充分利用总线空闲时间。6.2 架构设计建议避免“大块传输”阻塞总线 不要给一个低优先级通道配置一次传输数KB数据的任务。应将其拆分为多个小数据块传输并在每次传输完成后释放总线让仲裁器有机会服务高优先级请求。善用传输完成中断TC和半传输中断HT 在循环模式或双缓冲模式下利用HT和TC中断来切换缓冲区并处理数据。这不仅能实现“乒乓操作”还能在中断处理中嵌入一些必要的业务逻辑同时让DMA有机会在缓冲区切换间隙释放总线。结合定时器触发 对于周期性采样使用定时器触发ADC然后ADC触发DMA。这样可以精确控制数据产生的节奏便于分析总线负载。考虑使用双DMA控制器 如果芯片有多个DMA控制器如DMA1和DMA2可以将竞争激烈的关键外设分配到不同的控制器上它们有独立的仲裁器可以真正并行工作。6.3 配置注意事项文档化 在项目设计文档中明确记录每个DMA通道的分配、优先级、传输模式和数据量。这对于团队协作和后期维护至关重要。测试极端情况 在系统集成测试阶段需要模拟所有DMA通道同时满负荷请求的场景验证系统是否仍能满足实时性要求。留有余量 总线带宽和DMA处理能力是有限的。在设计时要计算所有DMA通道的理论带宽需求总和并确保它远小于理论总线带宽为CPU访问和其他总线主设备留出余地。掌握DMA优先级配置是进行高效、可靠嵌入式系统设计的一项基本功。它要求开发者不仅了解外设和DMA的配置寄存器更要理解系统总线的仲裁机制和数据流的时序特性。通过本文的讲解和实验希望你能建立起清晰的认知并在下一个项目中游刃有余地驾驭多路DMA数据传输。

相关新闻

Prompt 之外,生产级 Agent Harness 到底在控制什么

Prompt 之外,生产级 Agent Harness 到底在控制什么

Prompt 之外,生产级 Agent Harness 到底在控制什么 发布边界:本文的六层控制面是作者工程综合,不是 OpenAI 官方产品架构。预算阈值、权限强度和状态转换必须按具体系统验证。 摘要 “最多搜索五次”“不要浪费 Token”“完成后立刻停止”写…

2026/10/16 0:14:14 阅读更多 →
AI Agent构建实战:从核心认知到模块化设计与风险规避

AI Agent构建实战:从核心认知到模块化设计与风险规避

1. 从“玩具”到“生产力”:我们为什么需要AI Agent?最近两年,AI领域最火的概念,除了大模型本身,恐怕就是“AI Agent”了。从AutoGPT的横空出世,到各种“数字员工”、“AI副驾”的涌现,再到各大…

2026/10/16 8:25:21 阅读更多 →
NVIDIA Profile Inspector终极指南:免费解锁NVIDIA显卡隐藏性能

NVIDIA Profile Inspector终极指南:免费解锁NVIDIA显卡隐藏性能

NVIDIA Profile Inspector终极指南:免费解锁NVIDIA显卡隐藏性能 【免费下载链接】nvidiaProfileInspector 项目地址: https://gitcode.com/gh_mirrors/nv/nvidiaProfileInspector 还在为游戏卡顿、画面撕裂而烦恼吗?想不想免费获得专业级的显卡优…

2026/10/16 2:05:46 阅读更多 →

最新新闻

PyTorch实战指南:从核心原理到生产部署的完整路径

PyTorch实战指南:从核心原理到生产部署的完整路径

先交代一下背景:我从一个纯调库的“炼丹新手”到现在能独立把 PyTorch 模型搬上生产环境,中间踩过的坑、绕过的弯、想明白的道理,挺值得整理成一篇完整文章的。PyTorch 这套框架,表面上看起来就是一个定义模型、写训练循环、调 lo…

2026/10/16 8:25:28 阅读更多 →
通话回声怎么消除?从声学回声原理到免提设备排查全攻略

通话回声怎么消除?从声学回声原理到免提设备排查全攻略

一位朋友上周跟我诉苦,说他每次打电话都听到自己说话的回声,尤其是开了免提之后更明显,一度怀疑是麦克风老化要去售后换整机。结果我让他回复一句“你是不是开的免提或者用平板接的电话”,他问完对方之后沉默了——对方那头开着免…

2026/10/16 8:25:28 阅读更多 →
JDBC连接MySQL实战:增删改查、防注入与返回值类型详解

JDBC连接MySQL实战:增删改查、防注入与返回值类型详解

JDBC 这套东西,刚接触数据库编程的人多半会觉得它又臭又长:加载驱动、拿连接、开 Statement、拼 SQL、处理结果集、一层层关资源,写一次忘一次。但真到了项目里,尤其是需要自己手写数据访问层、做小工具、写批处理脚本、或者维护一…

2026/10/16 8:25:28 阅读更多 →
深入Django模板引擎:架构原理与高级API实战

深入Django模板引擎:架构原理与高级API实战

这几年带过不少新人,发现大家对Django模板引擎的态度基本分成两类:一类觉得它就是“在HTML里塞几个花括号占位符”的语法糖,能用就行;另一类觉得它自成一套体系,文档翻起来头大,于是宁愿在视图里拼字符串也…

2026/10/16 8:25:28 阅读更多 →
PyTorch七环节实战:张量、数据流水线、DDP与部署避坑指南

PyTorch七环节实战:张量、数据流水线、DDP与部署避坑指南

PyTorch 是我这几年用得最顺手的一套深度学习框架。从最早的图像分类 Demo,到后面做推荐排序、多模态内容理解,落地的代码基本都用它写的。如果你刚开始接触 PyTorch,或者已经在用但总觉得代码里有些细节解释不通——比如为什么有的层要单独初…

2026/10/16 8:25:28 阅读更多 →
多智能体协作系统架构设计与落地:从单体Agent到Agency Agents

多智能体协作系统架构设计与落地:从单体Agent到Agency Agents

最近差不多两个月的时间,我一直泡在一个内部研发辅助工具的重构项目里,核心动作就是把它从单Agent模式改成多智能体协作系统,内部代号就叫Agency Agents。听着有点绕,但整体思路其实很朴素:与其让一个大模型从头到尾包…

2026/10/16 8:24:28 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

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

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 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/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练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 阅读更多 →