码迷,mamicode.com
首页 > 其他好文 > 详细

Duanxx的STM32学习:GPIO的位带操作

时间:2015-06-08 09:56:34      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:stm32   位带操作   

支持了位带操作后,可以使用普通的加载/存储指令来对单一的比特进行读写。在 CM3中,有两个区中实现了位带。其中一个是 SRAM 区的最低 1MB 范围,第二个则是片内外设区的最低 1MB 范围。这两个区中的地址除了可以像普通的 RAM 一样使用外,它们还都有自己的“位带别名区”,位带别名区把每个比特膨胀成一个 32 位的字。当你通过位带别名区访问这些字时,就可以达到访问原始比特的目的


技术分享


关于位带操作的博客说明有很多,这里主要将代码贴出来,并做详细的注释


/**
    ******************************************************************************
    * @file GPIO.h
    * @author Duanxx
    * @version V1.1
    * @data 2015-06-07
    * @brief 这个头文件是对"stm32f10x_gpio.h"的一个补充
    *        主要是对《Cortex-M3权威指南(中文版)》chp05存储器系统->位带操作的一个实现
    *        这个功能实现之后,可以使得STM32像51一样对IO口按位操作
    *        
    ******************************************************************************    
*/

#ifndef _GPIO_H_
#define _GPIO_H_

#include "stm32f10x_gpio.h"

/**
    * 这里的实现是从《Cortex-M3权威指南(中文版)》chp05存储器系统->位带操作第92页直接抄过来的
    * 其目的是为了简化位带操作,而定义了一些专用的宏
*/
///< 把“位带地址+位序号”转换成别名地址的宏
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
///< 把该地址转换成一个指针的宏
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
///< 对地址的按位操作
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 

/**
    * 下面是GPIO输入输出数据寄存器的地址
    * 这里的地址是根据《STM32F10x Refernce manual(RM0008 英文版)》中
    * chp3 memory and bus architecture -> 3.2 Memory organization 以及
    * chp9 General-purpose and alternate-function I/Os (GPIOs and AFIOs) -> 9.5 GPIO and AFIO register maps
    * 中关于GPIO的地址分配表得到的
*/
///< 在GPIO的基址上偏移0x8,就是GPIOx_IDR的地址,即GPIO Input Data Register(输入数据寄存器)
#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的基址上偏移0x8,就是GPIOx_ODR的地址,即GPIO Output Data Register(输出数据寄存器)
#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    



/**
    * 下面是基于GPIO对位带操作的使用做了进一步的宏定义
    * 其使用方法如下
    * 如果GPIO是输出模式:
    * Step1: 将GPIO初始化为输出,比如:
        GPIO_InitTypeDef Duanxx_GPIO_InitStructure;   
    
        //< Enable GPIOA, RCC_APB2Periph_GPIOA
        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA , ENABLE);    

        
        //< Configure and PA.1 as output push-pull 
        Duanxx_GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
        Duanxx_GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        Duanxx_GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(GPIOA, &Duanxx_GPIO_InitStructure);
        
    *Step2: 控制PA1的输出
        PAout(1) = 0; //<PA1输出低电平
        PAout(1) = 1; //<PA1输出为高电平

    * 当然,我们也可以使用宏定义,对下面的宏定义做进一步的封装
    * 这样,就更有利于我们使用有意义的GPIO控制
    * 比如PA1链接的是LED,那么就可以有如下的操作
        #define LED PAout(1) ///<LED 为PA1
        #define LED_ON  1   ///<定义LED亮的值
        #define LED_OFF 0   ///<定义LED灭的值
        
        LED = LED_OFF; ///< LED 灭
        LED = LED_OFF; ///< LED 亮、
    
    **********************************************************************
    * 对于GPIO输入而言,也可有有相似的操作
    * 第一步也是初始化,将GPIo初始化位输入
    * 第二步则是对GPIO进行读取,比如
    * 判断PA1是否是高电平如下:
        if(PAin(1) == 1)
        {
            ....
        }
    *
*/
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n) 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n) 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n) 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n) 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n) 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n) 

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n) 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n) 

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n) 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n) 

void GPIO_Disale_JTAG(void);

#endif



Duanxx的STM32学习:GPIO的位带操作

标签:stm32   位带操作   

原文地址:http://blog.csdn.net/daunxx/article/details/46404209

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!