OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2052|回复: 0

嵌入式STM32之GPIO

[复制链接]

132

主题

340

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1036
金钱
1036
注册时间
2017-10-30
在线时间
163 小时
发表于 2018-1-22 14:21:22 | 显示全部楼层 |阅读模式
1、GPIO介绍
每个通用IO口都有四个32位的配置寄存器,分别是:
- GPIOx_MODER   : 模式设置- GPIOx_OTYPER  :类型设置- GPIOx_OSPEEDR :速度选择- GPIOx_PUPDR   :上拉下拉
两个32位的数据寄存,分别是:
- GPIOx_IDR  : 输入数据寄存器- GPIOx_ODR  :输出数据寄存器
一个32位的设置/复位寄存器:
- GPIOx_BSRR
一个32位的锁存器:
- GPIOx_LCKR
两个附加功能选择寄存器:
- GPIOx_AFRH : 高32位- GPIOx_AFRL :低32位
每个GPIO段都有16个引出引脚以供使用,引脚标号是Px0~Px15,这点与K60有区别
2、主要电气特性
输出状态: 上拉下拉,全推挽输出,开漏
从数据输出寄存器(GPIOx_ODR)或者外围设备(alternate function output)输出数据到IO引脚
每个IO口可选时钟速度
输入状态: 浮点,上拉下拉,逻辑
从数据输入寄存器(GPIOx_IDR)或者外围设备(alternate function input)输入数据到IO引脚
位操作寄存器(GPIOx_BSRR)用来对GPIOx_ODR进行位操作
3、输入配置
1.输出缓冲禁止
2.施密特触发输入激活
3.上拉下拉电阻状态取决于GPIOx_PUPDR寄存器的值
4.IO口当前状态每个AHB1时钟周期都会被送入输入数据寄存器
5.对输入数据寄存器的读操作获得IO口的状态
4、输出配置
1.输出缓冲使能:
o开漏模式: 输出寄存器赋值为0激活 N-MOS 而1则是处于高阻状态 (P-MOS 不会被激活)
o推挽模式: 输出寄存器赋值为0激活 N-MOS 输出寄存器赋值为1激活 P-MOS
2.施密特触发输入激活
3.弱上拉下拉电阻被激活
4.IO口当前状态每个AHB1时钟周期都会被送入输入数据寄存器
5.对输入数据寄存器的读操作获得IO口的状态
6.对输出数据寄存器的读操作获得最后一次写入的状态
5、特殊功能配置
1.输出配置为开漏或者推挽
2.输出缓冲区被来自外设的信号支配
3.施密特触发输入激活
4.弱上拉下拉电阻被激活
5.IO口当前状态每个AHB1时钟周期都会被送入输入数据寄存器
6.对输入数据寄存器的读操作获得IO口的状态
6、GPIO操作实例之LED灯的操作(PF9 PF10)
//外设的基地址#define PERIPH_BASE           ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region
//各个总线的基地址#define APB1PERIPH_BASE       PERIPH_BASE#define APB2PERIPH_BASE       (PERIPH_BASE + 0x00010000)#define AHB1PERIPH_BASE       (PERIPH_BASE + 0x00020000)#define AHB2PERIPH_BASE       (PERIPH_BASE + 0x10000000)
//AHB1外设节选/*!< AHB1 peripherals */#define GPIOA_BASE            (AHB1PERIPH_BASE + 0x0000)#define GPIOB_BASE            (AHB1PERIPH_BASE + 0x0400)#define GPIOC_BASE            (AHB1PERIPH_BASE + 0x0800)#define GPIOD_BASE            (AHB1PERIPH_BASE + 0x0C00)#define GPIOE_BASE            (AHB1PERIPH_BASE + 0x1000)#define GPIOF_BASE            (AHB1PERIPH_BASE + 0x1400)#define GPIOG_BASE            (AHB1PERIPH_BASE + 0x1800)#define GPIOH_BASE            (AHB1PERIPH_BASE + 0x1C00)#define GPIOI_BASE            (AHB1PERIPH_BASE + 0x2000)#define GPIOJ_BASE            (AHB1PERIPH_BASE + 0x2400)#define GPIOK_BASE            (AHB1PERIPH_BASE + 0x2800)
实例之:一个简单的gpio初始化
void gpio_init(GPIOx_SELECT gpiox, GPIOx_pn_SELECT gpiox_pn, \
               GPIO_PULL_TYPE pull, GPIO_IO_TYPE io, GPIO_STATUS_TYPE stat, GPIO_OUTPUT_TYPE otype)
{
    GPIO_TypeDef *GPIOx;

    /* Get the GPIOx's GPIO_TypeDef struct */
    GPIOx = BYM_GET_GPIO_struct(gpiox);

    RCC->AHB1ENR  |= (1 << gpiox);  //Enable the clock of GPIOx

    /* Set the io type of GPIOx's pn */
    GPIOx->MODER  &= ~(3 << (gpiox_pn * 2));       //Clear the old register data
    GPIOx->MODER  |= (io << (gpiox_pn * 2));        //Set the mode of GPIOx's pn

    /* Set the io ouput type of GPIOx's pn */
    GPIOx->OTYPER &= ~(1 << gpiox_pn);             //Clear the old register data
    GPIOx->OTYPER |= (otype << gpiox_pn);           //Set the output type of GPIOx's pn

    /* Pull down or pull up or nothing for GPIOx's pn */
    GPIOx->PUPDR  &= ~(3 << (gpiox_pn * 2));       //Clear the old register data
    GPIOx->PUPDR  |= (pull << (gpiox_pn * 2));

    /* Only set the pin status when the 'io' value is 'BYM_GPO' */
    if(io == BYM_GPO)
    {
        GPIOx->ODR  &= ~(1 << gpiox_pn);
        GPIOx->ODR  |= (stat << gpiox_pn);
    }   
}
实例之:获取IO口状态
/*
* Get GPIO pin status
*/
uint32_t gpio_get(GPIOx_SELECT gpiox, GPIOx_pn_SELECT gpiox_pn)
{
    GPIO_TypeDef *GPIOx;

    /* Get the GPIOx's GPIO_TypeDef struct */
    GPIOx = BYM_GET_GPIO_struct(gpiox);

    return ((GPIOx->IDR) & (1 << gpiox_pn));
}
//枚举变量的定义/* GPIO 段的选择枚举 */typedef enum
{
    BYM_GPIOA, BYM_GPIOB, BYM_GPIOC, BYM_GPIOD,
    BYM_GPIOE, BYM_GPIOF, BYM_GPIOG, BYM_GPIOH,
    BYM_GPIOI, BYM_GPIOJ, BYM_GPIOK,
}GPIOx_SELECT;
/* GPIO管脚号的选择枚举 */typedef enum
{
    BYM_Px0,    BYM_Px1,    BYM_Px2,    BYM_Px3,    BYM_Px4,    BYM_Px5,    BYM_Px6,    BYM_Px7,
    BYM_Px8,    BYM_Px9,    BYM_Px10,   BYM_Px11,   BYM_Px12,   BYM_Px13,   BYM_Px14,   BYM_Px15,
}GPIOx_pn_SELECT;
/* 上拉下拉的枚举 */typedef enum
{
    BYM_NO_PULL,
    BYM_PULL_UP,
    BYM_PULL_DOWN,
}GPIO_PULL_TYPE;
/* 输出模式枚举 */typedef enum
{
    BYM_PUSH_PULL,
    BYM_OPEN_DRAIN,
}GPIO_OUTPUT_TYPE;
/* IO管脚复用模式枚举 */typedef enum
{
    BYM_GPI,    BYM_GPO,
    BYM_GPALT,  BYM_GPANA,
}GPIO_IO_TYPE;
/* 当管脚设置为输出的时候管脚状态的枚举 */typedef enum
{
    BYM_LOW_LEVEL,
    BYM_HIGH_LEVEL,
}GPIO_STATUS_TYPE;
/* Get the GPIO's GPIO_TypeDef struct */#define BYM_GET_GPIO_struct(gpiox) \
    ((GPIO_TypeDef *)(AHB1PERIPH_BASE + (gpiox * 0x400)))
7、GPIO口的不同附加外设功能
AF0     system
AF1     TIM1/TIM2
AF2     TIM3~TIM5
AF3     TIM8~TIM11
AF4     I2C1~I2C3
AF5     SPI1~SPI2
AF6     SPI3
AF7     USART1~USART3
AF8     USART4~USART6
AF9     CAN1/CAN2,TIM12~TIM14
AF10    OTG_FS,OTG_HS
AF11    ETH
AF12    FSMC,SDIO,OTG_HS(1)
AF13    DCMI
AF14   
AF15    EVENTOUT
8、管脚锁存
&#61623;
管脚锁存通过寄存器的一系列操作之后达到gpio管脚状态锁定,直到下一次CPU复位或者gpio管脚模块复位时才允许改变状态
&#61623;
&#61623;
操作步骤,通过向GPIOx_LCKR寄存器进行写操作来完成
&#61623;
WR LCKR[16] = ‘1’ + LCKR[15:0]
WR LCKR[16] = ‘0’ + LCKR[15:0]
WR LCKR[16] = ‘1’ + LCKR[15:0]/* 上面三步是要求的操作步骤 */
RD LCKR
RD LCKR[16] = ‘1’ /* 上面两步是为了保证gpio管脚状态被成功的设置了 */
9、一个GPIO口初始化过程
&#61623;设置该GPIO段时钟开启(所有的芯片片内外设均需要先开启时钟),AHB1ENR(GPIO属于AHB1总线)
&#61623;选择该段需要设置的GPIO管脚号
&#61623;对其寄存器进行模式设置,包括输入输出方式,速度,引脚复用,上拉下拉等等
10、与51系列8位单片机IO口的主要区别
&#61623;
不同点:
&#61623;
o可选的上拉下拉电阻
o可设置的IO频率
o可锁存
o明确的输入输出状态
&#61623;
相同点:
&#61623;
o都可设置外设功能
o都有推挽、开漏、普通IO口三种模式
创客学院最新视频尽在:www.makeru.com.cn
嵌入式学习交流群:561213221
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-9 04:17

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表