各位看官老爺們,點擊關注不迷路喲。你的點贊、收藏,一鍵三連,是我持續更新的動力喲!!!
目錄
普中STM32F103ZET6開發攻略
1. GPIO端口實驗——點亮LED燈
1.1 實驗目的
1.2 實驗原理
1.3 實驗環境和器材:
1.4 實驗思路
1.5 實驗代碼
1.5.1 LED相關代碼
1.5.2 delay相關代碼
1.6 實驗思考和拓展
1.6.1 如何調整LED燈的閃爍頻率?
1.6.2 如何實現呼吸燈效果?
1.6.2.1 非 PWM 實現呼吸燈的原理
1.6.2.2 具體實現方法(以 STM32 為例)
1. 亮度等級劃分
2. 控制亮滅時間比例
1.6.2.3 代碼實例:
1.6.3 除了使用簡單延時外,STM32還有哪些更加精準的延時方式?
1.7 注意事項
普中STM32F103ZET6開發攻略
1. GPIO端口實驗——點亮LED燈
1.1 實驗目的
-
了解STM32F10x微控制器的GPIO口結構和基本操作
-
掌握STM32標準庫函數對GPIO的配置和使用方法
-
學會使用GPIO控制LED的亮滅,實現LED基本顯示效果
-
掌握簡單延時函數的編寫方法
1.2 實驗原理
-
GPIO原理
STM32的GPIO(通用輸入/輸出端口)用于外設信號的輸入輸出控制。STM32F10x系列GPIO具有以下特性:
(1) 每個I/O端口有16個可獨立配置的I/O位
(2) 支持8種不同的工作模式
模式分類 具體模式 核心特點 典型應用 輸入模式 浮空輸入 無內部上下拉,電平由外部決定 外部信號采集(需外部上下拉) 上拉輸入 內部上拉,默認高電平 按鍵輸入(低電平有效) 下拉輸入 內部下拉,默認低電平 按鍵輸入(高電平有效) 模擬輸入 連接 ADC,禁用數字輸入功能 ADC 模數轉換 輸出模式 開漏輸出 需外部上拉,支持線與邏輯 I2C 總線、電平轉換 推挽輸出 直接輸出高低電平,驅動能力強 LED 控制、普通數字信號 開漏復用功能 外設驅動,需外部上拉 SPI/I2C 外設輸出 推挽復用功能 外設驅動,直接輸出高低電平 USART/CAN 外設輸出 通過配置 GPIO 的模式寄存器(CRL/CRH)和輸出類型寄存器,可靈活選擇上述工作模式,滿足不同外設的控制需求。
(3) 每個I/O口可以產生外部中斷
(4) 位設置/復位寄存器,支持原子位操作
-
LED控制原理
LED (發光二極管) 是一種單向導電器件,只有在正向偏置時才會發光。根據開發板硬件設計,LED燈通常采用如下接法:
(1) 共陽極接法:LED陽極接VCC,陰極接單片機GPIO,GPIO輸出低電平時LED點亮;
(2) 共陰極接法:LED陰極接地,陽極接單片機GPIO,GPIO輸出高電平時LED點亮;
本實驗中,LED燈采用的是共陽極接法。
1.3 實驗環境和器材:
-
電腦:Keil5+Vstudio
-
硬件資源:普中玄武F103開發板(主控芯片:STM32F103ZET6)
1.4 實驗思路
硬件接線圖如下所示:
由上圖可知:
-
DS0即LED0、DS1即LED1,分別連接著:PB5和PE5
LED0連接到GPIOB的Pin5引腳,LED1連接到GPIOE的Pin5引腳
-
為了完成實驗目的:
我們需要再項目工程中新建兩個“庫函數”:LED.c+delay.c
1.5 實驗代碼
1.5.1 LED相關代碼
頭文件:
//led.h #ifndef _led_H #define _led_H #include "stm32f10x.h" #include "stm32f10x_gpio.h" // 包含GPIO相關的函數和宏定義 #include "stm32f10x_rcc.h" ? // 包含RCC(時鐘控制)相關的函數和宏定義 void LED_init(void); void LED0_On(void); void LED0_Off(void); void LED1_On(void); void LED1_Off(void); void LED0_Toggle(void); void LED1_Toggle(void); #endif ?
源文件:
//led.c #include "led.h" ? void LED_init(void) {// 使能 GPIOB 和 GPIOE 的時鐘(幾乎所有外設(包括 GPIO)在使用前都需要先使能對應的時鐘)RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOE, ENABLE); ?GPIO_InitTypeDef GPIO_InitStructure; ?// 配置 PB5 為推挽輸出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure); ?// 配置 PE5 為推挽輸出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;GPIO_Init(GPIOE, &GPIO_InitStructure); ?// 初始狀態GPIO_SetBits(GPIOB, GPIO_Pin_5);GPIO_SetBits(GPIOE, GPIO_Pin_5); } ? ? void LED0_On(void) {GPIO_ResetBits(GPIOB, GPIO_Pin_5); } void LED0_Off(void){GPIO_SetBits(GPIOB, GPIO_Pin_5); } void LED1_On(void) {GPIO_ResetBits(GPIOE, GPIO_Pin_5); } void LED1_Off(void) {GPIO_SetBits(GPIOE, GPIO_Pin_5); } void LED0_Toggle(void) {GPIOB->ODR ^= GPIO_Pin_5; } void LED1_Toggle(void) {GPIOE->ODR ^= GPIO_Pin_5; } ?
因為我們這里是直接輸出高低電平:所以采用的是推挽輸出的方式,由上文可知:推完輸出直接輸出高低電平,驅動能力強。
初始狀態需要設置成為高電平,由上文中的硬件接線圖可知,LED(發光二極管)是在正向偏置時才會發光,所以應該是“低電平有效”
1.5.2 delay相關代碼
頭文件:
#ifndef __DELAY_H #define __DELAY_H ? #include "stm32f10x.h" ? void Delay_Init(void); void Delay_ms(u32 nms); ? #endif ?
源文件:
#include "delay.h" ? static u32 fac_ms = 0; ? void Delay_Init(void) {SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); // HCLK/8fac_ms = SystemCoreClock / 8000; } ? void Delay_ms(u32 nms) {u32 temp;SysTick->LOAD = nms * fac_ms;SysTick->VAL = 0x00;SysTick->CTRL = 0x01;do{temp = SysTick->CTRL;} while ((temp & 0x01) && !(temp & (1 << 16)));SysTick->CTRL = 0x00;SysTick->VAL = 0X00; } ?
1.6 實驗思考和拓展
1.6.1 如何調整LED燈的閃爍頻率?
LED燈閃爍的頻率,歸根結底還是由燈光的亮和滅的時間間隔決定的,亮和滅的時間間隔越小,那么頻率就越高。
實現方法:
-
使用定時器實現精確延時
若使用自定義簡單延時函數(如
void Delay_ms(uint32_t ms)
),直接調整傳入的延時參數。 例:原閃爍周期為 0.6 秒(亮 0.3 秒 + 滅 0.3 秒),若改為亮 0.1 秒 + 滅 0.1 秒,則周期變為 0.2 秒,頻率提高 3 倍。// 原代碼(周期0.6秒) LED0_ON(); ?// 亮 Delay_ms(300); LED0_OFF(); // 滅 Delay_ms(300); ? // 調整后(周期0.2秒) LED0_ON(); Delay_ms(100); Delay_ms(100);
-
使用定時器實現精確延時:
簡單延時函數依賴系統時鐘和循環次數,可通過計算循環次數與時鐘周期的關系提高精度。 例:若系統時鐘為 72MHz,一個循環約耗時 1 微秒,則延時 1 毫秒需循環 1000 次。
-
使用定時器實現精確延時:
利用 STM32 的定時器(如 TIM2、TIM3)產生精確中斷,通過中斷計數實現延時,避免 CPU 空轉,提升系統效率。 步驟: ① 初始化定時器,配置為定時中斷模式(如定時 1 毫秒); ② 在中斷服務函數中維護一個全局計數器; ③ 主函數中通過判斷計數器值實現延時。
1.6.2 如何實現呼吸燈效果?
方法:軟件模擬漸變效果
1.6.2.1 非 PWM 實現呼吸燈的原理
呼吸燈的本質是讓人眼感知到 LED 亮度的線性漸變(從暗到亮或從亮到暗)。人眼對亮度的感知具有惰性,當 LED 在極短時間內(如幾毫秒)頻繁亮滅時,會將亮滅時間的平均值視為 “亮度”。因此,即使不使用硬件 PWM,也可以通過軟件控制 LED 的亮滅占空比(即導通時間與周期的比例),逐步改變占空比來模擬亮度變化。
1.6.2.2 具體實現方法(以 STM32 為例)
LED 為共陽極接法(低電平點亮),通過以下步驟實現亮度漸變:
1. 亮度等級劃分
將亮度從 0%(全滅)到 100%(最亮)劃分為若干等級(如 256 級),用一個變量(如brightness
)表示當前等級(范圍:0~255)。
-
brightness=0
:LED 全滅(高電平)。 -
brightness=255
:LED 全亮(低電平)。
2. 控制亮滅時間比例
每個亮度等級對應一個周期總時間(如 10ms),其中:
-
點亮時間 =
(brightness / 255) × 周期總時間
-
熄滅時間 = 周期總時間 - 點亮時間
通過循環改變brightness
的值(如從 0 逐漸增加到 255,再逐漸減小到 0),并在每個等級中控制 LED 的亮滅時間,即可實現漸變效果。
1.6.2.3 代碼實例:
// 定義LED引腳(共陽極,低電平點亮) #define LED_GPIO_PORT GPIOB #define LED_PIN GPIO_Pin_5 ? // 亮度等級(0~255) uint8_t brightness = 0; uint8_t direction = 1; // 1表示亮度增加,-1表示亮度減少 ? void breathe_led(void) {// 亮度漸變方向控制(到達邊界時反轉方向)if (brightness == 255) direction = -1;if (brightness == 0) direction = 1;brightness += direction; ?// 計算亮滅時間(周期總時間設為10ms,可調整)uint16_t on_time = (brightness * 10) / 255; // 點亮時間(ms)uint16_t off_time = 10 - on_time; // 熄滅時間(ms) ?// 控制LED點亮GPIO_ResetBits(LED_GPIO_PORT, LED_PIN); // 低電平點亮delay_ms(on_time); // 點亮持續時間 ?// 控制LED熄滅GPIO_SetBits(LED_GPIO_PORT, LED_PIN); // 高電平熄滅delay_ms(off_time); // 熄滅持續時間 } ? // 主循環中調用 while (1) {breathe_led(); }
與 PWM 方案的對比
特性 | 非 PWM 軟件模擬 | 硬件 PWM |
---|---|---|
實現復雜度 | 需編寫循環邏輯和延時函數,代碼較繁瑣 | 直接配置定時器 PWM 模式,代碼簡潔 |
CPU 占用率 | 高(需實時控制亮滅時間,阻塞延時) | 低(定時器硬件自動更新占空比) |
亮度平滑度 | 受延時精度限制,可能有閃爍感 | 平滑(硬件驅動,頻率穩定) |
適用場景 | 簡單實驗、對實時性要求低的場合 | 高要求場景(如電機調速、精密調光) |
1.6.3 除了使用簡單延時外,STM32還有哪些更加精準的延時方式?
-
定時器延時(精確且不阻塞 CPU)
原理:利用定時器的計數功能,通過配置自動重裝載值(TIMx_ARR)和預分頻器(TIMx_PSC)設定定時時間,結合中斷或查詢方式實現延時。
優點:精度高(可達微秒級),延時期間 CPU 可執行其他任務。
-
SysTick 定時器延時(系統級延時)
原理:利用 STM32 內部的 SysTick 定時器(系統滴答定時器),基于系統時鐘(如 72MHz)產生精確中斷。
優點:無需額外外設,由 Cortex-M 內核直接支持,適合系統級延時。
-
實時操作系統(RTOS)任務調度
原理:在 RTOS(如 FreeRTOS、uCOS)中,通過任務調度函數(如
vTaskDelay()
)實現延時,本質是釋放 CPU 資源給其他任務。優點:多任務并行處理,延時期間可執行其他任務,適合復雜系統。
-
總結與拓展
-
簡單場景:優先使用 SysTick 或定時器查詢方式,兼顧精度與代碼復雜度。
-
復雜場景:引入 RTOS 或定時器中斷,實現多任務協同和精確時序控制。
-
進階實踐:結合 DMA(直接內存訪問)與定時器,實現無 CPU 參與的自動 PWM 輸出,進一步提升效率。
-
1.7 注意事項
(1) 使用標準庫函數時,需要注意頭文件的包含和依賴關系。
(2) 共陽極LED的控制邏輯:低電平點亮,高電平熄滅。
(3) 簡單延時函數的精確度受系統時鐘和編譯優化的影響。
(4) GPIO操作前必須先使能對應的外設時鐘。
文章有寫的不當的地方,歡迎在評論區中指正修改。如果感覺文章實用對你有幫助,歡迎點贊收藏和關注,你的點贊關注就是我動力,大家一起學習進步。
有不懂的可以在評論區里提出來喲,博主看見后會及時回答的。