From 84d8874a38d228d6b3a052cccac416c6440c9367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BA=AA=E7=94=B0=E9=87=8E?= Date: Thu, 21 May 2026 08:07:16 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=88=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Hardware/Attendance.c | 23 +++++++++++++++++ Hardware/Attendance.h | 58 +++++++++++++++++++++++++++++------------- Hardware/Buzzer_LED.c | 1 + Hardware/Buzzer_LED.h | 1 + Hardware/Crypto.c | 5 ++++ Hardware/Crypto.h | 3 +++ Hardware/DS1302.c | 9 +++++++ Hardware/DS1302.h | 5 ++++ Hardware/K210_USART.c | 4 +++ Hardware/K210_USART.h | 4 +++ Hardware/LightSensor.c | 4 +++ Hardware/LightSensor.h | 12 ++++++--- Hardware/OLED.c | 17 +++++++++++++ Hardware/OLED.h | 9 +++++++ Hardware/Serial.c | 5 ++++ Hardware/Serial.h | 16 ++++++++---- Hardware/aes.c | 18 +++++++++++++ Hardware/aes.h | 6 +++++ Hardware/aes_fixed.c | 13 ++++++++++ Hardware/aes_fixed.h | 6 +++++ Hardware/base64.c | 3 +++ Hardware/base64.h | 2 ++ Hardware/esp8266.c | 15 +++++++++++ Hardware/esp8266.h | 9 +++++++ System/Debug.c | 6 +++++ System/Debug.h | 2 ++ System/Delay.c | 5 ++++ System/Delay.h | 5 ++++ User/main.c | 18 +++++++++++++ User/stm32f10x_conf.h | 1 + User/stm32f10x_it.c | 2 ++ User/stm32f10x_it.h | 11 ++++++++ 32 files changed, 271 insertions(+), 27 deletions(-) diff --git a/Hardware/Attendance.c b/Hardware/Attendance.c index 7e1405f..83503e9 100644 --- a/Hardware/Attendance.c +++ b/Hardware/Attendance.c @@ -32,6 +32,7 @@ static AttendanceRecord attendance_records[MAX_ATTENDANCE_RECORDS]; static uint16_t record_count = 0; static uint32_t total_attendance_count = 0; // 总考勤人次 +/* 函数作用:根据当前小时和分钟查找所处的考勤时间段。 */ static int8_t Attendance_FindTimeSlot(uint8_t hour, uint8_t minute) { uint16_t current_minutes = hour * 60 + minute; @@ -57,6 +58,7 @@ static int8_t Attendance_FindTimeSlot(uint8_t hour, uint8_t minute) /** * @brief 初始化考勤模块 */ +/* 函数作用:初始化考勤记录、时间段配置和今日已签到缓存。 */ void Attendance_Init(void) { record_count = 0; @@ -81,6 +83,7 @@ void Attendance_Init(void) /** * @brief 清空今日签到缓存 */ +/* 函数作用:清空当前时段的服务器已签到学号缓存。 */ void Attendance_ClearCache(void) { cached_id_count = 0; @@ -93,6 +96,7 @@ void Attendance_ClearCache(void) /** * @brief 添加学号到缓存 */ +/* 函数作用:把指定学号加入当前考勤时段的本地查重缓存。 */ void Attendance_AddToCache(const char* student_id) { int8_t current_slot = Attendance_GetCurrentTimeSlot(); @@ -132,6 +136,7 @@ void Attendance_AddToCache(const char* student_id) * @brief 在本地缓存中查重 * @retval 1=在缓存中找到(重复), 0=未找到 */ +/* 函数作用:检查指定学号是否已存在于当前时段缓存中。 */ uint8_t Attendance_IsDuplicateInCache(const char* student_id) { int8_t current_slot = Attendance_GetCurrentTimeSlot(); @@ -158,6 +163,7 @@ uint8_t Attendance_IsDuplicateInCache(const char* student_id) * @brief 从服务器加载今日已签到记录到缓存 * @retval 加载的记录数量 */ +/* 函数作用:下载当前时段已签到学号列表并写入本地查重缓存。 */ uint8_t Attendance_LoadTodayRecordsFromServer(void) { char slot_start[8]; @@ -221,6 +227,7 @@ uint8_t Attendance_LoadTodayRecordsFromServer(void) * @param slots 新的时间段配置数组 * @param count 时间段数量 */ +/* 函数作用:用服务端下发的新时间段数组替换本地时间段配置。 */ void Attendance_UpdateTimeSlots(TimeSlot* slots, uint8_t count) { if (count > MAX_TIME_SLOT_COUNT) { @@ -249,6 +256,7 @@ void Attendance_UpdateTimeSlots(TimeSlot* slots, uint8_t count) * @param json_str JSON字符串(格式:{"time_slots":[{"enabled":true,"start_time":"08:00",...}]}) * @retval 成功解析的时间段数量 */ +/* 函数作用:从服务端同步 JSON 中解析时间段配置并应用到本地。 */ uint8_t Attendance_ParseTimeSlotsJSON(const char* json_str) { TimeSlot temp_slots[MAX_TIME_SLOT_COUNT]; @@ -386,6 +394,7 @@ uint8_t Attendance_ParseTimeSlotsJSON(const char* json_str) * @param hour 小时 (0-23) * @param minute 分钟 (0-59) */ +/* 函数作用:更新考勤模块当前时间,并在跨时段时清空查重缓存。 */ void Attendance_SetCurrentTime(uint8_t hour, uint8_t minute) { int8_t old_slot = Attendance_FindTimeSlot(current_hour, current_minute); @@ -405,6 +414,7 @@ void Attendance_SetCurrentTime(uint8_t hour, uint8_t minute) * @brief 获取当前所处的考勤时段 * @retval 时段编号 (0-N),如果不在任何时段内则返回 -1 */ +/* 函数作用:返回当前时间对应的考勤时段索引。 */ int8_t Attendance_GetCurrentTimeSlot(void) { return Attendance_FindTimeSlot(current_hour, current_minute); @@ -415,6 +425,7 @@ int8_t Attendance_GetCurrentTimeSlot(void) * @param start_time 输出:开始时间(格式"HH:MM") * @param end_time 输出:结束时间(格式"HH:MM") */ +/* 函数作用:输出当前考勤时段的开始和结束时间字符串。 */ void Attendance_GetCurrentSlotTime(char* start_time, char* end_time) { int8_t current_slot = Attendance_GetCurrentTimeSlot(); @@ -438,6 +449,7 @@ void Attendance_GetCurrentSlotTime(char* start_time, char* end_time) * @param student_id 学生学号 * @retval 1=服务器显示已签到(重复), 0=未签到或查询失败 */ +/* 函数作用:向服务器查询指定学生在当前时段是否已经签到。 */ uint8_t Attendance_IsDuplicateOnServer(const char* student_id) { char slot_start[8]; @@ -458,6 +470,7 @@ uint8_t Attendance_IsDuplicateOnServer(const char* student_id) * @param student_id 学生学号 * @retval 1=重复, 0=不重复 */ +/* 函数作用:检查指定学生是否已在当前时段产生本地重复签到。 */ uint8_t Attendance_IsDuplicate(const char* student_id) { int8_t current_slot = Attendance_GetCurrentTimeSlot(); @@ -485,6 +498,7 @@ uint8_t Attendance_IsDuplicate(const char* student_id) * @param result 人脸识别结果 * @retval 考勤状态 */ +/* 函数作用:校验识别结果、查重并生成一条待同步考勤记录。 */ AttendanceStatus Attendance_ProcessFaceResult(FaceRecognitionResult* result) { // 1. 检查识别是否成功 @@ -598,6 +612,7 @@ AttendanceStatus Attendance_ProcessFaceResult(FaceRecognitionResult* result) /** * @brief 清空所有考勤记录 */ +/* 函数作用:清空当前缓存的考勤记录,但保留累计统计值。 */ void Attendance_ClearRecords(void) { record_count = 0; @@ -608,6 +623,7 @@ void Attendance_ClearRecords(void) /** * @brief 获取累计考勤总数 */ +/* 函数作用:返回系统启动以来累计处理的成功考勤次数。 */ uint16_t Attendance_GetTotalCount(void) { return total_attendance_count; @@ -616,6 +632,7 @@ uint16_t Attendance_GetTotalCount(void) /** * @brief 获取当前缓存中的记录数 */ +/* 函数作用:返回当前本地缓存中的考勤记录数量。 */ uint16_t Attendance_GetActiveCount(void) { return record_count; @@ -625,6 +642,7 @@ uint16_t Attendance_GetActiveCount(void) * @brief 获取待同步记录的数量(PENDING或FAILED状态) * @retval 待同步记录数 */ +/* 函数作用:统计当前等待上传或需要重试上传的记录数量。 */ uint16_t Attendance_GetPendingCount(void) { uint16_t count = 0; @@ -644,6 +662,7 @@ uint16_t Attendance_GetPendingCount(void) * @param index 输出参数,返回记录的索引 * @retval 记录指针,如果没有待同步记录则返回NULL */ +/* 函数作用:按优先级取出下一条可上传或可重试的考勤记录。 */ AttendanceRecord* Attendance_GetNextPendingRecord(uint16_t* index) { uint32_t current_time = Get_Time_ms(); @@ -690,6 +709,7 @@ AttendanceRecord* Attendance_GetNextPendingRecord(uint16_t* index) * @param index 记录索引 * @param status 新的同步状态 */ +/* 函数作用:更新指定考勤记录的服务器同步状态。 */ void Attendance_MarkSyncStatus(uint16_t index, SyncStatus status) { if (index < record_count) @@ -711,6 +731,7 @@ void Attendance_MarkSyncStatus(uint16_t index, SyncStatus status) * @brief 增加记录的重试计数 * @param index 记录索引 */ +/* 函数作用:增加指定记录的上传重试次数。 */ void Attendance_IncrementRetry(uint16_t index) { if (index < record_count) @@ -724,6 +745,7 @@ void Attendance_IncrementRetry(uint16_t index) /** * @brief 将所有FAILED记录重置为PENDING(用于网络恢复后) */ +/* 函数作用:网络恢复后把失败记录重新置为待同步状态。 */ void Attendance_ResetFailedRecords(void) { uint16_t reset_count = 0; @@ -748,6 +770,7 @@ void Attendance_ResetFailedRecords(void) * @param index 记录索引 * @retval 记录指针,如果索引无效则返回NULL */ +/* 函数作用:根据数组索引返回对应考勤记录指针。 */ AttendanceRecord* Attendance_GetRecordByIndex(uint16_t index) { if (index < record_count) diff --git a/Hardware/Attendance.h b/Hardware/Attendance.h index 8df9563..8ef4ac8 100644 --- a/Hardware/Attendance.h +++ b/Hardware/Attendance.h @@ -51,29 +51,51 @@ typedef struct { } TimeSlot; // 函数声明 +// 函数作用:初始化考勤模块的记录缓存、时间段配置和运行状态。 void Attendance_Init(void); -void Attendance_SetCurrentTime(uint8_t hour, uint8_t minute); // 设置当前时间 -void Attendance_UpdateTimeSlots(TimeSlot* slots, uint8_t count); // 更新时间段配置(从服务器下载后调用) -uint8_t Attendance_ParseTimeSlotsJSON(const char* json_str); // 从JSON字符串解析时间段配置 +// 函数作用:设置考勤模块当前使用的小时和分钟,用于判断当前是否处于考勤时段。 +void Attendance_SetCurrentTime(uint8_t hour, uint8_t minute); +// 函数作用:使用服务器下发的时间段数组更新本地考勤时间段配置。 +void Attendance_UpdateTimeSlots(TimeSlot* slots, uint8_t count); +// 函数作用:从服务器返回的 JSON 字符串中解析时间段配置并更新本地列表。 +uint8_t Attendance_ParseTimeSlotsJSON(const char* json_str); +// 函数作用:处理 K210 人脸识别结果,判断是否可打卡并生成考勤记录。 AttendanceStatus Attendance_ProcessFaceResult(FaceRecognitionResult* result); +// 函数作用:检查指定学号在当前考勤时段内是否已经打卡。 uint8_t Attendance_IsDuplicate(const char* student_id); -uint8_t Attendance_IsDuplicateOnServer(const char* student_id); // 服务器端查重 -void Attendance_GetCurrentSlotTime(char* start_time, char* end_time); // 获取当前时段时间 -uint8_t Attendance_LoadTodayRecordsFromServer(void); // 新增:从服务器加载今日签到记录 -uint8_t Attendance_IsDuplicateInCache(const char* student_id); // 新增:在本地缓存中查重 -void Attendance_AddToCache(const char* student_id); // 新增:添加学号到缓存 -void Attendance_ClearCache(void); // 新增:清空缓存 +// 函数作用:通过服务器接口检查指定学号在当前时段是否已经打卡。 +uint8_t Attendance_IsDuplicateOnServer(const char* student_id); +// 函数作用:获取当前考勤时段的开始和结束时间字符串。 +void Attendance_GetCurrentSlotTime(char* start_time, char* end_time); +// 函数作用:从服务器加载今日已签到记录,用于设备重启后恢复去重缓存。 +uint8_t Attendance_LoadTodayRecordsFromServer(void); +// 函数作用:在本地今日签到缓存中检查指定学号是否已存在。 +uint8_t Attendance_IsDuplicateInCache(const char* student_id); +// 函数作用:把指定学号加入本地今日签到缓存。 +void Attendance_AddToCache(const char* student_id); +// 函数作用:清空本地今日签到缓存。 +void Attendance_ClearCache(void); +// 函数作用:清空本地保存的考勤记录和同步状态。 void Attendance_ClearRecords(void); -uint16_t Attendance_GetTotalCount(void); // 获取累计考勤总数 -uint16_t Attendance_GetActiveCount(void); // 获取当前缓存记录数 -int8_t Attendance_GetCurrentTimeSlot(void); // 获取当前时段编号(-1表示不在考勤时段) +// 函数作用:返回累计考勤记录总数。 +uint16_t Attendance_GetTotalCount(void); +// 函数作用:返回当前本地缓存中的有效记录数量。 +uint16_t Attendance_GetActiveCount(void); +// 函数作用:返回当前所在考勤时段编号,-1 表示不在任意考勤时段。 +int8_t Attendance_GetCurrentTimeSlot(void); // 数据同步相关函数 -uint16_t Attendance_GetPendingCount(void); // 获取待同步记录数量(PENDING状态) -AttendanceRecord* Attendance_GetNextPendingRecord(uint16_t* index); // 获取下一个待同步记录 -void Attendance_MarkSyncStatus(uint16_t index, SyncStatus status); // 更新记录的同步状态 -void Attendance_IncrementRetry(uint16_t index); // 增加重试计数 -AttendanceRecord* Attendance_GetRecordByIndex(uint16_t index); // 按索引获取记录 -void Attendance_ResetFailedRecords(void); // 将所有FAILED记录重置为PENDING +// 函数作用:统计当前处于待同步状态的考勤记录数量。 +uint16_t Attendance_GetPendingCount(void); +// 函数作用:查找下一条待同步记录,并通过 index 返回其在缓存中的位置。 +AttendanceRecord* Attendance_GetNextPendingRecord(uint16_t* index); +// 函数作用:按缓存索引更新指定考勤记录的同步状态。 +void Attendance_MarkSyncStatus(uint16_t index, SyncStatus status); +// 函数作用:按缓存索引增加指定考勤记录的同步重试次数。 +void Attendance_IncrementRetry(uint16_t index); +// 函数作用:按缓存索引返回指定考勤记录指针。 +AttendanceRecord* Attendance_GetRecordByIndex(uint16_t index); +// 函数作用:将所有同步失败记录重置为待同步,便于后续重新上传。 +void Attendance_ResetFailedRecords(void); #endif diff --git a/Hardware/Buzzer_LED.c b/Hardware/Buzzer_LED.c index 7504474..7867f30 100644 --- a/Hardware/Buzzer_LED.c +++ b/Hardware/Buzzer_LED.c @@ -1,5 +1,6 @@ #include "Buzzer_LED.h" +/* 函数作用:初始化蜂鸣器、成功指示灯和板载状态 LED 对应 GPIO。 */ void Buzzer_LED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; diff --git a/Hardware/Buzzer_LED.h b/Hardware/Buzzer_LED.h index 67ce257..9a39c55 100644 --- a/Hardware/Buzzer_LED.h +++ b/Hardware/Buzzer_LED.h @@ -14,6 +14,7 @@ #define LED_STATUS_OFF() GPIO_SetBits(GPIOC, GPIO_Pin_13) // 就绪后:熄灭 // 声明初始化函数 +// 函数作用:初始化成功指示灯、状态灯和蜂鸣器相关 GPIO 输出状态。 void Buzzer_LED_Init(void); #endif diff --git a/Hardware/Crypto.c b/Hardware/Crypto.c index ffef1d6..c6aa1ab 100644 --- a/Hardware/Crypto.c +++ b/Hardware/Crypto.c @@ -23,6 +23,7 @@ static const uint8_t AES_IV[16] = { static struct AES_ctx aes_ctx; +/* 函数作用:初始化 AES 加密上下文。 */ void Crypto_Init(void) { // 初始化AES上下文(使用CBC模式) @@ -33,6 +34,7 @@ void Crypto_Init(void) * @brief PKCS#7填充 * 将数据填充到16字节的倍数 */ +/* 函数作用:为 JSON 明文追加 PKCS#7 填充。 */ static uint32_t pkcs7_pad(uint8_t* data, uint32_t data_len, uint32_t buffer_size) { // 计算需要填充的字节数 @@ -52,6 +54,7 @@ static uint32_t pkcs7_pad(uint8_t* data, uint32_t data_len, uint32_t buffer_size return data_len + padding_len; } +/* 函数作用:移除解密结果中的 PKCS#7 填充。 */ static uint32_t pkcs7_unpad(uint8_t* data, uint32_t data_len) { uint8_t padding_len; @@ -75,6 +78,7 @@ static uint32_t pkcs7_unpad(uint8_t* data, uint32_t data_len) return data_len - padding_len; } +/* 函数作用:将 JSON 字符串 AES-CBC 加密并 Base64 编码输出。 */ uint32_t Crypto_EncryptJSON(const char* json_data, char* encrypted_output) { uint32_t json_len = strlen(json_data); @@ -121,6 +125,7 @@ uint32_t Crypto_EncryptJSON(const char* json_data, char* encrypted_output) return encoded_len; } +/* 函数作用:将 Base64 密文解码并 AES-CBC 解密为 JSON 字符串。 */ uint32_t Crypto_DecryptJSON(const char* encrypted_base64, char* plain_output, uint32_t output_size) { uint32_t encrypted_len; diff --git a/Hardware/Crypto.h b/Hardware/Crypto.h index 076a921..116fca7 100644 --- a/Hardware/Crypto.h +++ b/Hardware/Crypto.h @@ -12,6 +12,7 @@ * * 注意:encrypted_output缓冲区至少需要 (strlen(json_data) / 16 + 1) * 16 * 4/3 + 10 字节 */ +// 函数作用:对 JSON 字符串执行 AES-CBC 加密和 Base64 编码,生成可上传服务端的密文。 uint32_t Crypto_EncryptJSON(const char* json_data, char* encrypted_output); /** @@ -21,6 +22,7 @@ uint32_t Crypto_EncryptJSON(const char* json_data, char* encrypted_output); * @param output_size 输出缓冲区大小 * @return 明文字节数,失败返回0 */ +// 函数作用:对 Base64 编码的 AES-CBC 密文进行解码和解密,输出 JSON 明文。 uint32_t Crypto_DecryptJSON(const char* encrypted_base64, char* plain_output, uint32_t output_size); /** @@ -34,6 +36,7 @@ uint32_t Crypto_DecryptJSON(const char* encrypted_base64, char* plain_output, ui * @brief 初始化加密模块 * 设置密钥和IV(初始化向量) */ +// 函数作用:初始化加密模块使用的固定密钥、IV 和底层 AES 上下文。 void Crypto_Init(void); #endif // _CRYPTO_H_ diff --git a/Hardware/DS1302.c b/Hardware/DS1302.c index 3d8f4b5..09ecdc4 100644 --- a/Hardware/DS1302.c +++ b/Hardware/DS1302.c @@ -33,6 +33,7 @@ #define DEC_TO_BCD(dec) ((((dec) / 10) << 4) | ((dec) % 10)) // 微秒延时 +/* 函数作用:为 DS1302 时序提供简短的微秒级软件延时。 */ static void delay_us(uint32_t us) { volatile uint32_t i; @@ -44,6 +45,7 @@ static void delay_us(uint32_t us) /** * @brief 配置IO口为输出 */ +/* 函数作用:把 DS1302 数据引脚配置为推挽输出模式。 */ static void DS1302_DATAOUT_init(void) { GPIO_InitTypeDef GPIO_InitStructure; @@ -56,6 +58,7 @@ static void DS1302_DATAOUT_init(void) /** * @brief 配置IO口为输入 */ +/* 函数作用:把 DS1302 数据引脚配置为浮空输入模式。 */ static void DS1302_DATAINPUT_init(void) { GPIO_InitTypeDef GPIO_InitStructure; @@ -67,6 +70,7 @@ static void DS1302_DATAINPUT_init(void) /** * @brief DS1302初始化 */ +/* 函数作用:初始化 DS1302 的时钟、数据和使能引脚。 */ void DS1302_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; @@ -92,6 +96,7 @@ void DS1302_Init(void) * @brief 向DS1302发送一字节数据(根据demo代码) * @param data 要发送的数据 */ +/* 函数作用:按 DS1302 时序向芯片写入一个字节。 */ static void DS1302_write_onebyte(uint8_t data) { uint8_t count = 0; @@ -119,6 +124,7 @@ static void DS1302_write_onebyte(uint8_t data) * @param address 寄存器地址 * @param data 数据 */ +/* 函数作用:向 DS1302 指定寄存器写入一个字节数据。 */ void DS1302_WriteByte(uint8_t address, uint8_t data) { CE_L; @@ -141,6 +147,7 @@ void DS1302_WriteByte(uint8_t address, uint8_t data) * @param address 寄存器地址 * @retval 读取到的数据 */ +/* 函数作用:从 DS1302 指定寄存器读取一个字节数据。 */ uint8_t DS1302_ReadByte(uint8_t address) { uint8_t count = 0; @@ -184,6 +191,7 @@ uint8_t DS1302_ReadByte(uint8_t address) * @brief 设置DS1302时间 * @param time 时间结构体指针 */ +/* 函数作用:把时间结构体转换为 BCD 后写入 DS1302。 */ void DS1302_SetTime(DS1302_Time* time) { // 关闭写保护 @@ -206,6 +214,7 @@ void DS1302_SetTime(DS1302_Time* time) * @brief 读取DS1302时间 * @param time 时间结构体指针 */ +/* 函数作用:读取 DS1302 时间寄存器并转换为十进制时间结构体。 */ void DS1302_GetTime(DS1302_Time* time) { uint8_t read_time[7]; diff --git a/Hardware/DS1302.h b/Hardware/DS1302.h index f65d4eb..cd28b3d 100644 --- a/Hardware/DS1302.h +++ b/Hardware/DS1302.h @@ -15,10 +15,15 @@ typedef struct { } DS1302_Time; // 函数声明 +// 函数作用:初始化 DS1302 时钟芯片使用的 GPIO 引脚和通信状态。 void DS1302_Init(void); +// 函数作用:把指定时间写入 DS1302 时钟芯片。 void DS1302_SetTime(DS1302_Time* time); +// 函数作用:从 DS1302 时钟芯片读取当前日期和时间。 void DS1302_GetTime(DS1302_Time* time); +// 函数作用:从 DS1302 指定寄存器地址读取一个字节数据。 uint8_t DS1302_ReadByte(uint8_t addr); +// 函数作用:向 DS1302 指定寄存器地址写入一个字节数据。 void DS1302_WriteByte(uint8_t addr, uint8_t dat); #endif diff --git a/Hardware/K210_USART.c b/Hardware/K210_USART.c index d6d01df..4b2b89b 100644 --- a/Hardware/K210_USART.c +++ b/Hardware/K210_USART.c @@ -11,6 +11,7 @@ extern volatile uint8_t g_k210_rx_flag; // 全局变量:存储解析后的人脸识别结果 FaceRecognitionResult K210_FaceResult; +/* 函数作用:初始化与 K210 通信的 USART3 串口和接收中断。 */ void K210_USART_Init(void) { // 根据连接图.md: K210使用USART3 (PB10/PB11) @@ -60,6 +61,7 @@ void K210_USART_Init(void) * K210数据格式示例: "ID:2021001,NAME:Zhang_San,CONF:0.95" * 或者: "UNKNOWN" (未识别到人脸) */ +/* 函数作用:解析 K210 串口发送的人脸识别字符串并填充结果结构体。 */ uint8_t K210_ParseFaceData(const char* buffer, FaceRecognitionResult* result) { DEBUG_PRINT("[K210] Raw data: %s\r\n", buffer); @@ -109,6 +111,7 @@ uint8_t K210_ParseFaceData(const char* buffer, FaceRecognitionResult* result) return 0; // 解析失败 } +/* 函数作用:检查 K210 接收完成标志,并在有新数据时解析识别结果。 */ uint8_t K210_GetRxFlag(void) { if (g_k210_rx_flag) @@ -129,6 +132,7 @@ uint8_t K210_GetRxFlag(void) return 0; } +/* 函数作用:清除 K210 串口接收完成标志和计数器。 */ void K210_ClearRxFlag(void) { g_k210_rx_flag = 0; diff --git a/Hardware/K210_USART.h b/Hardware/K210_USART.h index 1a6c0a2..9762e24 100644 --- a/Hardware/K210_USART.h +++ b/Hardware/K210_USART.h @@ -10,9 +10,13 @@ extern FaceRecognitionResult K210_FaceResult; // 声明公共函数 +// 函数作用:初始化 STM32 与 K210 通信用的 USART3 接口和接收中断。 void K210_USART_Init(void); +// 函数作用:返回 K210 串口接收完成标志,用于主循环判断是否有新识别结果。 uint8_t K210_GetRxFlag(void); +// 函数作用:清除 K210 串口接收完成标志,准备接收下一帧数据。 void K210_ClearRxFlag(void); +// 函数作用:解析 K210 发来的识别结果字符串,填充人脸识别结果结构体。 uint8_t K210_ParseFaceData(const char* buffer, FaceRecognitionResult* result); #endif diff --git a/Hardware/LightSensor.c b/Hardware/LightSensor.c index b6cda12..05b8eb9 100644 --- a/Hardware/LightSensor.c +++ b/Hardware/LightSensor.c @@ -6,6 +6,7 @@ static uint8_t g_fill_light_on = 0; /** * @brief 初始化光敏电阻ADC和补光灯GPIO */ +/* 函数作用:初始化光敏电阻 ADC 输入和补光灯 GPIO 输出。 */ void LightSensor_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; @@ -60,6 +61,7 @@ void LightSensor_Init(void) * @brief 获取光敏电阻ADC值 * @return ADC值 (0-4095),值越大表示光线越暗(电阻越大) */ +/* 函数作用:采集一次光敏电阻 ADC 数值。 */ uint16_t LightSensor_GetValue(void) { // 启动ADC转换 @@ -76,6 +78,7 @@ uint16_t LightSensor_GetValue(void) * @brief 更新补光灯状态(在主循环中定期调用) * 使用迟滞控制避免灯光频繁开关 */ +/* 函数作用:根据环境光强自动打开或关闭补光灯。 */ void LightSensor_Update(void) { uint16_t light_value = LightSensor_GetValue(); @@ -100,6 +103,7 @@ void LightSensor_Update(void) * @brief 获取补光灯当前状态 * @return 1=亮,0=灭 */ +/* 函数作用:返回补光灯当前开关状态。 */ uint8_t LightSensor_IsLightOn(void) { return g_fill_light_on; diff --git a/Hardware/LightSensor.h b/Hardware/LightSensor.h index 036f92d..809b9b3 100644 --- a/Hardware/LightSensor.h +++ b/Hardware/LightSensor.h @@ -22,9 +22,13 @@ // 使用迟滞区间避免频繁开关 // 函数声明 -void LightSensor_Init(void); // 初始化光敏电阻ADC和补光灯GPIO -uint16_t LightSensor_GetValue(void); // 获取光敏电阻ADC值 -void LightSensor_Update(void); // 更新补光灯状态(主循环中调用) -uint8_t LightSensor_IsLightOn(void); // 获取补光灯当前状态 +// 函数作用:初始化光敏电阻 ADC 输入和补光灯 GPIO 输出。 +void LightSensor_Init(void); +// 函数作用:读取光敏电阻 ADC 当前采样值。 +uint16_t LightSensor_GetValue(void); +// 函数作用:根据当前光照强度和迟滞阈值更新补光灯开关状态。 +void LightSensor_Update(void); +// 函数作用:返回补光灯当前是否处于点亮状态。 +uint8_t LightSensor_IsLightOn(void); #endif diff --git a/Hardware/OLED.c b/Hardware/OLED.c index 940631c..f203308 100644 --- a/Hardware/OLED.c +++ b/Hardware/OLED.c @@ -12,6 +12,7 @@ /* ... 请确保您文件里这部分内容是完整的 ... */ /*引脚初始化*/ +/* 函数作用:初始化 OLED 软件 I2C 使用的 SCL 和 SDA GPIO。 */ void OLED_I2C_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); @@ -28,6 +29,7 @@ void OLED_I2C_Init(void) OLED_W_SDA(1); } +/* 函数作用:产生 OLED 软件 I2C 起始信号。 */ void OLED_I2C_Start(void) { OLED_W_SDA(1); @@ -36,6 +38,7 @@ void OLED_I2C_Start(void) OLED_W_SCL(0); } +/* 函数作用:产生 OLED 软件 I2C 停止信号。 */ void OLED_I2C_Stop(void) { OLED_W_SDA(0); @@ -43,6 +46,7 @@ void OLED_I2C_Stop(void) OLED_W_SDA(1); } +/* 函数作用:通过软件 I2C 向 OLED 发送一个字节。 */ void OLED_I2C_SendByte(uint8_t Byte) { uint8_t i; @@ -56,6 +60,7 @@ void OLED_I2C_SendByte(uint8_t Byte) OLED_W_SCL(0); } +/* 函数作用:向 OLED 写入一条控制命令。 */ void OLED_WriteCommand(uint8_t Command) { OLED_I2C_Start(); @@ -65,6 +70,7 @@ void OLED_WriteCommand(uint8_t Command) OLED_I2C_Stop(); } +/* 函数作用:向 OLED 写入一个显示数据字节。 */ void OLED_WriteData(uint8_t Data) { OLED_I2C_Start(); @@ -74,6 +80,7 @@ void OLED_WriteData(uint8_t Data) OLED_I2C_Stop(); } +/* 函数作用:设置 OLED 显存写入光标位置。 */ void OLED_SetCursor(uint8_t Y, uint8_t X) { OLED_WriteCommand(0xB0 | Y); @@ -81,6 +88,7 @@ void OLED_SetCursor(uint8_t Y, uint8_t X) OLED_WriteCommand(0x00 | (X & 0x0F)); } +/* 函数作用:清空 OLED 屏幕显示内容。 */ void OLED_Clear(void) { uint8_t i, j; @@ -94,6 +102,7 @@ void OLED_Clear(void) } } +/* 函数作用:在指定行列显示一个 ASCII 字符。 */ void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char) { uint8_t i; @@ -109,6 +118,7 @@ void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char) } } +/* 函数作用:从指定行列开始显示字符串。 */ void OLED_ShowString(uint8_t Line, uint8_t Column, char *String) { uint8_t i; @@ -118,6 +128,7 @@ void OLED_ShowString(uint8_t Line, uint8_t Column, char *String) } } +/* 函数作用:计算整数 X 的 Y 次方,用于数字拆位显示。 */ uint32_t OLED_Pow(uint32_t X, uint32_t Y) { uint32_t Result = 1; @@ -128,6 +139,7 @@ uint32_t OLED_Pow(uint32_t X, uint32_t Y) return Result; } +/* 函数作用:在 OLED 上显示指定长度的无符号十进制数字。 */ void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length) { uint8_t i; @@ -137,6 +149,7 @@ void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length) } } +/* 函数作用:在 OLED 上显示带正负号的十进制数字。 */ void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length) { uint8_t i; @@ -157,6 +170,7 @@ void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Le } } +/* 函数作用:在 OLED 上显示指定长度的十六进制数字。 */ void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length) { uint8_t i, SingleNumber; @@ -174,6 +188,7 @@ void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Leng } } +/* 函数作用:在 OLED 上显示指定长度的二进制数字。 */ void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length) { uint8_t i; @@ -191,6 +206,7 @@ void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Leng * @param num 要显示的汉字在OLED_F16x16_CN字模数组中的索引 * @retval 无 */ +/* 函数作用:按照字模索引在 OLED 上显示一个 16x16 汉字。 */ void OLED_ShowChinese(uint8_t Line, uint8_t Column, uint8_t num) { uint8_t i; @@ -219,6 +235,7 @@ void OLED_ShowChinese(uint8_t Line, uint8_t Column, uint8_t num) /* ... OLED_Init() 函数保持不变 ... */ +/* 函数作用:初始化 OLED 控制器参数并清屏。 */ void OLED_Init(void) { uint32_t i, j; diff --git a/Hardware/OLED.h b/Hardware/OLED.h index 73bdc1b..2f495a2 100644 --- a/Hardware/OLED.h +++ b/Hardware/OLED.h @@ -6,16 +6,25 @@ #include "stm32f10x.h" +// 函数作用:初始化 OLED 屏幕通信接口并完成显示控制器基础配置。 void OLED_Init(void); +// 函数作用:清空 OLED 显示缓冲区或屏幕内容。 void OLED_Clear(void); +// 函数作用:在指定行列显示单个 ASCII 字符。 void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char); +// 函数作用:从指定行列开始显示字符串。 void OLED_ShowString(uint8_t Line, uint8_t Column, char *String); +// 函数作用:在指定位置显示无符号十进制数字。 void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length); +// 函数作用:在指定位置显示带符号十进制数字。 void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length); +// 函数作用:在指定位置显示十六进制数字。 void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length); +// 函数作用:在指定位置显示二进制数字。 void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length); // 添加显示汉字的函数声明 +// 函数作用:在指定行列显示字库中编号对应的汉字。 void OLED_ShowChinese(uint8_t Line, uint8_t Column, uint8_t num); #endif diff --git a/Hardware/Serial.c b/Hardware/Serial.c index 5613766..d8f2009 100644 --- a/Hardware/Serial.c +++ b/Hardware/Serial.c @@ -7,6 +7,7 @@ char RxBuffer[RX_BUFFER_SIZE]; uint16_t RxCounter = 0; // 初始化ESP8266所用的串口 (根据连接图.md: USART1 PA9/PA10) +/* 函数作用:初始化与 ESP8266 通信的 USART1 串口和接收中断。 */ void Serial_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; @@ -46,6 +47,7 @@ void Serial_Init(void) } // 发送字符串 +/* 函数作用:通过 USART1 向 ESP8266 发送字符串。 */ void Serial_SendString(const char* String) { for (uint32_t i = 0; String[i] != '\0'; i++) @@ -56,12 +58,14 @@ void Serial_SendString(const char* String) } // 获取接收缓冲区 +/* 函数作用:返回 USART1 接收缓冲区指针。 */ char* Serial_GetRxBuffer(void) { return RxBuffer; } // 清空接收缓冲区 +/* 函数作用:清空 USART1 接收缓冲区和接收计数。 */ void Serial_ClearRxBuffer(void) { memset(RxBuffer, 0, RX_BUFFER_SIZE); @@ -69,6 +73,7 @@ void Serial_ClearRxBuffer(void) } // USART1中断服务函数 (ESP8266) +/* 函数作用:接收 ESP8266 串口返回数据并写入环形缓冲区。 */ void USART1_IRQHandler(void) { if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET) diff --git a/Hardware/Serial.h b/Hardware/Serial.h index 7cf41b8..d9b7e57 100644 --- a/Hardware/Serial.h +++ b/Hardware/Serial.h @@ -4,14 +4,20 @@ #include #include "stm32f10x.h" -void Serial_Init(void); // 初始化串口 -void Serial_SendByte(uint8_t Byte); // 发送一个字节 -void Serial_SendString(const char* String); // 发送字符串 -char* Serial_GetRxBuffer(void); // 获取接收缓冲区指针 -void Serial_ClearRxBuffer(void); // 清空接收缓冲区 +// 函数作用:初始化调试/通信串口及其接收缓冲区。 +void Serial_Init(void); +// 函数作用:通过串口发送一个字节。 +void Serial_SendByte(uint8_t Byte); +// 函数作用:通过串口连续发送以空字符结尾的字符串。 +void Serial_SendString(const char* String); +// 函数作用:返回串口接收缓冲区指针,供主循环解析接收到的数据。 +char* Serial_GetRxBuffer(void); +// 函数作用:清空串口接收缓冲区并复位接收状态。 +void Serial_ClearRxBuffer(void); // 注意:Get_Time_ms() 函数与串口无关,应该在 `Delay.h` 中声明。 // 我们暂时将它与串口放一起,但更规范的做法是分离。 +// 函数作用:返回系统启动以来经过的毫秒数。 uint32_t Get_Time_ms(void); #endif diff --git a/Hardware/aes.c b/Hardware/aes.c index 614e8ce..ea74c96 100644 --- a/Hardware/aes.c +++ b/Hardware/aes.c @@ -54,6 +54,7 @@ static const uint8_t Rcon[11] = { #define getSBoxInvert(num) (rsbox[(num)]) // 密钥扩展 +/* 函数作用:根据 AES-128 主密钥生成每轮加密使用的轮密钥。 */ static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) { unsigned i, j, k; @@ -102,6 +103,7 @@ static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) } // AddRoundKey +/* 函数作用:将当前状态矩阵与指定轮密钥进行异或。 */ static void AddRoundKey(uint8_t round, uint8_t* state, const uint8_t* RoundKey) { uint8_t i, j; @@ -113,6 +115,7 @@ static void AddRoundKey(uint8_t round, uint8_t* state, const uint8_t* RoundKey) } // SubBytes +/* 函数作用:使用 AES S 盒对状态矩阵进行字节替换。 */ static void SubBytes(uint8_t* state) { uint8_t i; @@ -122,6 +125,7 @@ static void SubBytes(uint8_t* state) } // ShiftRows +/* 函数作用:执行 AES 加密流程中的行移位变换。 */ static void ShiftRows(uint8_t* state) { uint8_t temp; @@ -150,12 +154,14 @@ static void ShiftRows(uint8_t* state) } // xtime (用于MixColumns) +/* 函数作用:在 AES 有限域中执行乘以 2 的运算。 */ static uint8_t xtime(uint8_t x) { return ((x << 1) ^ (((x >> 7) & 1) * 0x1b)); } // MixColumns +/* 函数作用:执行 AES 加密流程中的列混淆变换。 */ static void MixColumns(uint8_t* state) { uint8_t i; @@ -184,6 +190,7 @@ static void MixColumns(uint8_t* state) } // Cipher - AES加密核心 +/* 函数作用:对 16 字节状态块执行完整 AES 加密。 */ static void Cipher(uint8_t* state, const uint8_t* RoundKey) { uint8_t round = 0; @@ -205,6 +212,7 @@ static void Cipher(uint8_t* state, const uint8_t* RoundKey) AddRoundKey(10, state, RoundKey); } +/* 函数作用:在 AES 有限域中执行两个字节的乘法。 */ static uint8_t Multiply(uint8_t x, uint8_t y) { return (((y & 1) * x) ^ @@ -214,6 +222,7 @@ static uint8_t Multiply(uint8_t x, uint8_t y) (((y >> 4) & 1) * xtime(xtime(xtime(xtime(x)))))); } +/* 函数作用:使用 AES 逆 S 盒对状态矩阵进行逆字节替换。 */ static void InvSubBytes(uint8_t* state) { uint8_t i; @@ -222,6 +231,7 @@ static void InvSubBytes(uint8_t* state) } } +/* 函数作用:执行 AES 解密流程中的逆行移位变换。 */ static void InvShiftRows(uint8_t* state) { uint8_t temp; @@ -245,6 +255,7 @@ static void InvShiftRows(uint8_t* state) state[15] = temp; } +/* 函数作用:执行 AES 解密流程中的逆列混淆变换。 */ static void InvMixColumns(uint8_t* state) { uint8_t i; @@ -263,6 +274,7 @@ static void InvMixColumns(uint8_t* state) } } +/* 函数作用:对 16 字节状态块执行完整 AES 解密。 */ static void InvCipher(uint8_t* state, const uint8_t* RoundKey) { uint8_t round; @@ -282,22 +294,26 @@ static void InvCipher(uint8_t* state, const uint8_t* RoundKey) // ========== 公开API函数 ========== +/* 函数作用:初始化 AES 上下文并生成轮密钥。 */ void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key) { KeyExpansion(ctx->RoundKey, key); } +/* 函数作用:初始化 AES 上下文并设置 CBC 模式 IV。 */ void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv) { KeyExpansion(ctx->RoundKey, key); memcpy(ctx->Iv, iv, AES_BLOCKLEN); } +/* 函数作用:对单个 16 字节数据块执行 AES-ECB 加密。 */ void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf) { Cipher(buf, ctx->RoundKey); } +/* 函数作用:使用 AES-CBC 模式加密指定长度的数据缓冲区。 */ void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) { size_t i; @@ -317,11 +333,13 @@ void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) } } +/* 函数作用:对单个 16 字节数据块执行 AES-ECB 解密。 */ void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf) { InvCipher(buf, ctx->RoundKey); } +/* 函数作用:使用 AES-CBC 模式解密指定长度的数据缓冲区。 */ void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) { size_t i; diff --git a/Hardware/aes.h b/Hardware/aes.h index 84a0ef3..71ec57a 100644 --- a/Hardware/aes.h +++ b/Hardware/aes.h @@ -20,6 +20,7 @@ struct AES_ctx * @param ctx AES上下文结构 * @param key 16字节密钥 */ +// 函数作用:根据 16 字节密钥初始化 AES 上下文并生成轮密钥。 void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); /** @@ -27,6 +28,7 @@ void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); * @param ctx AES上下文 * @param buf 要加密的数据(16字节块) */ +// 函数作用:使用 AES-ECB 模式加密单个 16 字节数据块。 void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf); /** @@ -34,6 +36,7 @@ void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf); * @param ctx AES上下文 * @param buf 要解密的数据(16字节块) */ +// 函数作用:使用 AES-ECB 模式解密单个 16 字节数据块。 void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf); /** @@ -43,6 +46,7 @@ void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf); * @param length 数据长度(必须是16的倍数) * @param iv 初始化向量(16字节) */ +// 函数作用:使用上下文中的 IV 按 AES-CBC 模式加密指定长度的缓冲区。 void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); /** @@ -52,6 +56,7 @@ void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); * @param length 数据长度(必须是16的倍数) * @param iv 初始化向量(16字节) */ +// 函数作用:使用上下文中的 IV 按 AES-CBC 模式解密指定长度的缓冲区。 void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); /** @@ -60,6 +65,7 @@ void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); * @param key 16字节密钥 * @param iv 16字节初始化向量 */ +// 函数作用:使用 16 字节密钥和 16 字节 IV 初始化 AES-CBC 上下文。 void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv); #endif // _AES_H_ diff --git a/Hardware/aes_fixed.c b/Hardware/aes_fixed.c index 9b8425c..5994596 100644 --- a/Hardware/aes_fixed.c +++ b/Hardware/aes_fixed.c @@ -34,6 +34,7 @@ static const uint8_t Rcon[11] = { #define getSBoxValue(num) (sbox[(num)]) // 密钥扩展 +/* 函数作用:根据 AES-128 主密钥生成每轮加密使用的轮密钥。 */ static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) { unsigned i, j, k; @@ -82,6 +83,7 @@ static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) } // AddRoundKey +/* 函数作用:将当前状态矩阵与指定轮密钥进行异或。 */ static void AddRoundKey(uint8_t round, uint8_t* state, const uint8_t* RoundKey) { uint8_t i, j; @@ -93,6 +95,7 @@ static void AddRoundKey(uint8_t round, uint8_t* state, const uint8_t* RoundKey) } // SubBytes +/* 函数作用:使用 AES S 盒对状态矩阵进行字节替换。 */ static void SubBytes(uint8_t* state) { uint8_t i; @@ -102,6 +105,7 @@ static void SubBytes(uint8_t* state) } // ShiftRows +/* 函数作用:执行 AES 加密流程中的行移位变换。 */ static void ShiftRows(uint8_t* state) { uint8_t temp; @@ -130,12 +134,14 @@ static void ShiftRows(uint8_t* state) } // xtime (用于MixColumns) +/* 函数作用:在 AES 有限域中执行乘以 2 的运算。 */ static uint8_t xtime(uint8_t x) { return ((x << 1) ^ (((x >> 7) & 1) * 0x1b)); } // MixColumns +/* 函数作用:执行 AES 加密流程中的列混淆变换。 */ static void MixColumns(uint8_t* state) { uint8_t i; @@ -164,6 +170,7 @@ static void MixColumns(uint8_t* state) } // Cipher - AES加密核心 +/* 函数作用:对 16 字节状态块执行完整 AES 加密。 */ static void Cipher(uint8_t* state, const uint8_t* RoundKey) { uint8_t round = 0; @@ -187,22 +194,26 @@ static void Cipher(uint8_t* state, const uint8_t* RoundKey) // ========== 公开API函数 ========== +/* 函数作用:初始化 AES 上下文并生成轮密钥。 */ void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key) { KeyExpansion(ctx->RoundKey, key); } +/* 函数作用:初始化 AES 上下文并设置 CBC 模式 IV。 */ void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv) { KeyExpansion(ctx->RoundKey, key); memcpy(ctx->Iv, iv, AES_BLOCKLEN); } +/* 函数作用:对单个 16 字节数据块执行 AES-ECB 加密。 */ void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf) { Cipher(buf, ctx->RoundKey); } +/* 函数作用:使用 AES-CBC 模式加密指定长度的数据缓冲区。 */ void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) { size_t i; @@ -223,12 +234,14 @@ void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) } // STM32端不需要解密功能 +/* 函数作用:对单个 16 字节数据块执行 AES-ECB 解密。 */ void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf) { (void)ctx; (void)buf; } +/* 函数作用:使用 AES-CBC 模式解密指定长度的数据缓冲区。 */ void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) { (void)ctx; diff --git a/Hardware/aes_fixed.h b/Hardware/aes_fixed.h index 142d860..4e99a71 100644 --- a/Hardware/aes_fixed.h +++ b/Hardware/aes_fixed.h @@ -20,6 +20,7 @@ struct AES_ctx * @param ctx AES上下文结构 * @param key 16字节密钥 */ +// 函数作用:根据 16 字节密钥初始化 AES 上下文并生成轮密钥。 void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); /** @@ -28,6 +29,7 @@ void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); * @param key 16字节密钥 * @param iv 16字节初始化向量 */ +// 函数作用:使用 16 字节密钥和 16 字节 IV 初始化 AES-CBC 上下文。 void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv); /** @@ -35,6 +37,7 @@ void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv) * @param ctx AES上下文 * @param buf 要加密的数据(16字节块) */ +// 函数作用:使用 AES-ECB 模式加密单个 16 字节数据块。 void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf); /** @@ -42,6 +45,7 @@ void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf); * @param ctx AES上下文 * @param buf 要解密的数据(16字节块) */ +// 函数作用:使用 AES-ECB 模式解密单个 16 字节数据块。 void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf); /** @@ -50,6 +54,7 @@ void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf); * @param buf 要加密的数据 * @param length 数据长度(必须是16的倍数) */ +// 函数作用:使用上下文中的 IV 按 AES-CBC 模式加密指定长度的缓冲区。 void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); /** @@ -58,6 +63,7 @@ void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); * @param buf 要解密的数据 * @param length 数据长度(必须是16的倍数) */ +// 函数作用:使用上下文中的 IV 按 AES-CBC 模式解密指定长度的缓冲区。 void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); #endif // _AES_H_ diff --git a/Hardware/base64.c b/Hardware/base64.c index e903745..11ff38c 100644 --- a/Hardware/base64.c +++ b/Hardware/base64.c @@ -9,6 +9,7 @@ static const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +/* 函数作用:将二进制数据编码为 Base64 字符串。 */ uint32_t base64_encode(const uint8_t* input, uint32_t input_length, char* output) { uint32_t i, j; @@ -41,6 +42,7 @@ uint32_t base64_encode(const uint8_t* input, uint32_t input_length, char* output return output_length; } +/* 函数作用:把 Base64 字符转换为 6 位数值。 */ static uint8_t base64_char_value(char c) { if (c >= 'A' && c <= 'Z') return c - 'A'; @@ -51,6 +53,7 @@ static uint8_t base64_char_value(char c) return 0; } +/* 函数作用:将 Base64 字符串解码为二进制数据。 */ uint32_t base64_decode(const char* input, uint32_t input_length, uint8_t* output) { uint32_t i, j; diff --git a/Hardware/base64.h b/Hardware/base64.h index 7d108c0..e1254d1 100644 --- a/Hardware/base64.h +++ b/Hardware/base64.h @@ -13,6 +13,7 @@ * * 注意:output缓冲区大小至少需要 ((input_length + 2) / 3) * 4 + 1 字节 */ +// 函数作用:将二进制输入数据编码为 Base64 字符串并返回输出长度。 uint32_t base64_encode(const uint8_t* input, uint32_t input_length, char* output); /** @@ -22,6 +23,7 @@ uint32_t base64_encode(const uint8_t* input, uint32_t input_length, char* output * @param output 输出缓冲区 * @return 解码后的数据长度 */ +// 函数作用:将 Base64 字符串解码为二进制数据并返回解码长度。 uint32_t base64_decode(const char* input, uint32_t input_length, uint8_t* output); /** diff --git a/Hardware/esp8266.c b/Hardware/esp8266.c index dea98ea..d7a1361 100644 --- a/Hardware/esp8266.c +++ b/Hardware/esp8266.c @@ -25,11 +25,13 @@ extern const char* HTTP_API_TOKEN; extern uint8_t g_server_connected; /* --- 私有辅助函数 --- */ +/* 函数作用:向 ESP8266 串口发送一条 AT 指令并追加回车换行。 */ static void ESP8266_SendCmd(const char* cmd) { Serial_SendString(cmd); Serial_SendString("\r\n"); } +/* 函数作用:在指定超时时间内等待 ESP8266 返回期望关键字。 */ static uint8_t ESP8266_WaitForAck(const char* ack, uint32_t timeout) { uint32_t time_start = Get_Time_ms(); uint32_t time_elapsed; @@ -57,11 +59,13 @@ static uint8_t ESP8266_WaitForAck(const char* ack, uint32_t timeout) { return ESP8266_FAIL; } +/* 函数作用:判断指定年份是否为闰年。 */ static uint8_t IsLeapYear(uint16_t year) { return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 1 : 0; } +/* 函数作用:返回指定年份月份的天数。 */ static uint8_t DaysInMonth(uint16_t year, uint8_t month) { static const uint8_t days_table[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; @@ -69,6 +73,7 @@ static uint8_t DaysInMonth(uint16_t year, uint8_t month) return days_table[month - 1]; } +/* 函数作用:把 Unix 时间戳转换为北京时间结构体。 */ static void EpochToDateTimeUTC8(uint32_t epoch_seconds, ESP8266_DateTime* datetime) { // 转为北京时间(UTC+8) @@ -99,6 +104,7 @@ static void EpochToDateTimeUTC8(uint32_t epoch_seconds, ESP8266_DateTime* dateti datetime->day = (uint8_t)(days + 1U); } +/* 函数作用:从 HTTP 响应中复制正文,并在响应加密时完成解密。 */ static uint8_t ESP8266_CopyDecryptedBody(char* response, char* body_start, uint16_t body_len, @@ -137,6 +143,7 @@ static uint8_t ESP8266_CopyDecryptedBody(char* response, /* --- 公共接口函数实现 --- */ +/* 函数作用:初始化 ESP8266 AT 模式、WiFi 模式和 TCP 单连接模式。 */ uint8_t ESP8266_Setup(void) { ESP8266_SendCmd("+++"); @@ -159,6 +166,7 @@ uint8_t ESP8266_Setup(void) return ESP8266_SUCCESS; } +/* 函数作用:连接指定 SSID 和密码的 WiFi 热点。 */ uint8_t ESP8266_ConnectWiFi(const char* ssid, const char* password) { char cmd_buffer[128]; @@ -172,6 +180,7 @@ uint8_t ESP8266_ConnectWiFi(const char* ssid, const char* password) /** * @brief 连接到HTTP服务器(新增) */ +/* 函数作用:与服务端建立 TCP 连接,为后续 HTTP 请求做准备。 */ uint8_t ESP8266_ConnectHTTPServer(const char* ip, const char* port) { char cmd_buffer[100]; @@ -215,6 +224,7 @@ uint8_t ESP8266_ConnectHTTPServer(const char* ip, const char* port) /** * @brief 发送加密数据(HTTP POST请求) */ +/* 函数作用:通过 HTTP POST 上传 AES 加密后的考勤 JSON 数据。 */ uint8_t ESP8266_SendEncryptedData(const char* encrypted_data) { char http_request[1024]; @@ -353,6 +363,7 @@ uint8_t ESP8266_SendEncryptedData(const char* encrypted_data) return ESP8266_FAIL; } +/* 函数作用:从服务端时间接口获取 Unix 时间戳并转换为本地时间。 */ uint8_t ESP8266_GetNetworkTime(ESP8266_DateTime* datetime) { char response_buffer[256]; @@ -405,6 +416,7 @@ uint8_t ESP8266_GetNetworkTime(ESP8266_DateTime* datetime) return ESP8266_SUCCESS; } +/* 函数作用:查询 ESP8266 当前 TCP/WiFi 连接状态。 */ uint8_t ESP8266_CheckConnection(void) { char* response; @@ -442,6 +454,7 @@ uint8_t ESP8266_CheckConnection(void) /** * @brief 发送HTTP GET请求并接收响应 */ +/* 函数作用:发送带 Token 的 HTTP GET 请求,并返回解密后的响应正文。 */ uint8_t ESP8266_HttpGet(const char* path, char* response_buffer, uint16_t buffer_size) { char http_request[320]; @@ -592,6 +605,7 @@ uint8_t ESP8266_HttpGet(const char* path, char* response_buffer, uint16_t buffer * @param slot_end 时段结束时间(格式"HH:MM") * @retval 1 表示已签到(重复), 0 表示未签到 */ +/* 函数作用:向服务器查询指定学生在给定时段内是否重复签到。 */ uint8_t ESP8266_CheckDuplicate(const char* student_id, const char* slot_start, const char* slot_end) { char path[128]; @@ -639,6 +653,7 @@ uint8_t ESP8266_CheckDuplicate(const char* student_id, const char* slot_start, c * @param buffer_size 缓冲区大小 * @retval 成功下载的学号数量 */ +/* 函数作用:下载指定时间段内今日已签到学生列表,用于本地查重缓存。 */ uint8_t ESP8266_DownloadTodayRecords(const char* slot_start, const char* slot_end, char* student_ids, uint16_t buffer_size) { char path[128]; diff --git a/Hardware/esp8266.h b/Hardware/esp8266.h index 1bfca52..428c222 100644 --- a/Hardware/esp8266.h +++ b/Hardware/esp8266.h @@ -25,6 +25,7 @@ typedef struct { * @brief 对ESP8266模块进行基础设置 * @retval 1 表示成功, 0 表示失败 */ +// 函数作用:初始化 ESP8266 模块并配置基础 AT 工作模式。 uint8_t ESP8266_Setup(void); /** @@ -33,6 +34,7 @@ uint8_t ESP8266_Setup(void); * @param password WiFi的密码 * @retval 1 表示成功, 0 表示失败 */ +// 函数作用:控制 ESP8266 连接指定 WiFi 网络。 uint8_t ESP8266_ConnectWiFi(const char* ssid, const char* password); /** @@ -41,6 +43,7 @@ uint8_t ESP8266_ConnectWiFi(const char* ssid, const char* password); * @param port 服务器的端口号 * @retval 1 表示成功, 0 表示失败 */ +// 函数作用:控制 ESP8266 与指定 HTTP 服务器建立 TCP 连接。 uint8_t ESP8266_ConnectHTTPServer(const char* ip, const char* port); /** @@ -48,12 +51,14 @@ uint8_t ESP8266_ConnectHTTPServer(const char* ip, const char* port); * @param encrypted_data 加密后的Base64数据 * @retval 1 表示成功, 0 表示失败 */ +// 函数作用:通过 ESP8266 发送加密后的考勤 HTTP POST 数据。 uint8_t ESP8266_SendEncryptedData(const char* encrypted_data); /** * @brief 检查TCP连接是否正常 * @retval 1 表示已连接, 0 表示未连接 */ +// 函数作用:检查 ESP8266 当前 TCP/网络连接是否仍然可用。 uint8_t ESP8266_CheckConnection(void); /** @@ -61,6 +66,7 @@ uint8_t ESP8266_CheckConnection(void); * @param datetime 时间结构体指针,用于存储获取的时间 * @retval 1 表示成功, 0 表示失败 */ +// 函数作用:从网络时间服务或服务端接口获取当前日期时间。 uint8_t ESP8266_GetNetworkTime(ESP8266_DateTime* datetime); /** @@ -70,6 +76,7 @@ uint8_t ESP8266_GetNetworkTime(ESP8266_DateTime* datetime); * @param buffer_size 缓冲区大小 * @retval 1 表示成功, 0 表示失败 */ +// 函数作用:通过 ESP8266 发起 HTTP GET 请求并把响应写入缓冲区。 uint8_t ESP8266_HttpGet(const char* path, char* response_buffer, uint16_t buffer_size); /** @@ -79,6 +86,7 @@ uint8_t ESP8266_HttpGet(const char* path, char* response_buffer, uint16_t buffer * @param slot_end 时段结束时间(格式"HH:MM") * @retval 1 表示已签到(重复), 0 表示未签到 */ +// 函数作用:调用服务端查重接口,判断学生在指定时段是否已签到。 uint8_t ESP8266_CheckDuplicate(const char* student_id, const char* slot_start, const char* slot_end); /** @@ -89,6 +97,7 @@ uint8_t ESP8266_CheckDuplicate(const char* student_id, const char* slot_start, c * @param buffer_size 缓冲区大小 * @retval 成功下载的学号数量 */ +// 函数作用:下载指定时段内今日已签到学生列表,用于本地去重缓存恢复。 uint8_t ESP8266_DownloadTodayRecords(const char* slot_start, const char* slot_end, char* student_ids, uint16_t buffer_size); #endif diff --git a/System/Debug.c b/System/Debug.c index 62f1c2c..7ccf313 100644 --- a/System/Debug.c +++ b/System/Debug.c @@ -10,6 +10,7 @@ static char debug_buffer[256]; /** * @brief 初始化调试串口(USART2, PA2=TX, PA3=RX) */ +/* 函数作用:初始化 USART2 调试串口并输出启动日志。 */ void Debug_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; @@ -52,6 +53,7 @@ void Debug_Init(void) /** * @brief 通过调试串口发送一个字节 */ +/* 函数作用:通过 USART2 发送单个调试字节。 */ static void Debug_SendByte(uint8_t byte) { while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); @@ -61,6 +63,7 @@ static void Debug_SendByte(uint8_t byte) /** * @brief 通过调试串口发送字符串 */ +/* 函数作用:通过 USART2 连续发送调试字符串。 */ static void Debug_SendString(const char* str) { while (*str) @@ -72,6 +75,7 @@ static void Debug_SendString(const char* str) /** * @brief 格式化调试信息输出(类似printf) */ +/* 函数作用:格式化调试信息并通过串口输出。 */ void Debug_Printf(const char* format, ...) { va_list args; @@ -85,7 +89,9 @@ void Debug_Printf(const char* format, ...) #else // 调试关闭时,提供空实现 +/* 函数作用:调试关闭时提供空初始化函数,保持接口兼容。 */ void Debug_Init(void) {} +/* 函数作用:调试关闭时丢弃格式化输出,保持接口兼容。 */ void Debug_Printf(const char* format, ...) {} #endif diff --git a/System/Debug.h b/System/Debug.h index 28df13c..0e25c7b 100644 --- a/System/Debug.h +++ b/System/Debug.h @@ -8,9 +8,11 @@ #define DEBUG_ENABLE 1 // 暂时关闭,添加Debug.c后改回1 // 调试串口初始化(使用USART2,PA2/PA3) +// 函数作用:初始化调试串口 USART2,供 DEBUG_PRINT 输出日志使用。 void Debug_Init(void); // 调试信息输出函数 +// 函数作用:按 printf 格式输出调试日志到调试串口。 void Debug_Printf(const char* format, ...); // 快捷宏定义 diff --git a/System/Delay.c b/System/Delay.c index 1086112..5620f33 100644 --- a/System/Delay.c +++ b/System/Delay.c @@ -8,6 +8,7 @@ volatile uint32_t g_time_ms = 0; /** * @brief 初始化SysTick定时器,配置为1ms中断一次 */ +/* 函数作用:初始化 SysTick,使系统每 1ms 进入一次中断。 */ void Delay_Init(void) { // 配置SysTick为1ms中断一次。SystemCoreClock通常是72MHz。 @@ -22,6 +23,7 @@ void Delay_Init(void) * @brief 获取自启动以来的毫秒数 * @retval 当前的毫秒时间戳 */ +/* 函数作用:返回系统启动以来累计的毫秒计数。 */ uint32_t Get_Time_ms(void) { return g_time_ms; @@ -30,6 +32,7 @@ uint32_t Get_Time_ms(void) // --- 以下是你原本就有的阻塞式延时函数,保持不变 --- +/* 函数作用:使用 SysTick 实现微秒级阻塞延时。 */ void Delay_us(uint32_t xus) { SysTick->LOAD = 72 * xus; @@ -39,6 +42,7 @@ void Delay_us(uint32_t xus) SysTick->CTRL = 0x00000004; } +/* 函数作用:基于毫秒 tick 实现毫秒级阻塞延时。 */ void Delay_ms(uint32_t xms) { // 使用SysTick计时器实现精确延时 @@ -48,6 +52,7 @@ void Delay_ms(uint32_t xms) } } +/* 函数作用:通过循环调用毫秒延时实现秒级阻塞延时。 */ void Delay_s(uint32_t xs) { while(xs--) diff --git a/System/Delay.h b/System/Delay.h index 0d635ab..9abfe3e 100644 --- a/System/Delay.h +++ b/System/Delay.h @@ -5,12 +5,17 @@ #include "stm32f10x.h" // 确保包含了这个 // 添加下面两个函数的声明 +// 函数作用:初始化 SysTick 延时模块和毫秒计时基准。 void Delay_Init(void); +// 函数作用:返回系统启动以来经过的毫秒数。 uint32_t Get_Time_ms(void); // 保留你原有的函数声明 +// 函数作用:阻塞延时指定微秒数。 void Delay_us(uint32_t us); +// 函数作用:阻塞延时指定毫秒数。 void Delay_ms(uint32_t ms); +// 函数作用:阻塞延时指定秒数。 void Delay_s(uint32_t s); #endif diff --git a/User/main.c b/User/main.c index 2748323..4608f05 100644 --- a/User/main.c +++ b/User/main.c @@ -84,11 +84,13 @@ uint32_t last_process_time = 0; #define PROCESS_INTERVAL_MS 2000 /* --- 辅助函数 --- */ +/* 函数作用:判断指定年份是否为闰年。 */ static uint8_t IsLeapYear(uint16_t year) { return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 1 : 0; } +/* 函数作用:返回指定年份和月份对应的天数。 */ static uint8_t DaysInMonth(uint16_t year, uint8_t month) { static const uint8_t days_table[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; @@ -97,6 +99,7 @@ static uint8_t DaysInMonth(uint16_t year, uint8_t month) return days_table[month - 1]; } +/* 函数作用:在没有 DS1302 可用时,用系统 tick 推进软件时钟一秒。 */ static void AdvanceSoftwareClockOneSecond(void) { g_current_time.second++; @@ -122,6 +125,7 @@ static void AdvanceSoftwareClockOneSecond(void) g_current_time.year++; } +/* 函数作用:启动签到成功提示音和成功指示灯。 */ void StartBeepSuccess(void) { BUZZER_OFF(); @@ -133,6 +137,7 @@ void StartBeepSuccess(void) LED_SUCCESS_ON(); } +/* 函数作用:启动重复签到提示音和指示灯闪烁序列。 */ void StartBeepDuplicate(void) { BUZZER_OFF(); @@ -144,6 +149,7 @@ void StartBeepDuplicate(void) LED_SUCCESS_ON(); } +/* 函数作用:在主循环中推进蜂鸣器和指示灯的非阻塞提示状态。 */ void ProcessBeep(void) { if (beep_state == BEEP_IDLE) { @@ -185,6 +191,7 @@ void ProcessBeep(void) } } +/* 函数作用:刷新空闲状态下 OLED 显示的系统状态和待同步数量。 */ void UpdateIdleScreen(void) { OLED_Clear(); @@ -203,6 +210,7 @@ void UpdateIdleScreen(void) /** * @brief 发送加密的考勤记录到服务器(新版本) */ +/* 函数作用:将一条考勤记录组装为 JSON,加密后通过 ESP8266 上传服务器。 */ uint8_t SendEncryptedAttendance(AttendanceRecord* record) { char json_data[256]; @@ -244,6 +252,7 @@ uint8_t SendEncryptedAttendance(AttendanceRecord* record) } } +/* 函数作用:批量同步本地待上传考勤记录,并根据结果更新同步状态。 */ void SyncPendingRecords(void) { uint32_t current_time = Get_Time_ms(); @@ -312,6 +321,7 @@ void SyncPendingRecords(void) synced_count, failed_count); } +/* 函数作用:从服务器同步网络时间,并在 DS1302 可用时写入 RTC。 */ uint8_t SyncNetworkTime(void) { DEBUG_INFO("Syncing time from network..."); @@ -376,6 +386,7 @@ uint8_t SyncNetworkTime(void) return 0; } +/* 函数作用:从同步状态 JSON 中提取服务端版本号。 */ static uint32_t ParseSyncVersion(const char* json) { const char* p; @@ -395,6 +406,7 @@ static uint32_t ParseSyncVersion(const char* json) return version; } +/* 函数作用:从服务端下载 STM32 需要的同步状态并更新时间段配置。 */ uint8_t DownloadTimeSlots(void) { char response_buffer[768]; @@ -444,6 +456,7 @@ uint8_t DownloadTimeSlots(void) return 0; } +/* 函数作用:按固定间隔自动从服务端刷新时间段配置。 */ void UpdateTimeSlotConfig(void) { uint32_t current_time = Get_Time_ms(); @@ -471,6 +484,7 @@ void UpdateTimeSlotConfig(void) } } +/* 函数作用:更新当前时间来源,优先读取 DS1302,失败时使用软件时钟并定期 NTP 校时。 */ void UpdateCurrentTime(void) { uint32_t current_ms = Get_Time_ms(); @@ -530,6 +544,7 @@ void UpdateCurrentTime(void) } } +/* 函数作用:按重连间隔尝试恢复 WiFi,并在成功后连接 HTTP 服务器和同步配置。 */ uint8_t TryReconnectWiFi(void) { uint32_t current_time = Get_Time_ms(); @@ -585,6 +600,7 @@ uint8_t TryReconnectWiFi(void) return 0; } +/* 函数作用:按重连间隔尝试恢复 HTTP 服务器连接。 */ uint8_t TryReconnectServer(void) { uint32_t current_time = Get_Time_ms(); @@ -616,6 +632,7 @@ uint8_t TryReconnectServer(void) return 0; } +/* 函数作用:周期性检查服务器连接状态,断线时触发自动重连。 */ void CheckServerConnection(void) { uint32_t current_time = Get_Time_ms(); @@ -653,6 +670,7 @@ void CheckServerConnection(void) // ====================================================================== // 主函数 // ====================================================================== +/* 函数作用:STM32 固件入口,完成硬件初始化并循环处理识别、考勤、联网和显示任务。 */ int main(void) { AttendanceStatus att_status; diff --git a/User/stm32f10x_conf.h b/User/stm32f10x_conf.h index cbb8819..80b86bc 100644 --- a/User/stm32f10x_conf.h +++ b/User/stm32f10x_conf.h @@ -67,6 +67,7 @@ */ #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) /* Exported functions ------------------------------------------------------- */ + /* 函数作用:在开启断言检查时报告参数断言失败所在的文件和行号。 */ void assert_failed(uint8_t* file, uint32_t line); #else #define assert_param(expr) ((void)0) diff --git a/User/stm32f10x_it.c b/User/stm32f10x_it.c index f41c492..610cf8b 100644 --- a/User/stm32f10x_it.c +++ b/User/stm32f10x_it.c @@ -13,6 +13,7 @@ extern volatile uint32_t g_time_ms; * @brief SysTick中断处理函数(1ms中断一次) * @note 用于维护系统时间戳和延时功能 */ +/* 函数作用:每 1ms 递增系统毫秒计数,为延时和定时任务提供时间基准。 */ void SysTick_Handler(void) { g_time_ms++; // 每1ms递增一次 @@ -21,6 +22,7 @@ void SysTick_Handler(void) //... HardFault_Handler 等其他中断保持不变 ... // USART3中断(来自K210,根据连接图.md: K210使用USART3 PB10/PB11) +/* 函数作用:接收 K210 串口发送的人脸识别结果,并按换行符组帧。 */ void USART3_IRQHandler(void) { if (USART_GetITStatus(USART3, USART_IT_RXNE) == SET) diff --git a/User/stm32f10x_it.h b/User/stm32f10x_it.h index 7c3b1d2..16082e2 100644 --- a/User/stm32f10x_it.h +++ b/User/stm32f10x_it.h @@ -21,18 +21,29 @@ /* Exported functions ------------------------------------------------------- */ +/* 函数作用:处理不可屏蔽中断,当前项目中保留默认异常入口。 */ void NMI_Handler(void); +/* 函数作用:处理硬件错误异常,进入错误保护循环便于定位严重故障。 */ void HardFault_Handler(void); +/* 函数作用:处理内存管理异常,当前项目中保留默认异常入口。 */ void MemManage_Handler(void); +/* 函数作用:处理总线错误异常,当前项目中保留默认异常入口。 */ void BusFault_Handler(void); +/* 函数作用:处理未定义指令等用法错误异常,当前项目中保留默认异常入口。 */ void UsageFault_Handler(void); +/* 函数作用:处理系统服务调用异常,当前项目中保留默认异常入口。 */ void SVC_Handler(void); +/* 函数作用:处理调试监视异常,当前项目中保留默认异常入口。 */ void DebugMon_Handler(void); +/* 函数作用:处理可挂起系统服务异常,当前项目中保留默认异常入口。 */ void PendSV_Handler(void); +/* 函数作用:处理系统滴答定时器中断,用于毫秒计时和延时基准。 */ void SysTick_Handler(void); // 外设中断 +/* 函数作用:处理 USART1 中断,用于 ESP8266 串口通信接收。 */ void USART1_IRQHandler(void); +/* 函数作用:处理 USART3 中断,用于 K210 人脸识别结果接收。 */ void USART3_IRQHandler(void); #ifdef __cplusplus