STM32F4 阿波罗寄存器 进阶版LED灯

上一节通过使用操作地址的方式进行了寄存器的操作,接下来通过两个部分,实现进阶版的操作寄存器(将寄存器的地址进行命名,然后使用名字进行调用  比如商场的A座5楼345号为卖玩具的,我们可以定义地址为shopa,接着使用shopa代替卖玩具的地址就OK了)

进阶1:首先需要完成寄存器的映射,将基地址进行定义,然后在基地址的基础上加上偏移地址即可。这部分需要在main.c对应的.h文件之中进行操作,代码如下.C语言在最后,第二个elsif之中

#define PERIPH_BASE       ((unsigned int)0x40000000)
#define PERIPH_AHB1       (PERIPH_BASE + 0x00020000)
#define PERIPH_RCC_BASE   (PERIPH_AHB1 + 0x00003800)
#define PERIPH_GPIOB_BASE (PERIPH_AHB1 + 0x00000400)
这部分代码是地址立即数的操作,前面就不需要写 *(unsigned int *)
#define RCC_AHB1_ENABLE *(unsigned int *)(PERIPH_RCC_BASE+0x00000030) #define GPIOB_MODER *(unsigned int *)(PERIPH_GPIOB_BASE) #define GPIOB_OTTYPE *(unsigned int *)(PERIPH_GPIOB_BASE+0x04) #define GPIOB_OSPEED *(unsigned int *)(PERIPH_GPIOB_BASE+0x08) #define GPIOB_PUPDR *(unsigned int *)(PERIPH_GPIOB_BASE+0x0C) #define GPIOB_ODR *(unsigned int *)(PERIPH_GPIOB_BASE+0x14) 这部分代码是要在c文件之中进行赋值,因此需要将该名字转换为一个为地址的量。

进阶2:上述的寄存器需要不断的定义,但是在实际的使用之中,会发现RCC的一部分寄存器都是32位的,我们可以用结构体进行定义,自动赋值就好。

 

typedef  unsigned  int   uint32_t;
typedef  unsigned  short uint16_t;

typedef struct 
{
    uint32_t MODER;
    uint32_t OTTYPE;
    uint32_t OSPEED;
    uint32_t PUPDR;
    uint32_t IDR;
    uint32_t ODR;
    uint32_t BSRR;
}GPIO_TypeDef;

typedef struct 
{
    uint32_t CR;
    uint32_t PLLCFGR;
    uint32_t CFGR;
    uint32_t CIR;
    uint32_t AHB1RSTR;
    uint32_t AHB2RSTR;
    uint32_t AHB3RSTR;
    uint32_t BLANK1;
    uint32_t APB1RSTR;
    uint32_t APB2RSTR;
    uint32_t BLANK2;
    uint32_t BLANK3;
    uint32_t AHB1ENR;
    uint32_t AHB2ENR;
    uint32_t AHB3ENR;
}RCC_TypeDef;
结构体之中的名字一定要写对,要根据初始地址之后的寄存器进行,地址也要对应,上边的BLANK就是为了增加地址写的哦。开始写的时候出错了,一个原因就是因为AHB1使能的地址不对。
#define GPIOB ((GPIO_TypeDef*)PERIPH_GPIOB_BASE) #define RCC ((RCC_TypeDef*)PERIPH_RCC_BASE)

C语言的代码:

//灯0 为PB1口

# include  "stm32f429xx.h"
# include  "stm32f429xx_gpio.h"

int main(void) { #if 0 //使能时钟AHB1 *(unsigned int *)0x40023830 |= (1<<1); //控制io口输出 *(unsigned int *)0x40020400 &= 0x00000000; *(unsigned int *)0x40020400 |= (1<<2); *(unsigned int *)0x40020404 &= 0x00000000; *(unsigned int *)0x40020408 &= 0x00000000; *(unsigned int *)0x40020408 |= (1<<3); *(unsigned int *)0x4002040C &= 0x00000000; *(unsigned int *)0x4002040C |= (1<<2); //ODR寄存器 *(unsigned int *)0x40020414 &=~(1<<1); #elif 0 RCC_AHB1_ENABLE |= (1<<1); //控制io口输出 GPIOB_MODER &= 0x00000000; GPIOB_MODER |= (1<<2); GPIOB_OTTYPE &= 0x00000000; GPIOB_OSPEED &= 0x00000000; GPIOB_OSPEED |= (1<<3); GPIOB_PUPDR &= 0x00000000; GPIOB_PUPDR |= (1<<2); GPIOB_ODR &=~(1<<1); #elif 0 RCC->AHB1ENR |= (1<<1); GPIOB->MODER &= 0x00000000; GPIOB->MODER |= (1<<2); GPIOB->OTTYPE &= 0x00000000; GPIOB->OSPEED &= 0x00000000; GPIOB->OSPEED |= (1<<3); GPIOB->PUPDR &= 0x00000000; GPIOB->PUPDR |= (1<<2); GPIOB->ODR &=~(1<<1); //GPIOB->BSRR |=(1<<1); #elif 1 RCC->AHB1ENR |= (1<<1); GPIOB->MODER &= 0x00000000; GPIOB->MODER |= (1<<2); GPIOB->OTTYPE &= 0x00000000; GPIOB->OSPEED &= 0x00000000; GPIOB->OSPEED |= (1<<3); GPIOB->PUPDR &= 0x00000000; GPIOB->PUPDR |= (1<<2); //GPIO_SetBits( GPIOB,GPIO_Pin_1); GPIO_ResetBits(GPIOB,GPIO_Pin_1); #endif } void systeminit(void) //骗过编译器不会报错 { }

C语言知识点总结:

 *(unsigned int *)   是一个强制类型转换,首先把指针强制转换成(unsigned int*)型,然后再取值,比如 int *addr,那么就需要强制转换,因为有的编译器编译会有警告,如果加上(unsigned int *),警告就会消失

注意:

  1. 其中.h文件之中需要对H文件进行一个判定,看是否已经定义过.H 文件,这部分代码不能出现在.c文件之中,我就不知怎么的写进去了,结果各种错误啊啊啊
  2. 在编写代码的过程之中一定要注意括号的使用,使用过多也会出现各种的错误哦。

 

 

posted @ 2019-08-24 16:07  菜鸟奇遇记  阅读(302)  评论(0)    收藏  举报