目錄
- 1、原理圖
- 2、文件結構
- 3、使用寄存器模式點亮
- 3.1、什么是寄存器
- 3.2、寄存器開發的本質
- 3.3、寄存器開發步驟
- 3.4、主要源碼
- 3.4.1、main.c
- 3.4.2、drv_gpio.h
- 3.4.3、drv_gpio.c
- 3.4.4、使用BSRR和BRR影子寄存器優化`drv_gpio.c`
- 3.4.5、效果演示
- 4、使用標準庫模式點亮
- 4.1、使用標準庫模式的好處
- 4.2、主要源碼
- 4.2.1、main.c
- 4.2.2、drv_gpio.h
- 4.2.3、drv_gpio.c
- 4.2.4、效果演示多了白燈
1、原理圖
如圖知,拉低為點亮
-
LED
燈 引腳 狀態 D3紅 PB5 輸出, 拉低為亮 D3綠 PB0 輸出, 拉低為亮 D3藍 PB1 輸出, 拉低為亮
2、文件結構
3、使用寄存器模式點亮
3.1、什么是寄存器
寄存器是微控制器(MCU)內部的一種特殊存儲器,用于存儲配置參數、狀態信息或控制信號。每個寄存器通常有固定的地址,并且每一位或一組位對應特定的功能。
3.2、寄存器開發的本質
寄存器開發的本質是直接與硬件交互,繞過高級庫(如 HAL 庫或標準庫)的封裝,直接操作底層硬件。
STM32 的寄存器開發是通過直接讀寫寄存器來實現對外設的控制。
3.3、寄存器開發步驟
(1) 查找寄存器地址
- 根據 STM32 的參考手冊(Reference Manual),找到目標外設的寄存器地址。
- 每個外設(如 GPIO、TIMER、USART 等)都有一組寄存器,用于配置和控制其行為。
(2) 配置寄存器
- 通過指針操作或直接訪問寄存器地址,向寄存器寫入特定的值,以配置外設的工作模式、中斷、時鐘等。
(3) 讀取寄存器
- 通過讀取寄存器的值,獲取外設的狀態信息(如標志位、數據等)。
3.4、主要源碼
3.4.1、main.c
#include "drv_gpio.h"// SysTick 初始化
void SysTick_Init(void)
{SysTick->LOAD = 72000000 / 1000 - 1; // 1ms 延時SysTick->VAL = 0; // 清空當前值SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;
}// 精確延時函數(單位:ms)
void Delay_ms(uint32_t ms)
{for (uint32_t i = 0; i < ms; i++){while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));}
}int main()
{// 初始化 SysTickSysTick_Init();// 初始化 RGB LEDRGB_Init();while (1){RGB_RedOn();Delay_ms(500); // 延時 500msRGB_RedOff();RGB_GreenOn();Delay_ms(500); // 延時 500msRGB_GreenOff();RGB_BlueOn();Delay_ms(500); // 延時 500msRGB_BlueOff();}
}
3.4.2、drv_gpio.h
#ifndef _DRV_GPIO_H_
#define _DRV_GPIO_H_//ARM提供的,有所有外設寄存器的信息
#include "stm32f10x.h"void RGB_Init(void);void RGB_RedOn(void);void RGB_RedOff(void);void RGB_GreenOn(void);void RGB_GreenOff(void);void RGB_BlueOn(void);void RGB_BlueOff(void);#endif
3.4.3、drv_gpio.c
#include "drv_gpio.h"void RGB_Init(void)
{// 1.配置RCCRCC->APB2ENR |= (1 << 3);// 2.配置PB5的功能// bit 20~23 全部置為0// bit 20 置為1//pb5GPIOB->CRL &= (uint32_t)(~(0xF << 20));GPIOB->CRL |= (uint32_t)(1 << 20); //配置為通用推挽輸出模式(0b0001)//pb0GPIOB->CRL &= (uint32_t)(~(0xF));GPIOB->CRL |= (uint32_t)(1);//pb1GPIOB->CRL &= (uint32_t)(~(0xF << 4));GPIOB->CRL |= (uint32_t)(1 << 4); // 3.將pb5、pb0、pb1的初始值改為1,防止配置完就亮燈GPIOB->ODR |= (1 << 5);GPIOB->ODR |= 1;GPIOB->ODR |= (1 << 1);}void RGB_RedOn(void)
{// 3.拉低PB5對應的ODR寄存器地址GPIOB->ODR &= ~(1 << 5);
}void RGB_RedOff(void)
{GPIOB->ODR |= (1 << 5);
}void RGB_GreenOn(void)
{GPIOB->ODR &= ~(1);
}void RGB_GreenOff(void)
{GPIOB->ODR |= 1;
}void RGB_BlueOn(void)
{GPIOB->ODR &= ~(1 << 1);
}void RGB_BlueOff(void)
{GPIOB->ODR |= (1 << 1);
}
3.4.4、使用BSRR和BRR影子寄存器優化drv_gpio.c
由于對
ODR
直接操作, 可能有意無意修改到其他引腳的狀態
#include "drv_gpio.h"void RGB_Init(void)
{// 1.配置RCCRCC->APB2ENR |= (1 << 3);// 2.配置PB5的功能// bit 20~23 全部置為0// bit 20 置為1//pb5GPIOB->CRL &= (uint32_t)(~(0xF << 20));GPIOB->CRL |= (uint32_t)(1 << 20); //配置為通用推挽輸出模式(0b0001)//pb0GPIOB->CRL &= (uint32_t)(~(0xF));GPIOB->CRL |= (uint32_t)(1);//pb1GPIOB->CRL &= (uint32_t)(~(0xF << 4));GPIOB->CRL |= (uint32_t)(1 << 4); // 3.將pb5、pb0、pb1的初始值改為1,防止配置完就亮燈GPIOB->ODR |= (1 << 5);GPIOB->ODR |= 1;GPIOB->ODR |= (1 << 1);}void RGB_RedOn(void)
{// 3.拉低PB5對應的ODR寄存器地址//GPIOB->ODR &= ~(1 << 5); GPIOB->BRR &= (1 << 5);// 直接將PB5拉低,同時不影響其他位
}void RGB_RedOff(void)
{//GPIOB->ODR |= (1 << 5);GPIOB->BSRR |= (1 << 5); //直接拉高,并不影響
}void RGB_GreenOn(void)
{//GPIOB->ODR &= ~(1);GPIOB->BRR &= (1);
}void RGB_GreenOff(void)
{//GPIOB->ODR |= 1;GPIOB->BSRR |= (1);
}void RGB_BlueOn(void)
{//GPIOB->ODR &= ~(1 << 1);GPIOB->BRR &= (1 << 1);
}void RGB_BlueOff(void)
{//GPIOB->ODR |= (1 << 1);GPIOB->BSRR |= (1 << 1);
}
3.4.5、效果演示
4、使用標準庫模式點亮
4.1、使用標準庫模式的好處
標準庫封裝了底層寄存器的操作,提供了易于理解的API函數,開發者無需直接讀寫寄存器。
4.2、主要源碼
4.2.1、main.c
#include "drv_gpio.h"// SysTick 初始化
void SysTick_Init(void)
{SysTick->LOAD = 72000000 / 1000 - 1; // 1ms 延時SysTick->VAL = 0; // 清空當前值SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;
}// 精確延時函數(單位:ms)
void Delay_ms(uint32_t ms)
{for (uint32_t i = 0; i < ms; i++){while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));}
}int main()
{// 初始化 SysTickSysTick_Init();// 初始化 RGB LEDRGB_Init();while (1){RGB_RedOn();Delay_ms(500); // 延時 500msRGB_RedOff();RGB_GreenOn();Delay_ms(500); // 延時 500msRGB_GreenOff();RGB_BlueOn();Delay_ms(500); // 延時 500msRGB_BlueOff();RGB_WriteOn();Delay_ms(500); // 延時 500msRGB_WriteOff();}
}
4.2.2、drv_gpio.h
#ifndef _DRV_GPIO_H_
#define _DRV_GPIO_H_//使用gpio標準庫
#include "stm32f10x_gpio.h"#define RGB_Port GPIOB
#define RGB_Pin_R GPIO_Pin_5
#define RGB_Pin_G GPIO_Pin_0
#define RGB_Pin_B GPIO_Pin_1void RGB_Init(void);void RGB_RedOn(void);void RGB_RedOff(void);void RGB_GreenOn(void);void RGB_GreenOff(void);void RGB_BlueOn(void);void RGB_BlueOff(void);void RGB_WriteOn(void);void RGB_WriteOff(void);#endif
4.2.3、drv_gpio.c
#include "drv_gpio.h"void RGB_Init(void)
{// 1.RCC配置RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);// 2、配置紅、綠、藍燈輸出GPIO_InitTypeDef gpio_initStruct = {0};gpio_initStruct.GPIO_Pin = RGB_Pin_R | RGB_Pin_G | RGB_Pin_B;gpio_initStruct.GPIO_Speed = GPIO_Speed_50MHz;gpio_initStruct.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(RGB_Port, &gpio_initStruct);GPIO_SetBits(RGB_Port, RGB_Pin_R | RGB_Pin_G | RGB_Pin_B);
}void RGB_RedOn(void)
{// 3.拉低PB5對應的ODR寄存器地址GPIO_ResetBits(RGB_Port, RGB_Pin_R);
}void RGB_RedOff(void)
{GPIO_SetBits(RGB_Port, RGB_Pin_R);
}void RGB_GreenOn(void)
{GPIO_ResetBits(RGB_Port, RGB_Pin_G);
}void RGB_GreenOff(void)
{GPIO_SetBits(RGB_Port, RGB_Pin_G);
}void RGB_BlueOn(void)
{GPIO_ResetBits(RGB_Port, RGB_Pin_B);
}void RGB_BlueOff(void)
{GPIO_SetBits(RGB_Port, RGB_Pin_B);
}void RGB_WriteOn(void)
{GPIO_ResetBits(RGB_Port, RGB_Pin_R | RGB_Pin_G | RGB_Pin_B);
}void RGB_WriteOff(void)
{GPIO_SetBits(RGB_Port, RGB_Pin_R | RGB_Pin_G | RGB_Pin_B);
}