stm32f103端口置位复位函数

博客介绍了GPIO宏定义的原理,如GPIO_Pin_x对应不同的引脚,并展示了如何通过设置BSRR和BRR寄存器实现端口的置位和复位函数,从而控制微控制器的输入输出状态。

宏定义

#define GPIO_Pin_0   ((uint16_t)0x0001) /*!<选择Pin0*/ //(00000000 00000001)b
#define GPIO_Pin_1   ((uint16_t)0x0002) /*!<选择Pin1*/ //(00000000 00000010)b
#define GPIO_Pin_2   ((uint16_t)0x0004) /*!<选择Pin2*/ //(00000000 00000100)b
#define GPIO_Pin_3   ((uint16_t)0x0008) /*!<选择Pin3*/ //(00000000 00001000)b
#define GPIO_Pin_4   ((uint16_t)0x0010) /*!<选择Pin4*/ //(00000000 00010000)b
#define GPIO_Pin_5   ((uint16_t)0x0020) /*!<选择Pin5*/ //(00000000 00100000)b
#define GPIO_Pin_6   ((uint16_t)0x0040) /*!<选择Pin6*/ //(00000000 01000000)b
#define GPIO_Pin_7   ((uint16_t)0x0080) /*!<选择Pin7*/ //(00000000 10000000)b

#define GPIO_Pin_8    ((uint16_t)0x0100) /*!<选择Pin8*/      //(00000001 00000001)b
#define GPIO_Pin_9    ((uint16_t)0x0200) /*!<选择Pin9*/      //(00000010 00000010)b
#define GPIO_Pin_10   ((uint16_t)0x0400) /*!<选择Pin10*/     //(00000100 00000100)b
#define GPIO_Pin_11   ((uint16_t)0x0800) /*!<选择Pin11*/     //(00001000 00001000)b
#define GPIO_Pin_12   ((uint16_t)0x1000) /*!<选择Pin12*/     //(00010000 00010000)b
#define GPIO_Pin_13   ((uint16_t)0x2000) /*!<选择Pin13*/     //(00100000 00100000)b
#define GPIO_Pin_14   ((uint16_t)0x4000) /*!<选择Pin14*/     //(01000000 01000000)b
#define GPIO_Pin_15   ((uint16_t)0x8000) /*!<选择Pin15*/     //(10000000 10000000)b
#define GPIO_Pin_AII  ((uint16_t)0xFFFF) /*!<选择全部引脚*/  //(11111111 11111111)b

端口置位函数

通过控制BSRR寄存器来置位

低16位的端口置1则对应的端口输出1

void GPIO_SetBits(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin)
{
  GPIOx->BSRR |= GPIO_Pin;
}

 

端口复位函数 

通过控制BRR寄存器来复位

低16位的端口置1则对应的端口输出0

<think> 我们正在讨论STM32F103的GPIO_ResetBits函数。根据引用[1]和引用[2],这个函数用于将指定的GPIO引脚输出低电平(即拉低引脚)。在标准外设库中,它的实现通常是通过操作BRR寄存器(Bit Reset Register)来完成的。 ### STM32F103 GPIO_ResetBits函数详解 #### 一、函数原型 在标准外设库中,函数原型通常定义如下(参考`stm32f10x_gpio.h`): ```c void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); ``` - **参数1**:`GPIOx`,指定GPIO端口(如GPIOA, GPIOB, ...) - **参数2**:`GPIO_Pin`,指定要操作的引脚(使用宏`GPIO_Pin_n`,其中n为0-15) #### 二、函数功能 该函数将指定GPIO的一个或多个引脚设为低电平(逻辑0)。它通过写BRR寄存器的对应来实现: - **操作原理**:向BRR寄存器的对应写1会复位(拉低)对应的引脚输出,而写0则不影响当前状态。 - **原子操作**:由于直接写BRR寄存器,避免了读-改-写操作,因此是原子操作。 #### 三、底层实现 参考引用[1]中的示例代码(注意:标准库的实现可能略有不同,但原理一致): ```c void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) { GPIOx->BRR = GPIO_Pin; // 直接写BRR寄存器 } ``` **注意**:在标准库的实际实现中,通常使用赋值操作(`=`)而不是按或(`|=`),因为BRR寄存器具有写1有效、写0无效的特性,且我们通常希望同时复位多个引脚时,直接赋值即可覆盖所有指定引脚。 #### 四、寄存器映射 - **BRR寄存器**(Bit Reset Register): - 地址偏移:`0x14`(相对于GPIO端口基地址) - 分配:160-15),每对应一个引脚 - 操作规则:写1将对应引脚的输出复位(拉低),写0无影响 #### 五、与BSRR寄存器的关系 BRR寄存器实际上相当于BSRR寄存器的高16复位控制)的简化版本。在STM32F103中,可以使用BSRR的高16实现同样的功能: ```c // 使用BSRR实现复位功能(将引脚拉低) GPIOx->BSRR = (uint32_t)GPIO_Pin << 16; ``` 而`GPIO_ResetBits`函数内部使用的是BRR寄存器(地址偏移0x14),其操作等同于BSRR的高16,但BRR是一个16寄存器(实际是32寄存器中的低16有效,高16保留)。 #### 六、使用示例 控制PA5引脚输出低电平: ```c GPIO_ResetBits(GPIOA, GPIO_Pin_5); ``` 同时控制多个引脚(如PA5和PA6): ```c GPIO_ResetBits(GPIOA, GPIO_Pin_5 | GPIO_Pin_6); ``` #### 七、注意事项 1. **原子性**:与BSRR类似,BRR寄存器的写操作也是原子的,因此无需担心在操作过程中被中断打断。 2. **端口**:在使用该函数前,必须确保相应的引脚已经配为**输出模式**(推挽或开漏),否则操作无效。 3. **开漏模式**:当引脚配为开漏输出时,拉低操作会使引脚输出低电平,而拉高操作(使用`GPIO_SetBits`)实际上是将输出为高阻(需要外部上拉电阻才能产生高电平)。 #### 八、替代方案 在标准库中,也可以使用BSRR寄存器同时实现复位。例如,同时复位多个引脚: ```c // 将PA5(高电平),PA6复位(低电平) GPIOA->BSRR = GPIO_Pin_5 | (GPIO_Pin_6 << 16); ``` 因此,一些应用可能更倾向于直接操作BSRR寄存器,因为它可以一次性完成多个引脚的复位操作。 ### 总结 `GPIO_ResetBits`是STM32标准外设库中用于拉低GPIO引脚输出的函数,通过写BRR寄存器实现。它提供了一种简单、原子且高效的方式来控制GPIO输出状态。 [^1]: STM32F103标准外设库源码分析(stm32f10x_gpio.c) [^2]: GPIO输出控制原理及LED驱动实践 §§相关问题§§ 1. 为什么在STM32中推荐使用BSRR/BRR寄存器而不是直接操作ODR来控制GPIO输出? 2. GPIO_ResetBits函数在中断服务程序中使用是否安全? 3. 如何同时设多个GPIO引脚为高电平和低电平? 4. 当GPIO配为开漏输出模式时,GPIO_ResetBits函数的行为是什么? </think> ### STM32F103 GPIO_ResetBits函数详解 #### 一、函数功能与作用 `GPIO_ResetBits`是STM32标准外设库中的核心函数,用于将指定GPIO引脚输出**低电平**(逻辑0)。该函数通过操作BRR寄存器(Bit Reset Register)实现,具有原子操作特性,适用于精确控制外设状态(如LED熄灭、继电器断开等)[^1][^2]。 #### 二、函数原型 ```c void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); ``` - **GPIOx**:目标GPIO端口指针(如GPIOA, GPIOB等) - **GPIO_Pin**:目标引脚掩码(使用`GPIO_Pin_n`宏定义) #### 三、底层实现原理 在标准库源码中(`stm32f10x_gpio.c`),函数实现为: ```c void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) { GPIOx->BRR = GPIO_Pin; // 直接写入BRR寄存器 } ``` 等价于寄存器级操作: ```c GPIOx->BRR = GPIO_Pin_xx; // 如GPIOA->BRR = GPIO_Pin_5 ``` #### 四、寄存器映射机制 操作对应BRR寄存器: 1. **地址偏移**:$0x14$(相对GPIO基地址) 2. **域功能**: - 0-15:引脚复位控制 - 写1:对应引脚输出低电平 - 写0:无操作 3. **原子性**:单次写操作完成,无读-改-写过程 #### 五、典型使用场景 1. **LED控制**: ```c // 熄灭PB0连接的LED GPIO_ResetBits(GPIOB, GPIO_Pin_0); ``` 2. **多引脚同步控制**: ```c // 同时拉低PA3和PA7 GPIO_ResetBits(GPIOA, GPIO_Pin_3 | GPIO_Pin_7); ``` 3. **脉冲信号生成**: ```c // 产生低脉冲 GPIO_SetBits(GPIOA, GPIO_Pin_6); // 先高 delay_us(10); GPIO_ResetBits(GPIOA, GPIO_Pin_6); // 再低 ``` #### 六、与BSRR寄存器的关系 | 特性 | GPIO_ResetBits (BRR) | BSRR高16 | |------------|------------------------------|-----------------------| | **操作** | 专用复位操作 | 复位功能同BRR | | **地址** | $0x14$ | $0x10$ (高16) | | **推荐度** | 兼容旧代码 | ★★★★☆ (推荐) | ```c // 两种等效实现: GPIO_ResetBits(GPIOA, GPIO_Pin_4); // 方式1:BRR寄存器 GPIOA->BSRR = GPIO_Pin_4 << 16; // 方式2:BSRR高16 ``` #### 七、使用注意事项 1. **模式配**:引脚必须配为输出模式(推挽/开漏) 2. **中断安全**:在中断中操作时需考虑优先级冲突 3. **性能对比**: ```c // 不推荐的传统ODR操作(非原子) GPIOA->ODR &= ~GPIO_Pin_5; // 需读-改-写操作 // 推荐使用ResetBits(原子操作) GPIO_ResetBits(GPIOA, GPIO_Pin_5); ``` #### 八、开漏输出模式特殊处理 当GPIO配为开漏输出时: ```c // 开漏模式下拉低引脚 GPIO_ResetBits(GPIOB, GPIO_Pin_8); // 输出强低电平 // 开漏模式拉高实际为高阻态 GPIO_SetBits(GPIOB, GPIO_Pin_8); // 需外部上拉 ``` > **最佳实践**:在新代码中优先使用BSRR寄存器(可同时操作/复位),但`GPIO_ResetBits`在维护旧代码时仍有重要价值[^1][^2]。 [^1]: STM32F10x标准外设库源码分析(stm32f10x_gpio.c) [^2]: GPIO输出控制原理及LED驱动实践
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值