HAL GPIO中断函数里区分下降沿和上升沿

 CubeMX按如下设置:

 

 

 

在main.c中添加中断响应函数:

/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	//外界消抖按键,实现按键与LED同步亮灯
    if(GPIO_Pin==KEY_Pin)   
  {
	if(HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin)){ //check pin state 
            HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET);
        }
        
        if(!HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin)){
            HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);
        }
 }
}

编译下载,外部接消抖按键和LED,即可实现按键与LED同步点亮。

### 使用STM32 HAL实现外部中断精确捕获上升沿下降沿时间戳 为了使用 STM32 的 HAL 通过外部中断来精确捕获信号的上升沿下降沿时间戳,可以按照如下方式配置 GPIO EXTI 中断,并利用 TIM 定时器记录事件发生的时间。 #### 配置 GPIO 及 EXTI 中断 首先,在初始化阶段设置好用于检测边沿变化的引脚。这假设使用的是 PA0 这个引脚作为外部中断源: ```c // 初始化GPIO并使能EXTI线上的中断请求 void MX_GPIO_Init(void) { __HAL_RCC_GPIOA_CLK_ENABLE(); // 开启PA端口时钟 GPIO_InitTypeDef GPIO_InitStruct = {0}; /* 配置PA0为输入模式 */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; // 上升沿/下降沿触发中断 GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 设置NVIC优先级组分组 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); // 使能EXTI线0对应的中断向量位 HAL_NVIC_EnableIRQ(EXTI0_IRQn); // 设置中断优先级 HAL_NVIC_SetPriority(EXTI0_IRQn, 15, 0); } ``` 这段代码完成了对 GPIOA 的第 0 脚 (即 PA0) 的初始化工作,将其设为上下拉电阻关闭的状态下等待来自该管脚上发生的电平跳变所引发的硬件中断[^1]。 #### 利用定时器获取高精度时间戳 为了让程序能够获得每次中断到来的确切时刻,还需要启动一个运行频率足够高的计数型定时器(比如 SysTick 或者通用定时器),以便于从中读取当前经过了多少个周期从而计算出实际经历的时间长度。下面是一个简单的例子展示如何操作 TIMx 来完成这一目标: ```c static uint32_t lastCaptureTime RisingEdgeTimestamp FallingEdgeTimestamp; /* 外部中断服务函数 */ void EXTI0_IRQHandler(void) { if (__HAL_GPIO_EXTI_GET_FLAG(GPIO_PIN_0)) { // 清除标志位以防重复响应同一事件 __HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_0); // 获取当前定时器值 uint32_t currentTimerValue = __HAL_TIM_GET_COUNTER(&htimX); if(HAL_GetRE()) RisingEdgeTimestamp = currentTimerValue - lastCaptureTime; else FallingEdgeTimestamp = currentTimerValue - lastCaptureTime; lastCaptureTime = currentTimerValue; } } // 在主循环或其他地方调用此函数以更新全局变量中的最新一次捕捉到的时间差值 void UpdateEdgeDurations() { static bool isFirstRun = true; if(isFirstRun || !__HAL_TIM_IS_TIM_COUNTING_DOWN(&htimX)){ isFirstRun=false; htimX.Instance->CNT=0;//重置计数值 }else{ // 如果是向下计数,则需做相应调整... } } ``` 在此基础上,当有新的上升沿下降沿被探测到时就会自动进入 `EXTI0_IRQHandler` 函数体内执行相应的逻辑运算,进而得到两个相邻状态转变之间间隔多长时间的信息[^2]。 需要注意的是,上述代码片段仅提供了一种基本思路框架下的解决方案示意;具体应用过程中可能还需考虑更多细节因素的影响,如不同型号芯片间寄存器定义差异、特定应用场景下的性能优化需求等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

armcsdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值