weixin_58085011 2024-02-07 22:56 采纳率: 75%
浏览 8
已结题

动态判断外部电路是否接通

想用STM32编一个动态判断外部电路是否接通的程序:如果接通就认为满足条件(标志位置1),可以执行下一步动作。在执行过程中外部电路状态可能发生改变,希望系统能一直监控并更新标志位。
用杜邦线连接3V3模拟外部电路导通,拔掉杜邦线模拟断开。
自己用中断方式试着实现了一下,断开电路(拔掉杜邦线)时响应过于频繁,连续有15个左右的中断,然后就不再响应了。怀疑是信号抖动,在中断响应程序里加了延时后中断干脆不响应了。
想请教一下有经验的人士指教一下,如何实现

  • 写回答

5条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-02-07 22:57
    关注

    引自免费微信小程序:皆我百晓生

    针对您的问题,您想在STM32上编写一个程序,动态检测外部电路的通断状态,并通过标志位控制后续操作。当拔插杜邦线时,中断过于频繁且可能存在信号抖动。下面我将提供一种基于GPIO输入和软件滤波的方式来解决这个问题:

    首先,确保您已经正确配置了GPIO引脚作为外部输入,并启用相应的外部中断(比如上升沿和下降沿)。这里我们假设使用的是PA0引脚:

    #include "stm32f10x.h"
    
    // 初始化GPIO及中断
    void GPIO_Init(void)
    {
        GPIO_InitTypeDef GPIO_InitStructure;
    
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 开启GPIOA时钟
    
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;  // PA0
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // 上拉输入
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    
        GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); // 配置EXTI线
        EXTI_InitTypeDef EXTI_InitStructure;
        EXTI_InitStructure.EXTI_Line = EXTI_Line0; // 对应PA0
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling | EXTI_Trigger_Rising; // 双边沿触发
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;
        EXTI_Init(&EXTI_InitStructure);
    
        NVIC_InitTypeDef NVIC_InitStructure;
        NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; // EXTI0通道中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
    }
    
    volatile bool circuit_connected = false; // 中断服务程序中更新的全局标志位
    
    // EXTI0中断服务程序
    void EXTI0_IRQHandler(void)
    {
        if(EXTI_GetITStatus(EXTI_Line0) != RESET)
        {
            EXTI_ClearITPendingBit(EXTI_Line0); // 清除中断标志
    
            static uint8_t debounce_counter = 0;
            static bool previous_state = !circuit_connected; // 记录前一次的状态
    
            GPIO_PinState current_state = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
    
            // 软件去抖动:连续检测n次(例如n=5)状态稳定才认为状态改变有效
            if(current_state != previous_state)
            {
                debounce_counter++;
                if(debounce_counter == DEBOUNCE_THRESHOLD)
                {
                    debounce_counter = 0;
                    circuit_connected = current_state; // 更新电路连接状态
                }
            }
            else
            {
                debounce_counter = 0;
            }
    
            previous_state = current_state;
        }
    }
    
    int main(void)
    {
        // ... 其他初始化代码 ...
    
        GPIO_Init(); // 初始化GPIO和中断
        while(1)
        {
            if(circuit_connected)
            {
                // 执行下一步动作
                // ...
            }
        }
    }
    

    请注意,在上述代码中,DEBOUNCE_THRESHOLD 是一个自定义的常量,用于设置去抖动的次数阈值,您可以根据实际情况调整该值以适应不同的硬件环境和需求。

    此外,由于无法实际模拟图片,请确保您的硬件接线没有问题,同时适当增大电阻(如10K欧姆)以减小接触电阻导致的信号干扰和电平变化速率,从而降低抖动的可能性。如果仍然存在问题,请检查MCU的工作模式、电源管理以及其它可能影响到中断响应的因素。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 2月21日
  • 已采纳回答 2月13日
  • 创建了问题 2月7日

悬赏问题

  • ¥15 ESP32CAM使用报错
  • ¥15 c#对datatable 所有列查询,符合条件的列替换数据
  • ¥15 ise14.7烧写flash失败
  • ¥100 ICEM3-4度尖角位置能不能将质量提升到0.2甚至更高
  • ¥15 在网页上点击view PDF或者open PDF之类的选项加载很慢甚至加载不出来,换网或浏览器都不行
  • ¥115 不能成功安装R语言pathview包
  • ¥15 LEfSe在线分析Galaxy报错,如何解决?
  • ¥15 GTEx数据库eqtl数据整理求教学
  • ¥15 初学者,自己写的js俄罗斯代码,谁能帮我调试并找出问题所在!! 自己调试了好多遍!快乱了,崩溃了!
  • ¥15 qt 编译webengine 支持 webgl