注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
tzzhuang的个人空间 https://home.eeworld.com.cn/space-uid-349046.html [收藏] [复制] [分享] [RSS]
日志

stm32学习(3)--GPIO

已有 3640 次阅读2011-8-17 18:20

STM32的IO口可以由软件配置成8种模式:
1、输入浮空
2、输入上拉
3、输入下拉
4、模拟输入
5、开漏输出
6、推挽输出
7、推挽式复用功能
8、开漏复用功能
每个IO口可以自由编程,单IO口寄存器必须要按32位字被访问。STM32的很多IO口都是5V兼容的,这些IO口在与5V电平的外设连接的时候很有优势,具体哪些IO口是5V兼容的,可以从该芯片的数据手册管脚描述章节查到(I/O Level标FT的就是5V电平兼容的)。
STM32的每个IO端口都有7个寄存器来控制。他们分别是:配置模式的2个32位的端口配置寄存器CRL和CRH;2个32位的数据寄存器IDR和ODR;1个32位的置位/复位寄存器BSRR;一个16位的复位寄存器BRR;1个32位的所存寄存器LCKR;这里我们仅介绍常用 的几个寄存器,我们常用的IO端口寄存器只有4个:CRL、CRH、IDR、ODR。
CRL和CRH控制着每个IO口的模式及输出速率。
STM32的IO口位配置表如表3.1.1.1所示:
 点击看大图
                      表3.1.1.1 STM32的IO口位配置表
STM32输出模式配置如表3.1.1.2所示:

点击看大图 
               表3.1.1.2 STM32输出模式配置表
 接下来我们看看端口低配置寄存器CRL的描述,如下图所示:
 点击看大图
                 图3.1.1.1 端口低配置寄存器CRL各位描述
该寄存器的复位值为0X4444 4444,从上图可以看到,复位值其实就是配置端口为浮空输入模式。从上图还可以得出:STM32的CRL控制着每个IO端口(A~G)的低8位的模式。每个IO端口的位占用CRL的4个位,高两位为CNF,低两位为MODE。这里我们可以记住几个常用的配置,比如0X4表示模拟输入模式(ADC用)、0X3表示推挽输出模式(做输出口用,50M速率)、0X8表示上/下拉输入模式(做输入口用)、0XB表示复用输出(使用IO口的第二功能,50M速率)。
CRH的作用和CRL完全一样,只是CRL控制的是低8位输出口,而CRH控制的是高8位输出口。这里我们对CRH就不做详细介绍了。
给个实例,比如我们要设置PORTC的11位为上拉输入,12位为推挽输出。代码如下:
GPIOC->CRH&=0XFFF00FFF;//清掉这2个位原来的设置,同时也不影响其他位的设置
GPIOC->CRH|=0X00038000;  //PC11输入,PC12输出
GPIOC->ODR=1<<11;//PC11上拉
通过这3句话的配置,我们就设置了PC11为上拉输入,PC12为推挽输出。
IDR是一个端口输入数据寄存器,只用了低16位。该寄存器为只读寄存器,并且只能以16位的形式读出。该寄存器各位的描述如下图所示:
 点击看大图
               图3.1.1.2 端口输入数据寄存器IDR各位描述
要想知道某个IO口的状态,你只要读这个寄存器,再看某个位的状态就可以了。使用起来是比较简单的。
ODR是一个端口输出数据寄存器,也只用了低16位。该寄存器虽然为可读写,但是从该寄存器读出来的数据都是0。只有写是有效的。其作用就是控制端口的输出。该寄存器的各位描述如下图所示:
 点击看大图
               图3.1.1.3 端口输出数据寄存器ODR各位描述

 

 


#include <stm32f10x_lib.h>   
#include "led.h"
//Mini STM32开发板
//LED驱动代码   
//正点原子@ALIENTEK
//2010/5/27

// V1.0
//初始化PA8和PD2为输出口.并使能这两个口的时钟     
 
//LED IO初始化
void LED_Init(void)
{
 RCC->APB2ENR|=1<<2;    //使能PORTA时钟     
 RCC->APB2ENR|=1<<5;    //使能PORTD时钟      
 GPIOA->CRH&=0XFFFFFFF0;
 GPIOA->CRH|=0X00000003;//PA8 推挽输出    
    GPIOA->ODR|=1<<8;      //PA8 输出高           
 GPIOD->CRL&=0XFFFFF0FF;
 GPIOD->CRL|=0X00000300;//PD.2推挽输出
 GPIOD->ODR|=1<<2;      //PD.2输出高
}
该代码里面就包含了一个函数void LED_Init(void),该函数的功能就是用来实现配置PA8和PD2为推挽输出。在配置STM32外设的时候,任何时候都要先使能该外设的时钟!APB2ENR是APB2总线上的外设时钟使能寄存器,其各位的描述如下:
 点击看大图
               图3.1.3.2 寄存器APB2ENR各位描述
我们要使能的PORTA和PORTD的时钟使能位,分别在bit2和bit5,只要将这两位置1就可以使能PORTA和PORTD的时钟了。该寄存器还包括了很多其他外设的时钟使能。大家在以后会慢慢使用到的。关于这个寄存器的详细说明在《STM32参考手册》的第61页。
在设置完时钟之后就是配置完时钟之后,LED_Init配置了PA8和PD2的模式为推挽输出,并且默认输出1。这样就完成了对这两个IO口的初始化。
保存led.c代码,然后我们按同样的方法,新建一个led.h文件,也保存在LED文件夹下面。在led.h中输入如下代码:
#ifndef __LED_H
#define __LED_H 
#include "sys.h"
//Mini STM32开发板
//LED驱动代码   
//正点原子@ALIENTEK
//2010/5/27
//LED端口定义
#define LED0 PAout(8)// PA8
#define LED1 PDout(2)// PD2 
void LED_Init(void);//初始化          
#endif
这段代码里面最关键就是2个宏定义:
#define LED0 PAout(8)// PA8
#define LED1 PDout(2)// PD2
这里使用的是位带操作来实现操作某个IO口的1个位的,关于位带操作前面已经有介绍,这里不再多说。需要说明的是,这里可以使用另外一种操作方式实现。如下:
#define LED0 (1<<8)  //led0 PA8
#define LED1 (1<<2)  //led1 PD2
#define LED0_SET(x) GPIOA->ODR=(GPIOA->ODR&~LED0)|(x ? LED0:0)
#define LED1_SET(x) GPIOD->ODR=(GPIOD->ODR&~LED1)|(x ? LED1:0) 
后者通过LED0_SET(0)和LED0_SET(1)来控制PA8的输出0和1。而前者的类似操作为:LED0=0和LED0=1。显然前者简单很多,从而可以看出位带操作带来的好处。以后像这样的IO口操作,我们都使用位带操作来实现,而不使用第二种方法。

转自正点原子博客

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章