学习资料:《野火零死角玩转STM32——F103》
STM32可以像51一样对寄存器的某一个位进行操作,即位操作。
位带区在片上外设和片上SRAM中,各1MB。位带别名区把每个位膨胀成32位的字。
STM32的全部寄存器都可以通过访问位带别名区的方式访问原始寄存器比特位的效果。
转换公式:
A = addr & 0xF0000000)+0x02000000+((addr & 0x00FFFFFF)<<5)+(n <<2))
其中 ,addr为寄存器的地址;n为寄存器比特位。
位带操作点亮LED灯——GPIO口的输入和输出
头文件与STM32学习笔记2的相同,主函数如下:
main.c
#include "stm32f10x.h"
#include "bsp_led.h" //led的控制头文件
#include "bsp_key.h" //key的控制头文件
//位带操作转换公式
#define BITBAND(addr, n) *(unsigned int*)((addr & 0xF0000000)+0x02000000+((addr & 0x00FFFFFF)<<5)+(n <<2))
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C
#define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C
#define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C
#define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C
#define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C
#define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C
#define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808
#define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08
#define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008
#define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408
#define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808
#define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08
#define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08
// 单独操作 GPIO 的某一个 IO 口,n(0,1,2...16),n 表示具体是哪一个 IO 口
#define PAout(n) BITBAND(GPIOA_ODR_Addr,n) //输出
#define PAin(n) BITBAND(GPIOA_IDR_Addr,n) //输入
#define PBout(n) BITBAND(GPIOB_ODR_Addr,n) //输出
#define PBin(n) BITBAND(GPIOB_IDR_Addr,n) //输入
#define PCout(n) BITBAND(GPIOC_ODR_Addr,n) //输出
#define PCin(n) BITBAND(GPIOC_IDR_Addr,n) //输入
#define PDout(n) BITBAND(GPIOD_ODR_Addr,n) //输出
#define PDin(n) BITBAND(GPIOD_IDR_Addr,n) //输入
#define PEout(n) BITBAND(GPIOE_ODR_Addr,n) //输出
#define PEin(n) BITBAND(GPIOE_IDR_Addr,n) //输入
#define PFout(n) BITBAND(GPIOF_ODR_Addr,n) //输出
#define PFin(n) BITBAND(GPIOF_IDR_Addr,n) //输入
#define PGout(n) BITBAND(GPIOG_ODR_Addr,n) //输出
#define PGin(n) BITBAND(GPIOG_IDR_Addr,n) //输入
#if 0
void Delay( uint32_t count ) //软件延迟
{
for(; count!=0; count-- );
}
int main(void)
{
LED_GPIO_Config();
//初始化后引脚全部置0,RGB全亮,故需把它们关闭
PBout(5) = 1;
Delay(0xFFFFF);
PBout(0) = 1;
Delay(0xFFFFF);
PBout(1) = 1;
Delay(0xFFFFF);
//流水灯循环
while(1)
{
//红
PBout(5) = 0;
Delay(0xFFFFFF);
PBout(5) = 1;
//绿
PBout(0) = 0;
Delay(0xFFFFFF);
PBout(0) = 1;
//蓝
PBout(1) = 0;
Delay(0xFFFFFF);
PBout(1) = 1;
//黄
PBout(5) = 0;
PBout(0) = 0;
Delay(0xFFFFFF);
PBout(5) = 1;
PBout(0) = 1;
//淡蓝
PBout(0) = 0;
PBout(1) = 0;
Delay(0xFFFFFF);
PBout(0) = 1;
PBout(1) = 1;
//紫
PBout(5) = 0;
PBout(1) = 0;
Delay(0xFFFFFF);
PBout(5) = 1;
PBout(1) = 1;
//白
PBout(5) = 0;
PBout(0) = 0;
PBout(1) = 0;
Delay(0xFFFFFF);
//关闭
PBout(5) = 1;
PBout(0) = 1;
PBout(1) = 1;
Delay(0xFFFFFF);
}
}
#else
int main(void)
{
LED_GPIO_Config();
KEY1_GPIO_Config();
PBout(5) = 1;
PBout(0) = 1;
PBout(1) = 1;
while(1)
{
if (PAin(0)==1) //按键检测
{
while(PAin(0)==1){}; //松手检测
LED_G_TOGGLE;
LED_B_TOGGLE;
}
}
}
#endif
本文详细介绍了STM32微控制器的位带操作技术,包括位带区和位带别名区的概念,以及如何使用位带操作点亮LED灯。通过具体的代码示例,展示了如何对GPIO口进行位级操作,实现对LED灯的控制。

被折叠的 条评论
为什么被折叠?



