嵌入式设计大赛(沁恒应用赛道)——从零到一:基于CH32V307的智能门锁实战开发笔记

张开发
2026/4/9 6:41:00 15 分钟阅读

分享文章

嵌入式设计大赛(沁恒应用赛道)——从零到一:基于CH32V307的智能门锁实战开发笔记
1. 项目背景与硬件选型第一次接触嵌入式开发的朋友可能会觉得智能门锁是个高大上的项目其实拆解开来无非就是感知-决策-执行三个核心环节。这次我们选用沁恒的CH32V307单片机作为主控这颗国产RISC-V芯片性价比极高主频144MHz内置256KB Flash和64KB RAM完全能满足智能门锁的需求。硬件选型时我主要考虑了几个关键点功耗控制门锁需要长期待机CH32V307的低功耗模式很实用外设接口需要足够多的UART和GPIO来连接各类模块开发生态沁恒提供的开发工具链完善资料丰富实际采购清单如下主控板CH32V307评估板约80元指纹模块AS608约60元RFID读卡器RC522约25元语音模块SYN6288约35元物联网模块ESP8266约15元电机驱动SG90舵机约8元2. 开发环境搭建新手最容易卡在环境配置这一步我推荐使用MounRiver Studio这个IDE对CH32系列支持很好。安装时注意这几个关键点下载WCH-Link调试驱动官网提供安装RISC-V GCC工具链配置工程时选择CH32V307型号遇到下载失败时可以尝试检查USB线是否接触良好按住板子的BOOT键再上电进入下载模式更新WCH-Link固件// 最简单的LED测试程序 #include debug.h void GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); } int main(void) { GPIO_Config(); while(1) { GPIO_WriteBit(GPIOA, GPIO_Pin_0, 1); Delay_Ms(500); GPIO_WriteBit(GPIOA, GPIO_Pin_0, 0); Delay_Ms(500); } }3. 基础外设驱动开发3.1 GPIO控制逻辑门锁需要控制舵机转动这里用到了PWM输出。CH32V307的定时器功能强大我们以TIM1为例void PWM_Init(u16 arr, u16 psc) { GPIO_InitTypeDef GPIO_InitStructure {0}; TIM_OCInitTypeDef TIM_OCInitStructure {0}; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE); // PA8作为PWM输出 GPIO_InitStructure.GPIO_Pin GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); TIM_TimeBaseInitStructure.TIM_Period arr; TIM_TimeBaseInitStructure.TIM_Prescaler psc; TIM_TimeBaseInitStructure.TIM_ClockDivision 0; TIM_TimeBaseInitStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1, TIM_TimeBaseInitStructure); TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse 0; TIM_OCInitStructure.TIM_OCPolarity TIM_OCPolarity_High; TIM_OC1Init(TIM1, TIM_OCInitStructure); TIM_CtrlPWMOutputs(TIM1, ENABLE); TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM1, ENABLE); TIM_Cmd(TIM1, ENABLE); }3.2 串口通信配置指纹模块、语音模块都需要UART通信这里以USART2为例void USART2_Init(u32 baudrate) { GPIO_InitTypeDef GPIO_InitStructure {0}; USART_InitTypeDef USART_InitStructure {0}; NVIC_InitTypeDef NVIC_InitStructure {0}; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // PA2-TX, PA3-RX GPIO_InitStructure.GPIO_Pin GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_Init(GPIOA, GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, GPIO_InitStructure); USART_InitStructure.USART_BaudRate baudrate; 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(USART2, USART_InitStructure); NVIC_InitStructure.NVIC_IRQChannel USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority 1; NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure); USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); USART_Cmd(USART2, ENABLE); }4. 功能模块集成4.1 指纹识别实现AS608指纹模块的通信协议比较特殊需要严格按照数据包格式// 指纹录入流程 void Fingerprint_Enroll(u8 id) { u8 cmd[12] {0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x03,0x01,0x00,0x05}; USART_SendData(USART2, cmd, 12); // 获取图像 Delay_Ms(200); cmd[9] 0x02; cmd[11] 0x07; USART_SendData(USART2, cmd, 12); // 生成特征 Delay_Ms(200); cmd[9] 0x05; cmd[11] 0x0A; USART_SendData(USART2, cmd, 12); // 存储特征 Delay_Ms(200); }4.2 物联网远程控制ESP8266连接OneNET平台的几个关键步骤配置WiFi连接void ESP8266_WiFiConfig(char *ssid, char *pwd) { USART_SendString(USART3, ATCWMODE1\r\n); Delay_Ms(1000); USART_SendString(USART3, ATCWJAP\); USART_SendString(USART3, ssid); USART_SendString(USART3, \,\); USART_SendString(USART3, pwd); USART_SendString(USART3, \\r\n); Delay_Ms(5000); }MQTT协议连接void ESP8266_MQTTConnect(char *productID, char *deviceName, char *apiKey) { char cmd[256]; sprintf(cmd, ATMQTTUSERCFG0,1,\%s\,\%s\,\%s\,0,0,\\\r\n, deviceName, productID, apiKey); USART_SendString(USART3, cmd); Delay_Ms(1000); USART_SendString(USART3, ATMQTTCONN0,\mqtts.heclouds.com\,1883,1\r\n); Delay_Ms(3000); }5. 系统整合与优化5.1 状态机设计智能门锁需要处理多种输入事件我采用了状态机架构typedef enum { LOCK_STATE_IDLE, LOCK_STATE_PASSWORD, LOCK_STATE_FINGERPRINT, LOCK_STATE_RFID, LOCK_STATE_REMOTE } LockState; void Lock_StateMachine(void) { static LockState state LOCK_STATE_IDLE; switch(state) { case LOCK_STATE_IDLE: if(Key_Pressed()) state LOCK_STATE_PASSWORD; else if(Fingerprint_Detected()) state LOCK_STATE_FINGERPRINT; else if(RFID_Detected()) state LOCK_STATE_RFID; else if(Remote_Cmd()) state LOCK_STATE_REMOTE; break; case LOCK_STATE_PASSWORD: if(Password_Verify()) { Lock_Open(); state LOCK_STATE_IDLE; } break; // 其他状态处理... } }5.2 低功耗优化通过合理配置时钟和休眠模式待机电流可以控制在1mA以下void Enter_LowPowerMode(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); // 唤醒后重新初始化时钟 SystemInit(); GPIO_Config(); USART_Config(); }6. 开发经验分享在调试指纹模块时发现有时响应特别慢后来发现是波特率误差导致。CH32V307的USART时钟需要精确配置// 对于144MHz主频115200波特率的精确配置 USART_InitStructure.USART_BaudRate 115200; RCC_USARTCLKConfig(RCC_USARTCLKSource_PCLK1); RCC_PCLK1Config(RCC_HCLK_Div4); // PCLK1 36MHz另一个坑是ESP8266的固件版本最初用的AT固件不稳定后来刷了安信可的定制固件后问题解决。建议开发时准备USB-TTL工具单独调试每个模块重要数据用printf输出到串口调试助手复杂逻辑先用伪代码梳理流程最后分享一个实用技巧用Excel管理引脚分配避免后期混乱功能模块引脚复用功能备注指纹模块RXPA2USART2_TX需交叉连接语音模块TXPA3USART2_RX舵机控制PA8TIM1_CH1PWM输出

更多文章