
簡介本資源是一套完整的基于STM32單片機的智能手環高分畢業設計項目面向電子信息、自動化、嵌入式等專業的本科生適用于畢業設計、課程設計及期末大作業實踐。項目涵蓋心率監測、血壓提醒、計步、時間顯示等核心功能源碼經本地實機編譯驗證可穩定運行評審得分高達98分內容已通過助教老師審定難度適中且工程規范性強。壓縮包共103個文件含11個C源文件與8個H頭文件構成完整固件工程11個PDF文檔提供原理圖說明、算法解析與測試報告8個DOCX格式的設計說明書與答辯PPT框架以及大量BMP/PNG界面資源圖如開機廣告、心率/血壓測量界面等整體大小為17.75MB。目前已有210人學習下載配套資料齊全、模塊劃分清晰、注釋充分可直接用于移植開發或作為嵌入式系統綜合實踐的優質參考范例。 每年三月份總有一批人開始為畢業設計失眠。題目選了“基于STM32單片機的智能手環”的人表面上開心背地里也在打鼓網上源碼一大堆但到底哪份能跑通文檔怎么寫才能不像是抄的其實我一開始做這個項目時也經歷過同樣的迷茫。今天這篇東西不曬成品圖也不吹噓功能就從一個過來人的角度把基于STM32單片機的智能手環從選題、硬件、軟件、文檔、調試到答辯的完整鏈路講清楚。手里這套源碼和全部資料我是按照“拿到手就能復現、改一改就能畢業”的標準整理的所以你會看到很多實際踩過坑之后才明白的細節。這不是一篇枯燥的技術說明書而是更適合當畢設參考的實戰筆記。1. 為什么“STM32智能手環”是畢業設計里的穩妥牌1.1 手環項目的天然優勢畢業設計選題最怕什么怕題目太空、太抽象也怕太簡單沒有工作量更怕太復雜做不完。STM32智能手環恰好落在“中間剛剛好”的位置它有一個物理實體能戴在手腕上實時顯示數據視覺沖擊力強它內部有傳感器采集、數據處理、顯示交互、電源管理這些模塊單獨拿出來都能講幾分鐘它又不需要做太深的人工智能或大數據大部分功能用單片機基礎外設就能實現。換句話說這個題目天然適合在答辯現場演示。常規的“溫度采集系統”只能看一個數而智能手環可以把時間、步數、心率、溫度、菜單切換全部展示出來老師一眼就能看出這是一個完整的小型嵌入式系統。再加上“智能穿戴”這個概念本身就有話題度就算你的算法只用了最簡單的閾值檢測也能用“低功耗場景下的輕量級計步實現”這種說法包裝聽起來并不掉價。1.2 項目訓練的核心能力很多人在簡歷里寫“熟悉STM32”但實際只跑過流水燈。做一個智能手環至少能逼你接觸這些東西硬件最小系統晶振、復位、電源、啟動模式、下載接口。常見通信協議I2C讀傳感器、SPI或I2C驅動OLED、UART接藍牙模塊。ADC采樣電池電壓檢測、溫濕度模擬量讀取。傳感器數據處理加速度計數據的濾波、計步閾值判定、心率信號峰值檢測。狀態機編程OLED菜單切換、按鍵事件響應、低功耗模式切換。這些能力不是背出來的是在反復調試中磨出來的。等到你真把計步從“亂跳”調到“走一步數一下”你對單片機中斷、定時器、DMA、線程調度這些概念的理解會遠超那種只會調用庫函數的人。1.3 源碼、文檔、全部資料對拿高分的作用畢設成績從來不是只看功能而是看“資料完整性”。一份高分畢設通常要交付論文、可運行源碼、演示視頻、硬件實物。很多人代碼能跑但論文寫不出來也有人論文寫得漂亮但代碼一運行就崩。所以我在整理這套資料時特別強調“源碼文檔說明全部資料”三件套。源碼負責“能跑”文檔負責“能講”電路圖、原理圖、芯片手冊、調試記錄這類的全部資料則負責“可信度”。答辯時老師隨口問一句“你電源芯片為什么選這個”你如果能從資料里翻出數據手冊并說出“靜態功耗、壓降、輸出電流”這幾個關鍵詞印象分會立刻不一樣。資料齊全的意義就是讓你在壓力下也能快速找到依據而不是硬著頭皮編。2. 硬件搭建從主控到傳感器的完整選型思路2.1 主控最小系統不要一上來就畫PCB很多新手拿到原理圖就開始畫PCB結果焊接后板子不工作半天找不到原因。我第一次做手環時也犯過這個錯。后來學乖了先買現成的核心板或最小系統板把功能全部調通再考慮畫集成板。STM32F103C8T6這種小容量芯片淘寶上一塊核心板十幾塊錢帶USB轉串口下載對畢設來說完全夠用。手環項目主控我推薦STM32F103C8T6原因有三個第一網上資料最多幾乎每個外設都能找到例程第二內置64KB Flash和20KB RAMOLED、MPU6050、心率傳感器、RTC這些模塊堆在一起也不會爆第三封裝是LQFP48手工焊接比BGA容易太多。如果你的功能加了藍牙音頻或者需要跑FreeRTOS多任務可以考慮F103RCT6甚至F407但對普通計步手環來說C8T6已經綽綽有余。最小系統需要注意的引腳分配NRST接上拉電阻和復位按鍵BOOT0接10K下拉到GNDBOOT1隨意VDDA/VSSA用磁珠和電容隔離OSC_IN/OSC_OUT接8MHz晶振和兩個20pF負載電容SWDIO/SWCLK引出來下載調試。另外VBAT引腳最好直接接3.3V這樣待機時RTC還能繼續走。2.2 傳感器模塊選型MPU6050、MAX30102、DHT11智能手環的核心功能是計步和心率所以傳感器選型很關鍵。計步我建議用MPU6050它內部集成了三軸加速度計和三軸陀螺儀通過I2C接口輸出16位數據。雖然陀螺儀對計步用處不大但后續如果你想做姿態識別比如抬手亮屏、搖一搖切歌陀螺儀就能派上用場。心率模塊選MAX30102這是目前畢設中最常用的血氧心率傳感器。它用紅光和紅外光照射血管通過光電二極管檢測PPG信號。需要注意的是MAX30102的I2C地址可以通過AD引腳設置默認0x57而且模塊工作電壓是1.8V所以很多成品模塊已經帶了電平轉換芯片購買時一定要確認是否兼容3.3V主控。溫濕度傳感器可以根據需求選DHT11或SHT30。DHT11便宜但精度低、采樣周期長1秒一次手環上顯示環境溫度夠用SHT30精度高且支持I2C代碼寫起來更舒服。如果不想增加復雜度DHT11完全沒問題但論文里需要提一句“傳感器性能滿足日常環境監測需求”。除了傳感器還要預留一個無源蜂鳴器或振動馬達。振動馬達推薦扁平紐扣式PWM控制就能驅動用來做鬧鐘或者來電提醒比蜂鳴器安靜且更像真實手環。2.3 顯示與交互OLED、按鍵、振動馬達的設計顯示部分0.96寸OLED是最常見的選擇。I2C版本只需要四根線VCC、GND、SCL、SDA接線簡單但刷新速度一般SPI版本雖然多兩根線但刷新速度快很多如果你要在界面上畫動態波形SPI是更好的選擇。我自己后來改用了SPI版本的OLED因為心率波形刷新時I2C模式的撕裂感太明顯。OLED的引腳分配要盡量避免和傳感器沖突。比如MPU6050也走I2C你可以把OLED放在SPI總線上這樣兩條總線并行驅動互不干擾。注意OLED模塊的邏輯電平和功耗3.3V供電即可背光電流大概20mA對鋰電池來說不算大。按鍵設計要防抖。手環上一般放兩個按鍵一個用于菜單切換一個用于確認/返回。如果用的是外部中斷軟件里要加20ms消抖如果是掃描方式建議放到定時器中斷里每10ms掃描一次避免主循環卡頓。振動馬達用NPN三極管或MOS管驅動GPIO接基極馬達正極接電源負極接集電極續流二極管和RC吸收電路一定要加否則開關瞬間的尖峰電壓可能讓單片機復位。2.4 電源系統鋰電池充放電和電壓檢測手環是穿戴設備供電不能拉根電源線。我用的方案是3.7V鋰電池加TP4056充電模塊再加ME6211穩壓芯片。TP4056負責給電池充電最大充電電流可以透過外部電阻設置我一般設500mA發熱小ME6211是一款低壓差LDO輸入2.5V到6V輸出3.3V靜態功耗幾十微安很適合電池供電。電池電壓檢測是很多新手容易忽略的地方。鋰電池電壓范圍3.0V到4.2V不能直接接ADC引腳需要用兩個電阻分壓后再采樣。選電阻時要算好分壓比比如用100K和100K把電壓減半最大只有2.1V安全落在STM32的3.3V ADC范圍內。但要注意電阻分壓會持續消耗電池電流為了省電可以在分壓電阻和電池之間加一個MOS管平時關閉需要檢測電量時再打開每次只打開幾毫秒。低功耗設計上STM32可以進入STOP模式配合RTC喚醒但畢設階段不一定要求這個老師更看重你有沒有這個意識。如果你能在論文里寫下“系統在休眠時關閉傳感器和OLED電流從35mA降到1.2mA”這已經是一個不小的加分項。3. 軟件架構和算法實現源碼不是堆出來的3.1 工程目錄怎么劃分讀代碼才不累很多畢設源碼是把所有代碼塞進一個main.c幾千行看著頭皮發麻。這種代碼即使功能正常也很容易在答辯時被老師挑刺。我建議按模塊拆分目錄至少分成這樣main.c初始化外設進入主循環。bsp.c / bsp.h板級支持包封裝LED、按鍵、OLED、傳感器初始化函數。app.c / app.h業務邏輯比如頁面切換、參數設置、報警處理。algorithm.c / algorithm.h計步算法、心率算法、濾波函數。driver存放廠商提供的驅動比如MPU6050、MAX30102、SSD1306。這樣做的好處是答辯時你可以直接說“這里是驅動層只負責寄存器讀寫這里是應用層負責數據處理和界面跳轉”一句話就能體現架構意識。源碼閱讀者也更容易快速定位問題顯示亂了去查app數據跳變去查algorithm沒反應去查bsp。3.2 數據采集與濾波傳感器原始數據的“洗干凈”方法MPU6050讀出來的加速度數據不可能直接用。手腕擺動時會有大量噪聲直接算步數會飄得離譜。我常用的辦法是滑動平均濾波維護一個長度為N的環形緩沖區每來一個新數據剔除最老的數據求剩余數據的平均值。N通常取8到16太短濾不干凈太長會引入滯后讓計步反應變慢。如果對實時性要求更高還可以用一階低通濾波公式是filtered alpha * new_sample (1 - alpha) * filtered;alpha值取0.2到0.4比較合適。這個公式簡單代碼量幾乎為零在MCU上跑非常快。對于加速度計這種連續變化的信號一階低通配合滑動平均已經能應對大部分噪聲。心率傳感器MAX30102的數據處理更麻煩。它需要先設置采樣率和LED電流然后讀取PPG數據。我建議把采樣率設在100Hz左右通過定時器中斷均勻采樣。原始PPG信號會有基線漂移可以用高速濾波去掉直流分量再用低通濾波濾除高頻噪聲。畢設階段不用做得很復雜能穩定顯示波形、算出一個看得過去的心率值就夠了。3.3 計步和心率算法原理與簡化實現計步算法的核心思想是檢測加速度矢量的周期性波動。每走一步加速度大小會先增大再減小出現一個波峰。所以算法步驟是先計算三軸加速度的合成幅值magnitude sqrt(ax*ax ay*ay az*az);然后對幅度做高通濾波去掉重力分量。設定一個閾值比如重力加速度的15%到20%當濾波后的幅度超過閾值時記一個“候選步”再通過時間窗口判斷比如兩個波峰間隔必須在250ms到2000ms之間避免把抖動當步數。偽代碼如下static float threshold 0.15f; static uint32_t last_step_time 0; static uint32_t step_count 0; void step_detect(float magnitude) { float filtered highpass(magnitude); if (filtered threshold) { uint32_t now HAL_GetTick(); if (now - last_step_time 250 now - last_step_time 2000) { step_count; last_step_time now; } } }這個簡化算法在正常走路時準確率能達到90%左右。如果要進一步提升可以加入步頻檢測、動態閾值、靜止檢測等但那是加分項。心率算法更復雜簡化版是把PPG信號按1秒分成一段找這段區間內的峰值和波谷然后計算峰值間平均間隔再換算成每分鐘心跳數。注意運動偽影很嚴重戴在手上跑步時基本沒法用所以畢設里最好寫清楚“本系統側重靜息心率測量運動場景下準確性會下降”。承認限制不可怕可怕的是測試條件寫不清楚老師一眼看出你在糊弄。3.4 OLED界面菜單用狀態機代替一堆if elseOLED顯示界面如果直接在main函數里寫if else功能一多就亂。我用的方法是狀態機typedef enum { PAGE_MAIN, PAGE_STEPS, PAGE_HEARTRATE, PAGE_TEMPERATURE, PAGE_SETTINGS, } PageState; static PageState current_page PAGE_MAIN; void page_key_handle(uint8_t key) { switch (current_page) { case PAGE_MAIN: if (key KEY_NEXT) current_page PAGE_STEPS; break; case PAGE_STEPS: if (key KEY_NEXT) current_page PAGE_HEARTRATE; else if (key KEY_BACK) current_page PAGE_MAIN; break; // ... } }狀態機的好處是每次只有“當前狀態”和“觸發事件”兩個變量邏輯清晰不容易出bug。頁面上要顯示哪些數據可以放在對應狀態的refresh函數里主循環每100ms調用一次刷新。OLED內部有顯存操作時先改顯存再一次性刷新到屏幕能顯著減少閃爍。主循環我建議控制頻率不要while(1)瘋狂刷屏。可以用一個時間片輪詢的思路uint32_t tick HAL_GetTick(); if (tick - last_heart_tick 20) { read_heart(); last_heart_tick tick; } if (tick - last_ui_tick 100) { ui_update(); last_ui_tick tick; } if (tick - last_step_tick 50) { step_detect(); last_step_tick tick; }這樣不僅代碼好讀實際運行也更流暢。4. 文檔說明與答辯資料怎么把項目“講明白”4.1 畢設論文的正文結構拿到一份完整的畢設項目光會跑代碼沒用還得會寫文檔。論文的基本結構我建議這樣安排第一章 緒論寫智能手環的研究背景、意義、國內外現狀。別直接復制百度百科改寫成自己的話重點強調“輕量級、低功耗、可穿戴”。第二章 系統總體設計放系統框圖畫出主控、傳感器、顯示、電源、藍牙等模塊的關系然后做功能需求分析。第三章 硬件設計對應我上面說的電路選型和原理每個模塊單獨一節包括芯片選型理由、接口電路、元器件參數計算。第四章 軟件設計按模塊寫流程配狀態轉換圖、算法流程圖、關鍵代碼片段。計步算法這里值得單獨寫一節。第五章 系統測試列出測試環境、測試表格比如不同行走速度下的計步準確率、靜息心率誤差、續航時間、OLED刷新表現。第六章 總結與展望總結你做了什么指出不足然后寫未來可以增加藍牙App、手勢識別、睡眠監測等。如果項目是“源碼文檔說明全部資料”的形式這份文檔就是你最后的門面。寫的時候注意圖文并茂不要大段貼代碼老師沒那么多耐心看代碼要把代碼思路抽出來用流程圖和文字講清楚。4.2 圖表、流程圖和實物圖的重要性圖表永遠是答辯評委最容易抓的“閱讀錨點”。我的經驗是每一章至少配兩張圖一張結構圖一張流程圖或實物圖。硬件部分配電路連接圖、PCB截圖、整機照片軟件部分配狀態轉換圖、算法流程圖、OLED界面示意圖。你不需要畫得多專業用Visio、Draw.io甚至PPT都能做只要要素齊全、箭頭清楚。實物圖一定要用工整的接線和干凈的背景重拍。很多同學實物圖上面沾滿膠帶和飛線老師第一印象就不好。你可以把系統板放在亞克力底座上用彩色杜邦線分類綁扎拍近景和遠景各一張放到論文和PPT里。越是“看起來專業”越容易給評委留下好印象。4.3 答辯演示的節奏控制與高頻問題答辯演示講究“臺上一分鐘臺下十年功”。我的演示流程是先展示手環外觀然后開機顯示主界面逐一進入步數、心率、溫度頁面再模擬一次計步走幾步最后用手按住心率傳感器展示波形。整個過程控制在5分鐘內不要講到藍牙傳輸和低功耗細節那是留給老師提問的。高頻問題至少準備這幾個為什么選STM32F103而不是MSP430或ESP32 答開發資料多、外設豐富、低功耗模式夠用而且畢設階段性價比高。計步算法怎么排除非走路動作 答用了高通濾波和波峰時間間隔約束能排除大部分抖腕、甩手干擾。心率傳感器在運動時準確嗎 答本系統偏靜息測量運動場景下會因為運動偽影導致誤差這是當前方案的限制。如何降低系統功耗 答OLED只在更新時刷新傳感器按需采樣主控可以進入STOP模式。電池能用多久 答實測待機約XX小時正常工作約XX小時已經接入低功耗處理。提前把這些問題和答案寫在文檔的“答辯常見問題”一頁上臺前多讀兩遍絕對比臨時想詞要好。5. 實測中繞不開的坑從OLED閃爍到I2C通信異常5.1 OLED刷新閃爍罪魁禍首往往是主循環太慢很多人在調試時發現OLED顯示的數字一跳一跳甚至閃爍。第一個念頭是OLED壞掉了其實大部分情況是主循環里有耗時操作。比如你每次采集傳感器后就馬上顯示傳感器I2C通信一次要好幾毫秒主循環被拖慢OLED刷新頻率就掉下去了。解決辦法有三個第一把I2C讀取放到定時器中斷或狀態機里主循環只負責“是否有新數據”的判斷第二OLED使用SPI模式并開啟DMA把顯存數據搬運從CPU手里解放出來第三采用局部刷新只更新變化區域。我最推薦第三種因為代碼改動最小只需要在寫顯存時判斷一下舊值和新值是否相同相同就跳過寫操作。手環界面基本是數字變化局部刷新后效果立竿見影。5.2 I2C通信偶發失敗上拉電阻和時鐘速率MPU6050和MAX30102都用I2C如果總線上設備多了就容易偶發通信失敗比如讀到全0或者同時掛兩條總線時互相干擾。我第一次遇到時排查了整整半天最后發現是模塊自帶上拉電阻和主控上拉電阻重復導致總線上拉太強通信時序變形。解決方法是確認每個傳感器模塊是否已經自帶上拉電阻。像GY-521模塊默認有4.7K上拉如果STM32內部也開啟了上拉組合后的等效電阻可能只有2.3K對標準I2C來說驅動能力過強。相比之下配置為開漏輸出、外部只保留一組4.7K上拉是最穩的。另外I2C時鐘速率可以降到100KHz犧牲一點速度換穩定性。代碼里給每次傳輸加超時處理如果返回錯誤就重新初始化一次很多偶發問題都能被“重試”掩蓋掉。5.3 電池電量顯示不準不要直接讀ADC電池電壓通過分壓電阻送進ADC但直接讀出來的值跳動很大充滿電顯示120%用了一會兒就掉到80%再一會兒又回升。這是因為電池電壓在負載變化時會有波動OLED亮起時電壓瞬間跌落OLED熄滅時電壓回升。改進思路是軟件上做三點第一多次采樣求平均第二只在固定時間點采樣比如每10秒采樣一次避開OLED刷新和傳感器讀取的瞬間第三用開路電壓法估算電量先測出滿電4.2V和空電3.3V對應的ADC值再用線性或折線映射。雖然不能像手機那樣精準但用來顯示“低電量、中等電量、滿電”三檔已經夠用。如果硬件允許還可以加一個MOS管斷開分壓電阻的長期電流。很多低功耗設計都在這里做文章我也在資料里專門寫了這個電路按著搭就能減少電池額外消耗。5.4 RTC時間偏差外部晶振與軟件校準手環必須顯示時間STM32內部RTC的時鐘源選擇很重要。如果用了內部LSI RC振蕩器誤差會比較大一天可能偏幾十秒如果改接一個32.768KHz的外部晶振誤差能降到每天幾秒。但外部晶振需要嚴格匹配負載電容一般6pF到12.5pF選錯電容可能導致不起振。如果RTC還是走不準可以做軟件校準隔一小時和標準時間對比一次算出偏差在代碼里每小時補償幾秒。這個思路在文檔里寫出來老師會覺得你有工程意識。另外要注意RTC最好用BKP寄存器保存校準參數否則斷電重啟后校準就丟了。調試RTC時最煩的是下載程序后時間復位。解決辦法是設定一個標志位寫入備份寄存器如果備份寄存器里的值是特定魔數說明RTC已經初始化過不要重新設置時間否則才執行初始寫時間。這樣每次燒錄程序后時間能繼續保持不需要每次手動輸入。6. 拿到這套源碼資料后怎么變成自己的東西6.1 先燒錄、再拆解、最后才改代碼我見過許多同學把源碼下載下來后直接打開main.c一行一行地讀讀了幾百行就放棄了。更高效的做法是先編譯燒錄讓系統跑起來看實際現象然后改一段代碼觀察變化比如把OLED刷新時間改慢把計步閾值改大把某個狀態機的初始頁面改掉。通過“破壞性實驗”理解每段代碼的作用比靜態閱讀快得多。硬件也一樣先拿著資料里的原理圖逐個量電壓、量信號確認每個模塊工作正常。不要一上來就拆傳感器、換芯片要先建立“系統是好的”這個信心再開始做個性化修改。6.2 明確每個源文件的職責給源碼加注釋一份“高分項目”的源碼注釋一定清楚。我的習慣是每個文件開頭寫一段模塊說明包括功能、主要接口、依賴關系每個關鍵函數前面寫輸入輸出和調用時機遇到特殊計算公式在邊上寫上公式來源和參數含義。比如計步算法里的閾值為什么取0.15我會專門寫一句注釋因為正常行走時垂直方向加速度波動幅度約為重力加速度的10%到20%閾值取中間值能減少零散抖動。這種注釋直接體現你對算法原理的理解老師在檢查源碼看到這些細節分數會明顯不一樣。6.3 從手環到產品增加藍牙和App的擴展路徑如果你覺得純手環界面不夠出彩可以把手環和手機連起來。最省事的方案是加一個HC-08藍牙串口模塊用UART和STM32通信手機端用一個現成的“藍牙串口”App接收數據或者自己寫一個簡單的微信小程序。不需要做實時同步只要在手機端能顯示步數、心率、溫度并支持時間校準項目檔次就提升了一大截。藍牙模塊本身代碼量不大初始化UART、接收藍牙指令、解析數據、打包發送。關鍵是協議設計我建議用字符串協議比如發送“STEPS:1234\n”方便調試等穩定后再換成二進制協議。資料里已經放了我常用的協議文檔直接拿來改一下功能碼就能用。6.4 項目經歷在簡歷上的正確寫法這是畢設之外同樣重要的事。很多人在簡歷上只寫“基于STM32的智能手環”看起來平平無奇。更好的寫法是分條目描述負責手環硬件電路設計完成STM32主控、MPU6050、MAX30102、OLED顯示、鋰電池充電模塊的選型與接線。完成傳感器驅動開發基于I2C/SPI接口讀取加速度、心率、溫濕度數據編寫滑動平均和低通濾波算法。設計狀態機頁面管理框架實現多級菜單、按鍵交互、低功耗模式聯合調通計步、心率、溫度顯示功能。實測數據平路步數準確率93%靜息心率誤差±5BPM待機電流約1.2mA。這樣寫一個關鍵詞對應一個能力點HR和面試官才能快速抓到重點。不要小看這些描述同一個項目表達方式不同價值完全不同。最后再分享一點我的體會做這類嵌入式畢設最大的收獲往往不是代碼跑通那一刻而是你在反復拆解、調試、寫文檔過程中形成的對系統整體和各模塊間關系的理解。哪怕你后續不再接觸STM32這種“先定方案、再搭硬、后寫軟、最后沉淀文檔”的工作方式也值得帶進下一份工作。希望這篇筆記能讓你少走幾段我走過的彎路把“智能手環”這個題目真正做成一份拿得出手的高分作品。本文還有配套的精品資源點擊獲取