【STM32F10x】二:利用结构体访问外设

之前了解使用寄存器操作GPIOA口的LED灯亮灭程序,原理是将寄存器的地址强制转换成指针形式, 然后对指针进行操作。这一章尝试通过将外设定义成结构体的形式来操作外设寄存器。

本章重点在于理解和使用<结构体>来控制外设寄存器,然后举例一个按键控制LED灯实现亮灭功能,通过结构体访问RCC和GPIO的相关寄存器。


预备知识

寄存器地址和结构体在形式上都是地址连续分布

通过C语言的学习可以得知,在结构体中地址都是连续分布的。而在STM32的寄存器中同样也是连续的地址分布的,且恰好相差四个字节。


 


1 在main函数中定义结构体,首先将始终信号RCC转化为结构体形式,通过在参考手册中可以查询到相关寄存器

#ifndef __MAIN_H_
#define __MAIN_H_
typedef struct
{
    unsinged int CR;
    unsinged int CFGR;
    unsinged int CIR;
    unsinged int APB2RSTR;
    unsinged int APB1RSTR;
    unsinged int AHBENR;
    unsinged int APB2ENR;
    unsinged int APB1ENR;
    unsinged int BDCR;
    unsinged int CSR;
    unsinged int AHBRSTR; //其中后两个寄存器是互联型的
    unsinged int CFRG2;
}RCC_Typedef;
#endif

2此时,在主函数中定义一个指针变量,使其恰好等于RCC_Typedef的基地址,那么根据基地址+偏移地址的方式,就可以利用结构体来访问相关寄存器而不用再去记忆一系列的地址。

    RCC_Typedef *p;
    p = (RCC_Typedef *) 0x40021000 ;

由此,若需要使用某一个寄存器.

RCC-> APB2ENR |= (1<<2); //使用APB2ENR寄存器,将其第2位置1

 


依次对GPIO也进行类似的转换,那么main.h文件中

#ifndef __MAIN_H_
#define __MAIN_H_
typedef struct
{
    unsinged int CR;
    unsinged int CFGR;
    unsinged int CIR;
    unsinged int APB2RSTR;
    unsinged int APB1RSTR;
    unsinged int AHBENR;
    unsinged int APB2ENR;
    unsinged int APB1ENR;
    unsinged int BDCR;
    unsinged int CSR;
    unsinged int AHBRSTR; //其中后两个寄存器是互联型的
    unsinged int CFRG2;
}RCC_Typedef;
#define RCC ((RCC_Typedef *) 0x400210000)

typedef struct
{
    unsinged int CRL;
    unsinged int CRH;
    unsinged int IDR;
    unsinged int ODR;
    unsinged int BSRR;
    unsinged int BRR;
    unsinged int LCKR;
}GPIOA_Typedef;
#define GPIOA ((GPIOA_Typedef *) 0x40010800)

#endif

 

 

 

那么替换后的代码格式即为:

#include "stm32f10x.h"
#include "main.h"
void Delay(unsigned long N);

int main(void)
{
    RCC -> APB2ENR |=(1<<2);    //RCCAPB2ENR |= (1<<2);
    GPIOA -> CRL &= 0xfff0000f;    //GPIOA_CRL &= 0xfff0000f;
    GPIOA -> CRL |= 0x00033330;  //GPIOA_CRL |= 0x00033330; 
    GPIOA -> ODR &= ~((1<<1)|(1<<2)|(1<<3)|(1<<4)); //GPIOA_ODR  &= ~((1<<1)|(1<<2)|(1<<3)|(1<<4));

    while(1)
    {
        GPIOA -> ODR &= ((1<<1)|(1<<2)|(1<<3)|(1<<4));  // GPIOA_ODR &= ((1<<1)|(1<<2)|                    (1<<3)|(1<<4)); 
        Delay(10000);
    }
}
void Delay(unsigned long N)
{
    for(;N!=0;N--);
}

 

 

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值