一、位代操作概念及优缺点:
直接通过硬件的都端口地址对硬件进行操作:
优点:响应快,可适用于军工等对硬件性能要求严格的领域
缺点:操作难度略大,需要进行编程的人员硬件的地址如何运算有一定了解并指导如何操作硬件,以及硬件的其他设定有概念。
二、寄存器地址与别名地址转换技巧:
1.确定某端口访问起始地址,如端口F访问起始地址为GPIOF_BASE
#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)
2.根据要访问的寄存器地址计算偏移值,如计算
GPIOF的ODR寄存器地址 = GPIOF_BASE+0x14;
{ODR代表输出寄存器
若使用按键可将ODR改为IDR使用即可}
3.根据以下公式进行换算
寄存器的位带别名 = 0x42000000 + (寄存器的地址-0x40000000)*8*4 + 引脚编号*4
寄存器地址和映射地址都可产生同样现象.
三、位代操作的计算公式:
方法一、设置PF9引脚电平代码如下
uint32_t *PF9_BitBand = (uint32_t *)(0x42000000 + (GPIOF_BASE + 0x14 - 0x40000000)*32 + 9*4);
方法二、更优解的方法:
uint32_t *PF9_BitBand = (uint32_t *)(0x42000000 + ((uint32_t)&GPIOF->ODR - 0x40000000)*32 + 9*4);
下面的代码使用了两种方法对GPIOF9端口进行操作,主要实现闪烁灯功能,
#include "stm32f4xx.h" #include<stdio.h> static GPIO_InitTypeDef GPIO_InitStructure; uint32_t *p9 = (uint32_t *)(0x42000000+((uint32_t)&GPIOF->ODR - 0x40000000)*32+9*4); //通过位代操作进行获取硬件的地址 void delay(void) { uint32_t i=0x2000000; while(i--); } int main(void) { //使能(打开)端口F的硬件时钟,就是对端口F供电 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); //初始化GPIO引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //第9根引脚 GPIO_InitStructure.GPIO_Mode= GPIO_Mode_OUT; //输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出,增加输出电流能力。 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//高速响应 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //没有使能上下拉电阻 GPIO_Init(GPIOF,&GPIO_InitStructure); while(1) { //PF9引脚输出高电平 //GPIO_SetBits(GPIOF,GPIO_Pin_9); *p9 = 1; delay(); //PF9引脚输出低电平 GPIO_ResetBits(GPIOF,GPIO_Pin_9); delay(); } }