尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
STM32电子密码锁仿真设计:状态机、EEPROM存储与Keil+Proteus联调
简介这是一套基于STM32F103C6设计的电子密码锁仿真与源码工程面向嵌入式初学者、STM32开发爱好者及课程设计用户。资源包含完整的HAL库驱动源码、外设配置和应用层逻辑可帮助读者理解密码输入、校验、显示及开锁控制等典型设计流程也便于在此基础上扩展按键、LCD或EEPROM等功能。压缩包共277个文件以h头文件与c源文件为主体另有o目标文件、axf调试输出及uvprojx工程配置等整体约7.6MB目录结构清晰适合对照学习与二次开发。目前已有559人学习下载资料偏重实践比较适合想通过完整工程快速入门STM32外设编程和状态机设计的用户。1. 需求切入为什么选用 STM32 做电子密码锁仿真而不是直接上实物某实验室要把机械锁换成电子密码锁需求列出来其实只有三条密码能改、输错三次要锁定、掉电不能丢密码。最终交付的是一套基于 STM 设计的电子密码锁仿真加源码仿真在先、代码在后不急着铺 PCB先把按键、存储、校验、驱动这一整套逻辑在仿真环境里完整跑通。选 STM32 而不是 51 单片机是因为密码存储要碰 I2C 和 EEPROM错误计数、锁定计时、状态切换这些业务逻辑放在 51 上写会非常挤而且调试手段也受限。STM32F103 系列仿真模型成熟Keil 里可以直接单步调试外设映射清晰很适合把逻辑设计和硬件设计拆开做。这套方案适合两类人准备交电子系统课设或毕设的学生以及产品还没有定型、想先把核心流程在仿真里验证完再考虑硬件方案的工程师。2. 总体架构设计硬件选型、外设映射与状态机规划2.1 主控选型与外设引脚映射主控选择 STM32F103C8T6而不是同系列的低容量型号主要看三件事一是硬件 I2C 外设完整直接接 AT24C02不需要软件模拟时序二是 64KB Flash、20KB SRAM跑密码状态机绰绰有余还给后续加指纹模块或者蓝牙模块留了空间三是 Proteus 和 Keil MDK 对这颗芯片的支持都很完整仿真模型不用自己建直接放置就能用。外设引脚映射如下这套分配在后续代码里保持一致功能模块引脚分配配置说明4×4 矩阵键盘行线 PB0~PB3列线 PB4~PB7行线推挽输出列线浮空输入LCD1602 显示数据线 PA0~PA7RSPC0RWPC1ENPC28 位并行模式AT24C02 密码存储PB6SCLPB7SDA硬件 I2C1两根线各接 4.7kΩ 上拉电磁锁继电器驱动PA8高电平导通继电器线圈并联续流二极管有源蜂鸣器PA9NPN 三极管放大驱动状态指示 LEDPC13低电平点亮用于锁定/开锁可视化引脚分配的原则是让矩阵键盘和 LCD 各占一组完整端口这样操作 GPIO 端口寄存器时不需要做位屏蔽代码写起来直接、不容易出错。I2C 引脚固定挂在 PB6/PB7 上这是 STM32F103 的硬件映射不能随意改。实物开发时经常有人把 PB6/PB7 复用到别的功能上导致 I2C 拉不起来仿真阶段虽然不会遇到这个问题但按这个映射表去做实物能少踩一个坑。2.2 四层模块划分与数据流向工程代码按职责拆成四层每一层只做自己范围内的事遇到问题也知道去哪层找原因。BSP 驱动层负责 GPIO、I2C、定时器和看门狗的初始化只提供 Init 和极少数读写接口。应用层封装具体外设矩阵键盘扫描、LCD1602 显示、AT24C02 读写、蜂鸣器与继电器控制。业务层实现密码校验状态机包括错误次数累计、锁定倒计时、修改密码事务。主循环只做三件事轮询按键、喂狗、把按键事件交给状态机处理。数据流向是一条单行道矩阵键盘产生按键事件状态机根据当前状态决定是写 EEPROM、操作继电器还是忽略按键LCD 只负责把结果呈现出来。所有模块之间不跨层调用比如 LCD 显示函数不能直接读按键缓冲区那样会把逻辑搅成一团。实际做下来这种分层最大的收益是测试方便把按键事件模拟成函数调用不碰屏幕不碰存储就能把状态机跑一遍。2.3 系统状态机六状态设计与转移边界系统运行生命周期由六个状态覆盖每个状态的行为边界非常明确STATE_INIT 上电初始化从 EEPROM 读取密码长度、密码内容和上次的错误次数。如果读出来是 0xFF 或长度越界说明 EEPROM 是空白的此时写入默认密码 123456确保系统第一次上电就有可用密码。STATE_IDLE 待机屏幕显示待机界面等待第一个数字键。STATE_INPUT 输入每按一个数字键追加进输入缓冲界面统一用 * 回显不显示明文。STATE_VERIFY 校验按下 # 键触发把输入缓冲与 EEPROM 中存储的密码逐字节比对。STATE_OPEN 开锁继电器吸合 5 秒后自动断开回到待机。STATE_LOCKED 锁定连续输错三次进入锁定 30 秒期间蜂鸣器鸣叫任何按键都无效。状态转移关系可以收敛成一张表当前状态触发事件动作下一状态INIT初始化完成读取 EEPROM 并显示待机画面IDLEIDLE按下数字键清空输入缓冲写入第一位INPUTINPUT按下数字键且缓冲未满追加输入位显示一个 *INPUTINPUT按下 # 且长度符合要求发起校验VERIFYVERIFY校验通过继电器吸合错误次数清零OPENVERIFY校验失败且错误次数不足 3 次提示剩余可尝试次数IDLEVERIFY校验失败且累计达到 3 次锁定系统蜂鸣器报警LOCKEDLOCKED30 秒倒计时结束清空错误计数恢复待机IDLE这里有两个容易被漏掉的转移边界。第一个是 INPUT 状态下按 * 键应该在当前输入缓冲内删除最后一位用作输错时的后悔药不进其他状态。第二个是 VERIFY 状态执行校验期间不允许任何按键打断要等校验函数返回后再恢复按键扫描否则处理到一半被新按键塞进来输入缓冲就乱了。Locked 状态下还要注意不要用阻塞延时做 30 秒倒计时否则看门狗会一直在临界边缘试探我用 SysTick 做全局 tick 计数锁定后每毫秒递减到零自动回 IDLE。3. 核心实现细节键盘扫描、EEPROM 存取与校验状态机代码3.1 矩阵键盘扫描与双次消抖矩阵键盘扫描的基本思路是逐行拉低、读列线电平。代码里先用一张映射表把行列位置翻译成实际键值再按行扫描// 键值映射表4 行 × 4 列 static const uint8_t key_map[4][4] { {1, 2, 3, A}, // 第一行 {4, 5, 6, B}, // 第二行 {7, 8, 9, C}, // 第三行 {*, 0, #, D} // 第四行* 退格# 确认 }; // 行线 PB0~PB3列线 PB4~PB7 static const uint16_t row_pin[4] {GPIO_Pin_0, GPIO_Pin_1, GPIO_Pin_2, GPIO_Pin_3}; static const uint16_t col_pin[4] {GPIO_Pin_4, GPIO_Pin_5, GPIO_Pin_6, GPIO_Pin_7}; uint8_t Key_Scan(void) { uint8_t row, col; for (row 0; row 4; row) { GPIO_Write(GPIOB, 0xFF); // 所有引脚先置高 GPIO_ResetBits(GPIOB, row_pin[row]); // 当前行拉低 Delay_us(50); // 等待电平稳定 for (col 0; col 4; col) { if (GPIO_ReadInputDataBit(GPIOB, col_pin[col]) 0) { // 列线被拉低说明当前行列交叉处有按键按下 while (GPIO_ReadInputDataBit(GPIOB, col_pin[col]) 0); return key_map[row][col]; } } } return 0xFF; // 无按键 }这段代码里有两个细节一是每轮扫描先把整个 GPIOB 写 0xFF再单独拉低当前行防止上一行残留电平影响判断二是检测到按键后自旋等待松开避免一次按键被重复返回多次。自旋等待在仿真阶段没有问题但如果后面要做低功耗休眠需要改成非阻塞方式检测到按下就记录并返回键值主循环下一轮再检测松开状态。单纯扫描还不够机械按键按下瞬间有 5~15ms 的抖动窗口Proteus 仿真模型里也带这个特性所以必须加消抖uint8_t Key_Get(void) { uint8_t k1 Key_Scan(); if (k1 0xFF) return 0xFF; Delay_ms(20); // 抖动窗口 5~15ms延时 20ms 足够覆盖 uint8_t k2 Key_Scan(); if (k1 k2) return k1; // 两次扫描结果一致判定为有效按键 return 0xFF; // 结果不一致按抖动处理丢弃 }消抖的延时长短不是拍脑袋定的实测大多数轻触按键的抖动集中在 10ms 以内取 20ms 是留了余量。仿真环境运行速度比实物慢35 毫秒以上的延时会让按键响应显得迟钝所以 20ms 是一个兼顾稳定性和响应速度的值。真正容易翻车的地方是如果在消抖延时期间主循环去做了别的耗时操作按键状态就丢了一半所以 Key_Get 应该被看成一次完整的原子操作。3.2 EEPROM 密码存储地址规划与读写封装AT24C02 通过硬件 I2C1 挂载密码、长度、错误次数和锁定标志都放在里面。先规划地址避免后续逻辑越界地址内容说明0x00密码长度写入时固定为 60x01~0x06密码内容6 字节 ASCII 码0x10连续错误次数掉电不清零0x11锁定标志记录是否处于锁定状态读一个字节的标准 I2C 时序如下使用硬件 I2C 外设而不是软件模拟是因为硬件时序由芯片内部状态机保证不会被按键中断打断#define EEPROM_WR_ADDR 0xA0 #define EEPROM_RD_ADDR 0xA1 uint8_t EEPROM_ReadByte(uint8_t addr) { uint8_t val 0; // 起始信号 写地址 I2C_GenerateSTART(I2C1, ENABLE); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, EEPROM_WR_ADDR, I2C_Direction_Transmitter); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // 发送内存地址 I2C_SendData(I2C1, addr); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // 重复起始信号 切到读模式 I2C_GenerateSTART(I2C1, ENABLE); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, EEPROM_RD_ADDR, I2C_Direction_Receiver); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); // 读取一个字节 while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); val I2C_ReceiveData(I2C1); I2C_GenerateSTOP(I2C1, ENABLE); return val; }代码里每一步都在轮询 I2C 事件标志这是硬件 I2C 的标准用法。如果仿真中程序卡在某个 while 循环里出不来大概率是地址发送后 AT24C02 没回 ACK需要在前面加一个读状态寄存器的调试函数确认器件在线。另一个我常犯的错是写完一字节后立刻读AT24C02 有 5ms 左右的写周期写完马上访问会读到旧数据行业内管这叫黑匣子问题所以写操作后必须加延时或查询 ACK 状态。密码写入比读取多一步回读校验uint8_t Password_Save(uint8_t *pw, uint8_t len) { uint8_t i; EEPROM_WriteByte(PW_LEN_ADDR, len); Delay_ms(10); // 等待 AT24C02 内部写周期完成 for (i 0; i len; i) { EEPROM_WriteByte(PW_DATA_ADDR i, pw[i]); Delay_ms(10); // 每个字节之间留足够写周期 } // 回读校验写入和读出不一致直接返回失败 for (i 0; i len; i) { if (EEPROM_ReadByte(PW_DATA_ADDR i) ! pw[i]) return 0; } return 1; }回读校验这步不是多余动作。仿真环境里时序不太严格可能稳定但实物上电源跌落、总线干扰都可能导致写失败。如果不回读界面提示“保存成功”但实际存的是错值掉电重启后才发现密码不对那时候已经没有后悔药了。3.3 密码校验与连续错误锁定密码校验函数把输入缓冲和 EEPROM 里的密码逐字节比对长度不一致直接返回失败不做多余的比较uint8_t Password_Verify(void) { uint8_t stored_len, match 1, i; stored_len EEPROM_ReadByte(PW_LEN_ADDR); if (stored_len ! input_len) return 0; for (i 0; i stored_len; i) { if (EEPROM_ReadByte(PW_DATA_ADDR i) ! input_buf[i]) { match 0; break; } } return match; }校验之后的动作分为三路通过则继电器吸合并清零错误计数失败且次数小于 3 则提示剩余次数失败且达到 3 次则进入 LOCKED 状态。错误次数本身也存进 EEPROM这样即使断电重启锁定状态依然保留用户不能靠重启绕过锁定。void StateMachine_Process(uint8_t key) { switch (lock_state) { case STATE_INPUT: if (key 0 key 9) { if (input_len 6) { input_buf[input_len] key; LCD_ShowChar(*); // 只回显星号 } } else if (key #) { lock_state STATE_VERIFY; Verify_And_Act(); } else if (key *) { if (input_len 0) { input_len--; // 删除输入缓冲最后一位 LCD_Backspace(); } } break; case STATE_LOCKED: // 锁定期间不处理任何按键倒计时结束后由 tick 机制复位 break; default: break; } }状态机的执行入口在主循环里统一调用输入缓冲、输入长度都定义为全局变量这样各个状态之间共享数据不需要传递指针。这种写法在裸机工程里最常见也最容易被评审老师看懂。如果将来要加多用户密码把 input_buf 换成二维数组再加一个用户索引就能扩展。3.4 修改密码流程与操作反馈修改密码的入口放在待机界面按 B 键触发。流程分三步先要求输入旧密码验证通过后才能录入新密码新密码需要输入两遍两遍一致才写入 EEPROM写入成功后给出一秒的提示音和显示反馈。void Change_Password_Start(void) { // 修改密码前强制验证旧密码防止误操作或旁路 if (Verify_OldPassword()) { input_cnt 0; state STATE_INPUT_NEW; // 进入新密码录入 LCD_Clear(); LCD_ShowString(NEW PIN: ); } else { error_cnt; // 旧密码错误同样计入错误次数 LCD_ShowString(OLD PIN ERR); } }新密码两遍录入的逻辑不复杂但有一个细节第一次录入完按 # 确认后清空缓冲进入第二次录入第二遍确认时直接比较两遍缓冲。如果两遍不一致重置输入状态并提示重新开始而不是把第一遍缓存保留这样能避免用户记忆混乱。这个流程里最容易踩的坑是把修改密码做成可以无条件触发。如果任何人在待机界面按 B 都能改密码密码锁就等于形同虚设所以旧密码验证是硬门槛而且验证失败也计入错误次数。3.5 看门狗与主循环的耦合设计电子密码锁长期处于待机状态程序跑飞了没人知道所以独立看门狗是必须的。看门狗初始化配置如下void IWDG_Init(void) { IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); IWDG_SetPrescaler(IWDG_Prescaler_64); // 64 分频 IWDG_SetReload(0xFFF); // 重载值 4095 IWDG_ReloadCounter(); IWDG_Enable(); }喂狗的位置比看门狗本身的配置更关键。如果只在按键事件或状态切换时喂狗用户输入密码期间停顿超过一秒看门狗就会复位。通常的做法是把喂狗放在主循环的最开头每轮循环都执行一次不依赖任何业务分支while (1) { IWDG_ReloadCounter(); // 无条件喂狗放在主循环入口 uint8_t key Key_Get(); if (key ! 0xFF) StateMachine_Process(key); LCD_Refresh(); }开发调试阶段有个实用技巧先把看门狗整体禁用等所有功能都调通后再打开避免调试暂停时反复触发复位干扰思路。仿真和实物的运行速度不一样Proteus 里模拟 I2C 和 LCD 的耗时明显变长主循环周期比实物大好几倍喂狗间隔要留足余量我就是这么应对的。4. 仿真部署与常见问题排查Keil 与 Proteus 联调中的五个坑4.1 仿真前的工程配置与文件清单开始联调前先把三件事核对掉第一Keil 的 Device 选择要和 Proteus 原理图里放的芯片型号一致型号不同启动文件配置的寄存器地址对不上代码会在 SystemInit 阶段跑飞第二Proteus 的晶振参数要和代码里 RCC 配置匹配STM32F103 外部晶振通常填 8MHz第三仿真运行速度优先调成低比例开了 LCD 刷新和蜂鸣器之后 Proteus 会明显变慢按键响应看起来像死机其实只是仿真速度跟不上。这套工程的代码文件可以按下面的结构组织每个文件职责单一文件职责main.c主循环、外设初始化、喂狗key.c矩阵键盘扫描与消抖lcd1602.cLCD1602 显示驱动at24c02.cAT24C02 I2C 读写state_machine.c密码校验、错误锁定、修改密码状态机stm32f10x_it.c中断服务函数与 tick 计时4.2 问题一仿真启动后程序卡在 SystemInit现象Proteus 启动仿真程序指针停在 SystemInit 或 HardFault_HandlerKeil 软件仿真却一切正常。原因这一类现象十有八九是外部晶振没震起来。Proteus 里的晶振模型需要设置匹配的频率如果代码用 HSE 而原理图晶振参数没配好RCC 等待外部时钟就绪的循环会一直转不出去看起来就是卡死。解决先用内部时钟 HSI 把程序跑通确认逻辑无误后再切回外部晶振。RCC 配置要加上超时保护等待外部时钟的标志位循环加一个计数上限超时后自动切换回内部时钟这样即使晶振异常程序也能继续运行不会变成黑匣子。4.3 问题二按键按一次输入框出现两个字符现象按下数字键LCD 上一下子多出两个 *输入长度直接跳过一位。原因矩阵键盘扫描里用了等待松开的自旋但 Proteus 按键模型按下时存在抖动Key_Get 的双次消抖没有覆盖到释放阶段或者主循环轮询频率太高一次按下被拆成两个有效事件。解决把按键事件的生成条件改成“边沿触发”也就是只有在按键状态从按下变成松开的那一轮才返回键值。实现方式很直接全局记录上一次扫描值本次扫描值不同且本次为松开状态时才把缓存里的键值交给状态机其余情况一律返回 0xFF。4.4 问题三修改密码后重启仿真新密码丢失现象修改密码成功关闭仿真重新打开用新密码无法开锁旧密码反而有效。原因Proteus 里 AT24C02 模型的存储内容在仿真会话之间不一定保留尤其是直接关闭工程的情况。另外如果写入时序没留够 AT24C02 的写周期最后一个字节写入不完整重启后读取到的密码长度或内容异常系统回退到默认状态。解决两个办法叠加。第一上电初始化时增加默认密码填充逻辑读到的长度不是 6 或内容校验失败时重写默认密码 123456 并清零错误计数保证每次仿真起始状态确定。第二修改密码的写入流程必须带回读校验Password_Save 返回失败时界面直接提示写入错误不给用户造成保存成功的假象。// 上电时修复非法 EEPROM 状态 void Storage_CheckAndInit(void) { uint8_t len EEPROM_ReadByte(PW_LEN_ADDR); if (len ! 6) // 非法长度说明存储区损坏或从未写入 { const uint8_t default_pw[6] {1,2,3,4,5,6}; Password_Save(default_pw, 6); EEPROM_WriteByte(PW_ERR_ADDR, 0); EEPROM_WriteByte(PW_LOCK_ADDR, 0); } }4.5 问题四开启看门狗后系统在仿真中反复复位现象代码在 Keil 里单步正常挂到 Proteus 后每隔几秒屏幕重新初始化像是系统不断重启。原因Proteus 模拟速度比真实芯片慢得多LCD 忙等待、EEPROM 写延时和蜂鸣器操作把单次主循环的时间拉长喂狗周期超过了看门狗超时值。仿真模式下用户输入停顿一秒以上也会触发这个问题。解决把喂狗从业务分支挪到主循环入口保证每轮都执行。然后按仿真实际耗时把看门狗超时从 1 秒放宽到 2 秒64 分频下把重载值从 0xFFF 改成更大值。更稳妥的做法是开发阶段先禁用看门狗全部功能验收通过后最后再打开用最短时间把风险面收敛。4.6 问题五LCD 显示乱码或第二行黑影现象LCD 前几个字符正常往后越显示越乱或者第二行出现一排黑色方块屏幕整体发花。原因LCD1602 初始化时序不满足。常见的做法是用固定延时代替忙标志查询仿真环境运行速度变化时固定延时不够就会丢数据。另一个原因是 EN 引脚脉冲宽度不够LCD 模块的时钟边沿采不到数据。解决把写命令和写数据的函数统一改成忙标志查询方式先读 BF 标志为 1 就继续等待为 0 再写下一个字节。同时核对 Proteus 里 LCD1602 模型的时序参数把 EN 高电平脉冲宽度保持在 1ms 以上。这个修改在实物和仿真上都适用是 LCD 驱动的标准写法。5. 验收与答辩测试用例矩阵与评审演示脚本5.1 功能测试用例与验收标准验收不能只看“能开锁”要按功能点逐条过。下面这份测试矩阵是我实际用过的版本直接照着执行就可以用例编号操作步骤预期结果T01上电不输入任何按键屏幕显示待机画面无乱码无异常T02输入正确 6 位密码后按 #继电器吸合LED 点亮5 秒后自动断开T03连续输入错误密码两次每次提示剩余次数第三次直接锁定 30 秒T04锁定期间按任意键屏幕保持锁定提示按键不响应T05输入过程中按 *删除输入缓冲最后一位星号同步减少T06按 B 修改密码两次输入一致提示保存成功断电重启后新密码生效T07在 LOCKED 状态下断电再上电系统仍然处于锁定状态不能通过重启绕过5.2 答辩演示脚本演示顺序建议按风险从低到高排第一步先演示正常开锁这是主功能稳定得分第二步演示错误次数锁定和倒计时恢复展示状态机边界处理能力第三步演示修改密码和断电重启证明存储设计经得起检验第四步展示代码文件结构和模块分层让评审看到工程能力而不只是功能实现。整个过程控制在五分钟以内不要在一次演示里反复试错评委最怕看到的就是现场按了五次密码都开不了锁。5.3 评审老师最常追问的三个问题“为什么用硬件 I2C 而不用软件模拟”可以答硬件 I2C 不占 CPU 轮询时间AT24C02 是总线上唯一的从设备不存在总线抢占问题硬件时序由外设状态机保证比软件模拟稳定。“密码明文存在 EEPROM 里安全性怎么保证”可以答当前方案重功能验证扩展上可以在密码写入前做异或混淆或者只存密码的散列值这两种改法都不影响状态机结构。“锁定 30 秒期间断电再上电锁定会不会被绕过”可以答错误次数和锁定标志都写在 EEPROM掉电不清零重新上电后初始化流程会读取锁定标志停留在 LOCKED 状态直到倒计时结束。我还记得第一次做类似项目时就是没做存储状态的自检答辩现场演示修改密码后重启直接变回出厂密码当时对着键盘反复按场面很尴尬。那之后我每次交付仿真工程都强制自己走一遍“修改密码 → 回读校验 → 断电重启 → 再验证”的完整链路确认存储状态在掉电前后一致才敢说完成。这套基于 STM32 的电子密码锁仿真和源码整体就是按“状态机正确、存储可靠、边界可验证”这三条标准组织起来的希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

容器镜像加载原理:分层、联合挂载与写时复制机制详解

容器镜像加载原理:分层、联合挂载与写时复制机制详解

1. 镜像加载到底在加载什么很多人第一次接触容器技术时,都会有一个直觉性的误解:以为镜像就是一个压缩包,运行容器就是把压缩包解压到某个目录里,然后启动里面的程序。这个理解不能算全错,但它漏掉了最关键的一层——镜…

📅 2026/10/20 19:55:20
AI时代的内容焦虑:从“学生用AI讲PPT”到把AI当陪练

AI时代的内容焦虑:从“学生用AI讲PPT”到把AI当陪练

这学期我旁听了一门课,最后一堂是学生展示。A同学上台,打开了一份排版精致、逻辑工整的PPT,页脚还带着AI生成标记。他念了一页,停顿,再念一页,整个教室里只有他的声音和翻页声。老师问了一个问题&#xff1…

📅 2026/10/20 19:55:20
Ascend C算子开发实战:从LayerNorm融合到NPU性能调优

Ascend C算子开发实战:从LayerNorm融合到NPU性能调优

我最早接触 Ascend C 算子开发,是因为跑模型时被一个简单的 LayerNorm 卡住了性能。框架自带的算子能用,但融合度不够,读一遍数据做均值,再读一遍做方差,最后再来一遍归一化,Global Memory 被反复读写&…

📅 2026/10/20 19:55:20
MORE NEWS

更多资讯

📰

servicestack鸿蒙化适配:Flutter强类型API与消息路由跨端迁移实践

最近在做 Flutter 跨端项目时,需要把一个基于 servicestack 的旧应用底层能力迁移到鸿蒙生态里。这个库在 Dart/Flutter 端的核心价值是强类型 API 客户端和 Message-based 消息路由,它把服务端接口封装成了强类型调用,让前端不用整天拼字符串…

📰

工业组态屏选型与通讯调试全解析:从硬件到组态实战

设备运行好好的,操作工却跑过来喊“屏上数字不动了”,这是我在现场听得最多的一句话。很多人误以为“工业组态屏就是一块高级点的触摸屏”,实际上它的角色远不止显示——它是操作员与PLC之间的翻译官、数据中转站,也是整个产线的第…

📰

四款AI论文生成工具组合实战:从选题到初稿效率翻倍

写论文这件事,卡住人的往往不是查资料,而是从零到一那个从无到有的空白期。面对一屏空白文档,脑子里翻涌着几十篇文献,却不知道第一句话怎么写——这种情况我见过太多次,自己也体验过太多次。后来我开始长期试用各类AI…

📰

AI选人落地全流程:从经验直觉到数据驱动的识别体系

招聘这行做了十几年,我发现一个很扎心的现象:很多业务负责人嘴上说“我相信自己的直觉”,但年底复盘试用期淘汰率的时候,往往说不出一个像样的理由。我自己就经历过一次惨痛的复盘会——某部门一年招了10个人,3个没过试…

📰

Ubuntu+VS Code搭建C++开发环境:从工具链到调试的完整指南

1. 为什么选择 Ubuntu VS Code 搭建 C 开发环境1.1 这套组合到底解决了什么问题很多刚接触 Linux 下 C 开发的朋友,第一反应往往是"我该用哪个 IDE"。有人推荐重量级的集成环境,有人推荐纯命令行加 Vim,还有人干脆在 Windows 上写…

📰

企业微信回调验证与AES加解密:.NET开发者接入指南

接手过几个企业微信自建应用的项目,每次新人对接时几乎都会卡在同一个地方:管理后台保存“接收消息服务器”配置时提示URL验证失败,或者明明验证过了,消息却一直推送不进来。这个环节看着只是填几个参数,背后实际上是一…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬