打印

转贴:使用GPIO有心得分享

[复制链接]
1320|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
拿起书本|  楼主 | 2013-11-11 20:11 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1. 我使用GPIO的不同就是,GPIO 操作是直接动用了STM32 内部的寄存器的.虽说库好用,但
对于某些IO 操作,很多人都会嫌库的效率底下(包括我自己在内),总得对STM32 的寄存器看
两眼的吧,
2. 当然了,即使直接操作寄存器了,但一些方便的宏定义还是用库里面的好,反正宏定义本身
并不影响效率.这里要说一下MDK 的一个重要技巧,就是把工程编译完以后,在变量或函
数体上按下F12 键,就会自动跳转到这个变量或函数的定义处.要研究库代码,这个技巧必
不可少,不然在大堆C文件里找一个定义是相当累人的.

大家看看ST 官方库里面对各个寄存器的定义,是使用结构体的,可谓相当有技巧,首先要
定义几个基础地址:

//定义片内外设基础地址
#define PERIPH_BASE ((uint32_t)0x40000000)

//定义APB2地址,APB2地址在片内外设的0x10000偏移处.
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)

//这个定义了GPIOA首地址:,在APB2 的0x800偏移处
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)

//定义GPIOA的结构体
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
GPIO_TypeDef结构体的原型:
typedef struct
{
  __IO uint32_t CRL;
  __IO uint32_t CRH;
  __IO uint32_t IDR;
  __IO uint32_t ODR;
  __IO uint32_t BSRR;
  __IO uint32_t BRR;
  __IO uint32_t LCKR;
} GPIO_TypeDef;

那个__IO 的东西也是库定义的类型,还有__I 和__O 呢,主要方便表达这个寄存器是读写,
还是只读,只写:

#define __I volatile const /*!< defines 'read only' permissions */
#define __O volatile /*!< defines 'write only' permissions */
#define __IO volatile /*!< defines 'read / write' permissions */

好了,说了这么多,其实每组GPIO 就7 个寄存器:
CRL,CRH,IDR,ODR,BSSR,BRR,LCKR.

库函数之所以用如此繁琐的定义,也是为了代码结构的一致和更系统的使用库调用,当然
你看库会觉得这样很麻烦,但相对的是,我们使用起来就很简单.例如要操作GPIOA 的

CRL寄存器,那么就是:
GPIOA->CRL=0x00;就可以了.
这些GPIO 寄存器STM32F10xxx_CH_Rev7V3 中文用户手册.pdf 中的P75 里有详细
介绍.

另外,IO 还有一些重映射和事件寄存器等的,将在以后讨论.

3. 例程中IO 的输入输出控制都是直接操作的寄存器,例如:
#define LED1_ON GPIOA->BRR = GPIO_Pin_8
#define GET_LEFT() (!(GPIOD->IDR&GPIO_Pin_3))
这个GPIO_Pin_8,其实就是(1<<8), GPIO_Pin_3,就是(1<<3).
这些操作都要比调用库函数快不少的.对于实际项目中需要快速IO操作的,建议像这样直
接操作寄存器.

另外在GPIO.C 文件里的GPIO_Configuration()函数中,配置按键的输入,也采用了直接操
作寄存器的方式,这里只是简单地介绍一下使用寄存器配置GPIO 的方法,实际使用中,还
是建议用库函数配置,毕竟,配置硬件这类操作一般不会十分频繁地调用,而是在系统上电
的时候调用一次的,所以这些情况下都不会在乎执行效率.而且,直接操作寄存器,出低级
错误的几率挺大~


沙发
andyhu05| | 2013-11-12 16:30 | 只看该作者
楼主总结得很好,学习了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:好好学习,天天向上!

519

主题

4195

帖子

31

粉丝