stm32使用位带操作实现流水灯效果
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位的字,当访问位带别名区的这些字时,就可以达到访问位带区某个比特位的目的。
- 解释有点复杂,关键是记住公式即可。后续使用中慢慢琢磨。