1. 項目:51單片機可以通過控制位進行控制單片機的端口電平,類似的stm32也具有同樣的功能。現在使用stm32的位帶操作控制GPIO端口的電壓實現流水燈效果。
2. 代碼:
主函數main.c
#include "stm32f10x.h"
#include "bsp_led.h"
/*位帶操作公式*/
//公式: #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x02000000+((addr &0x00FFFFFF)<<5)+(bitnum<<2))
/*******************************使用位帶操作控制GPIOB的端口點亮LED燈********************************/
#define GPIOB_ODR_Addr (GPIOB_BASE + 0x0c)
#define PBout(n) *(unsigned int*)((GPIOB_ODR_Addr&0xf0000000) + 0x02000000 + ((GPIOB_ODR_Addr&0x00ffffff)<<5)+ (n<<2)) /*定義GPIOB輸出端口的宏*/
/*延時函數*/
void Delay(uint32_t count)
{
for(;count!=0; count--);
}
/*主函數*/
int main(void)
{
LED_GPIO_Config(); /*LED燈端口初始化*/
while(1)
{
PBout(0) = 1; /*控制GPIOB的PB0端口輸出高電平,類似與51單片機中的P^0 = 1*/
Delay(0xfffff);
PBout(0) = 0;
Delay(0xfffff);
}
}
LED燈宏定義函數bsp_led.h
#ifndef __bsp_led_h #define __bsp_led_h #include "stm32f10x.h" //LED燈引腳宏定義(綠燈) #define LED_G_GPIO_PIN GPIO_Pin_0 /*定義pin口*/ #define LED_G_GPIO_PORT GPIOB /*定義為GPIOB端口*/ #define LED_G_GPIO_CLK RCC_APB2Periph_GPIOB /*定義GPIOB端口時鍾*/ void LED_GPIO_Config(void); /*LED燈初始化函數聲明*/ #endif /*__bsp_led_h*/
控制LED燈的GPIO口配置函數 bsp_led.c
#include "bsp_led.h"
void LED_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(LED_G_GPIO_CLK,ENABLE); /*打開綠燈外設時鍾*/
GPIO_InitStruct.GPIO_Pin = LED_G_GPIO_PIN; /*定義pin腳(綠燈)結構體變量*/
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LED_G_GPIO_PORT, &GPIO_InitStruct); /*調用函數初始化結構體*/
}
3. 參考資料:
- 原理圖
-
GPIO端口配置步驟:
- 使能GPIO端口時鍾;
- 初始化GPIO目標引腳為推挽輸出模式;
- 編寫簡單測試程序,控制GPIO引腳輸出高、低電平。

4. 總結:
- 位帶操作類似與51單片機中的位操作,這里是叫法不一樣。都是控制芯片的管腳電平實現電燈操作。
- 位操作就是可以單獨的對一個比特位讀和寫,這個在51單片機中非常常見。51單片機中通過關鍵字sbit來實現位定義,STM32沒有這樣的關鍵字,而是通過訪問位帶別名區來實現。
- 在STM32中,有兩個地方實現了位帶,一個是SRAM區的最低1MB空間,令一個是外設區最低1MB空間。這兩個1MB的空間除了可以像正常的RAM一樣操作外,他們還有自己的位帶別名區,位帶別名區把這1MB的空間的每一個位膨脹成一個32位的字,當訪問位帶別名區的這些字時,就可以達到訪問位帶區某個比特位的目的。
- 解釋有點復雜,關鍵是記住公式即可。后續使用中慢慢琢磨。
