Timer 与按键消抖的应用(复盘总结)

HAL库下的systick 底层配置 HAL_Delay实现原理 微秒级延时(非中断)以及一些重写延时的小坑 关于HAL_Delay的使用问题 systick HAL_Delay实现原理 微秒级延时(非中断)以及一些重写延时的小坑 关于HAL_Delay的使用问题HAL_Delay实现原理HAL库下的systick 底层配置实现微妙级的延时重写延时的小坑关于HAL_Delay的使用问题 HAL_Delay实现原理 HAL_Delay 底层是配置systick进行1ms进行一次中断,没进入一次,有一个全局变量 uwTick 就加1 上面这个函数就是systick的中断函数 下面就是 计数的函数 void SysTick_Handler(void) 阅读详情

         因为通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。

         消抖是为了避免在按键按下或是抬起时电平剧烈抖动带来的影响。按键的消抖,可用硬件或软件两种方法,在实际的设计中,为了节省硬件成本,大多数情况会选择使用软件消抖。 

延时消抖

        软件消抖,即检测出按键闭合后执行一个延时程序,5ms~10ms 的延时,让前沿抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认为真正有键按下。当检测到按键释放后,也要给 5ms~10ms 的延时,待后沿抖动消失后才能转入该键的处理程序。

        以前常用的消抖算法往往就是:判断按下->延时->再次判断是否按下->是,执行/否,退出。

        最简单的消抖原理,就是当检测到按键状态变化后,先等待一个 10ms 左右的延时时间,让抖动消失后再进行一次按键状态检测,如果与刚才检测到的状态相同,就可以确认按键已经稳定的动作了。

//按键处理函数 
void ButtonScan(void)
{     
    static int ButtonFlag = 0;//按键标志,1代表松开,0代表按下

    if(Button == 0)//第一次判断按键按下
    {
        delay_ms(10);//延时10ms,去抖动
        if(Button == 0)//第二次判断按键按下
        {
            ButtonFlag = 1;    //确认按键为按下,按键标志置1
        }        
}

 利用定时器消抖

        利用定时器消抖算法:通过 SysTick 中断每1ms对按键进行扫描,当检测到连续的稳定无抖动电平信号(长度可设置)之后,才进行相应的逻辑操作。

        启用一个定时中断,每 1ms 进一次中断,扫描一次按键状态并且存储起来,连续扫描 25 次后,看看这连续 25 次的按键状态是否是一致的。25 次按键的时间是 25ms,这 25ms 内如果按键状态一直保持一致,那就可以确定现在按键处于稳定的阶段,而非处于抖动的阶段。

对 SYS 进行了配置

在 STM32CubeMX 中,默认 SysTick 中断为 1ms。 我们可以打开 MDK-ARM 工程,在左侧 Drivers/STM32F1xx_HAL_Driver 文件夹的 stm32f1xx_hal.c 文件中找到 SysTick 的初始化。

/**
  * @brief This function configures the source of the time base.
  *        The time source is configured  to have 1ms time base with a dedicated
  *        Tick interrupt priority.
  * @note This function is called  automatically at the beginning of program after
  *       reset by HAL_Init() or at any time when clock is reconfigured  by HAL_RCC_ClockConfig().
  * @note In the default implementation, SysTick timer is the source of time base.
  *       It is used to generate interrupts at regular time intervals.
  *       Care must be taken if HAL_Delay() is called from a peripheral ISR process,
  *       The SysTick interrupt must have higher priority (numerically lower)
  *       than the peripheral interrupt. Otherwise the caller ISR process will be blocked.
  *       The function is declared as __weak  to be overwritten  in case of other
  *       implementation  in user file.
  * @param TickPriority Tick interrupt priority.
  * @retval HAL status
  */
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
  /* Configure the SysTick to have interrupt in 1ms time basis*/
  if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
  {
    return HAL_ERROR;
  }

  /* Configure the SysTick IRQ priority */
  if (TickPriority < (1UL << __NVIC_PRIO_BITS))
  {
    HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
    uwTickPrio = TickPriority;
  }
  else
  {
    return HAL_ERROR;
  }

  /* Return function status */
  return HAL_OK;
}

函数里面有一句注释: /* Configure the SysTick to have interrupt in 1ms time basis*/,翻译过来就是,将 SysTick 配置为 1ms 中断。也就是说,经过此函数,SysTick 定时器被初始化为 1ms 的时基单元,即每毫秒进入一次 Systick 中断。

我们可以在左侧 Application/User 文件夹的 stm32f1xx_it.c 文件中找到 SysTick 中断服务函数。

/**
  * @brief This function handles System tick timer.
  */
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}

里面只有一个 HAL_IncTick() 函数,我们右键转跳到该函数可以看到该函数的定义。

 

/**
  * @brief This function is called to increment  a global variable "uwTick"
  *        used as application time base.
  * @note In the default implementation, this variable is incremented each 1ms
  *       in SysTick ISR.
  * @note This function is declared as __weak to be overwritten in case of other
  *      implementations in user file.
  * @retval None
  */
__weak void HAL_IncTick(void)
{
  uwTick += uwTickFreq;
}

每毫秒 uwTick 加一,用于计算 Systick 产生的节拍数。

在 HAL_IncTick 函数的下方有一个 HAL_GetTick(void) 函数,主要用于获取当前节拍,如果内核正常运行,则 uwTick 的值即为已经经过的 ms 数。

这里顺便提及一下 HAL 库的延时函数 HAL_Delay() 。在左侧 Drivers/STM32F1xx_HAL_Driver 文件夹的 stm32f1xx_hal.c 文件中找到 HAL_Delay() 函数。

/**
  * @brief This function provides minimum delay (in milliseconds) based
  *        on variable incremented.
  * @note In the default implementation , SysTick timer is the source of time base.
  *       It is used to generate interrupts at regular time intervals where uwTick
  *       is incremented.
  * @note This function is declared as __weak to be overwritten in case of other
  *       implementations in user file.
  * @param Delay specifies the delay time length, in milliseconds.
  * @retval None
  */
__weak void HAL_Delay(uint32_t Delay)
{
  uint32_t tickstart = HAL_GetTick();
  uint32_t wait = Delay;

  /* Add a freq to guarantee minimum wait */
  if (wait < HAL_MAX_DELAY)
  {
    wait += (uint32_t)(uwTickFreq);
  }

  while ((HAL_GetTick() - tickstart) < wait)
  {
  }
}

可以看到 HAL_Delay() 函数其实就是通过 HAL_GetTick() 函数数节拍以确定精准的延时。

        回到按键消抖的主题,既然 STM32CubeMX 已经默认设置 Systick 为 1ms 中断,那么我们可以直接利用起来。打开 MDK-ARM 工程,按下组合键 Ctrl+N(按住 Ctrl 键再按 N 键),新建一个文件,再按下组合键 Ctrl+S,文件名改为 button.c,保存到 MiaowLabs-DEMO 的 Src 文件夹里。来到这里,我们虽然新建了button.c 源文件,但是还没有把该文件加入到 MDK-ARM 工程里。我们在 MDK-ARM 工程界面左侧 Project 栏目双击 Application/User 文件夹,把 button.c 加进来。

双击 button.c 文件,把下面代码敲进去。

#include "button.h"
#include "main.h"
#include "stm32f1xx_it.h"

int iButtonCount;//i代表int型变量,ButtonCount表示按键计数变量
int iButtonFlag;//i代表int型变量,ButtonFlag表示重按键标志,1代表重新按键,0为没有重新按键
int g_iButtonState;//g是globle代表全局变量,会在其他地方引用;i代表int型变量,ButtonState表示按键标志,1代表按下,0代表松开
void ButtonScan(void){
  if(   HAL_GPIO_ReadPin(Button_GPIO_Port,Button_Pin) == GPIO_PIN_RESET )//如果引脚检测到低电平
  {
      iButtonCount++;                         //按键按下,计数iButtonCount加1
      if(iButtonCount>=30)                    //1ms中断服务函数里运行一次,iButtonCount大于等于30,即按键已稳定按下30ms
         {
            if(iButtonFlag==0)                  //判断有没有重按键,1为有,0为没有
                {
                    g_iButtonState=1;                 //设置按键标志
                    iButtonCount=0;
                    iButtonFlag=1;                  //设置重按键标志
                    }
                else                              //如果重按键,则重新计数
                    iButtonCount=0;
                }
    else                                  //如果没有稳定按下30ms,则代表没有按下按键
         g_iButtonState=0;

         }
else                                      //如果一直无检测到低电平,即一直无按键按下
    {
         iButtonCount=0;                  //清零iButtonCount
         g_iButtonState=0;                  //清除按键标志
         iButtonFlag=0;                   //清除重按键标志
    }
}

        再新建一个文件 button.h 头文件,把文件保存到 Inc 文件夹。然后,把下面代码敲进去。

#ifndef __BUTTON_H
#define __BUTTON_H

extern int g_iButtonState;//声明外部变量,方便其他地方引用

void ButtonScan(void);//声明按键扫描函数

#endif

        打开 stm32fxx_it.c 文件,在 /* USER CODE BEGIN Includes */ 与 /* USER CODE END Includes */ 之间加入 #include "button.h"。

        在 stm32fxx_it.c 文件里面 SysTick_Handler() 函数里加入按键扫描函数 ButtonScan(),更重要的是,要在后面加上 HAL_SYSTICK_IRQHandler() 函数,STM32CubeMX v5.x 之后的版本为避免 HAL_SYSTICK_Callback() 执行时间超过 1ms 或产生循环依赖时出现阻塞,默认不调用 HAL_SYSTICK_IRQHandler(),所以我们要手动加上这个语句。

/**
  * @brief This function handles System tick timer.
  */
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */
  ButtonScan();//按键扫描函数
  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */
  HAL_SYSTICK_IRQHandler(); //必须加这个语句,不加按键会失效
  /* USER CODE END SysTick_IRQn 1 */
}

        在左侧 Application/User 文件夹里打开 main.c 函数,在主循环里面加入以下代码:

    if(g_iButtonState == 1)
    {            
        HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);//翻转LED引脚(PB12)的电平
        while(HAL_GPIO_ReadPin(Button_GPIO_Port,Button_Pin)==GPIO_PIN_RESET);//按键松手检测
    }

        这段代码的意思就是:如果按键状态标志为 1 ,则代表按键被按下了,这时候进行 LED 电平翻转。

        在左侧 Application/User 文件夹里点开 main.c 函数左侧的加号,找到 main.h 头文件,并把#include "button.h"头文件加进去。

        代码已经编写好了。这时候,点击编译按钮,会提示没有错误和警告。

      (完成)

12. 定时器按键消抖 使用延时函数消抖会浪费 CPU 性能,因为延时函数就是空跑。如果按键是使用中断的方式实现的,就更不能在中断服务函数中使用延时函数,因为中断服务函数最基本的要求就是快进快出。所以可以使用定时器设置好时间,就可以去跑其他的进程,当时间到了,就会触发中断,然后在中断函数中做相应的处理。需要在图中t1 ~ t3 这个时间段消抖。设置按键为下降沿触发,因此会在t1、t2和t3这3个时刻会触发按键中断,每次进入中断处理函数都会重新开启定时器中断。 阅读详情

相关推荐

树莓派Pico旋转编码器消抖:定时器扫描与状态机实战

机械旋转编码器在嵌入式项目中应用广泛,但其内部触点闭合瞬间会产生高频抖动,导致单片机误判方向、计数跳变。理解编码器A/B相正交信号与抖动成因,是构建可靠交互的基础。在树莓派Pico这类MicroPython平台上,纯延时代码会阻塞主循环,而硬件滤波又缺乏灵活性。采用定时器周期扫描替代主循环轮询,结合状态机查表判断旋转方向,可同时解决抖动、实时性和资源开销问题。该方案不依赖外部滤波电路,代码精简,特别适合音量旋钮、菜单导航、舵机微调等场景。掌握这一思路,能帮助开发者在Pico、ESP32等平台上快速落地稳定的

weixin_33795093的博客 362

51单片机教程:按键的定时器消抖(有延时的程序不是好程序)

按键消抖原理 一、首先来回顾一下按键延时消抖 按键由于是机械结构,按下的时候难免产生抖动,一般抖动会在按下的时候与松开的时候产生,抖动时间大概是10ms 于是针对按键抖动就有了延时消抖的一种简单的解决方法: 二、按键消抖代码 方法一: 按下按键损耗的时间取决于按下按键到松开的时间,至少10ms,按下按键后CPU不再执行其他指令,直到按键松开,应用能力弱 void main(void) { while(1) { if(key==0) //读P1.0引脚,如果引脚为低电平,则进入if {

mbs706的博客 5万+

蓝桥杯单片机国赛第九届深度复盘:硬件驱动、软件架构与系统调试实战

单片机作为嵌入式系统的核心,其开发涉及硬件驱动、软件架构与系统集成等多个层面。理解其工作原理,关键在于掌握外设通信协议(如I2C)、中断机制以及多任务调度方法。这些技术能有效提升嵌入式设备的实时性与可靠性,广泛应用于工业控制、智能仪器等领域。本文以蓝桥杯竞赛为具体场景,深入剖析了DAC7578数模转换模块的精度校准与波形生成优化,以及基于状态机的矩阵键盘消抖策略,为嵌入式开发者提供了从模块驱动到系统集成的实战经验。

weixin_30321449的博客 389

【裸机开发】EPIT 定时器 —— 按键消抖

【裸机开发】EPIT 定时器 —— 按键消抖

challenglistic的博客 2002

蓝桥杯嵌入式国赛复盘:STM32模块化设计与状态机调度实战

在嵌入式系统开发中,模块化设计与状态机是构建复杂应用的核心思想。模块化通过将系统划分为硬件抽象层、业务逻辑层等独立部分,降低了代码耦合度,提升了可维护性。状态机则用于管理系统的不同运行模式,是实现清晰逻辑控制的关键技术。这些方法对于开发资源受限的微控制器(如STM32)系统具有重要价值,尤其在需要高效处理多任务、实时响应的场景中,例如环境监测、智能控制等物联网应用。本文以蓝桥杯嵌入式国赛项目为例,深入剖析了如何运用模块化与状态机思想,结合ADC采集、I2C通信、LCD显示等关键技术,构建一个稳定可靠的环境监

weixin_34417200的博客 339

按键消抖的三种方案

首先,做两个假定,以方便后面的描述: 假定按键的默认状态为0,被按下后为1 假定按键抖动时长小于20ms,也即使用20ms的消抖时间 方案1:在按键电平稳定的情况下,当第一次检测到键位电平变化,开始20ms计时,计时时间到后将按键电平更新为当前电平 方案2:在20ms计时的过程中,有任何的电平变化都立即复位计时 方案3:在有电平变化时立即改变按键输出电平,并开始20ms计时,忽略这其中抖动 1、方案1代码: module debounce( input wire clk, nrst, i

耐心的小黑的博客 2万+

靠别Delay,按键边沿检测与消抖分享

本人斩获第十五届蓝桥杯单片机赛道国奖,结合 STC15F2K60S2 平台复盘三种按键消抖与边沿检测实现方案,分享备赛实战经验,欢迎大家一同交流学习、共同进步。

Van_137的博客 622

FPGA时钟项目实战:Verilog实现闹铃、报时与按键消抖全解析

在数字系统设计中,时钟与状态机是两大基石。FPGA 开发常从计数器分频、BCD 编码和动态扫描显示入手,这些基础技术直接决定了系统的稳定与可扩展性。按键消抖与跨时钟域处理则是工程化落地的关键。基于这些原理,本文深入拆解一个完整的 Verilog 时钟工程,涵盖分频器、时间计数器、闹铃状态机、整点报时逻辑以及动态扫描显示,并结合仿真与上板调试方法,指出常见陷阱(如蜂鸣器优先级、扫描频率选择)。无论你是在学习数字逻辑还是准备竞赛,这套从原理到实践的方法论都能帮助你快速构建可靠的 FPGA 应用。

weixin_34292402的博客 283

慧净电子 HL-1/HL-2 小车 & ATmega16A-PU & 裸机 + 寄存器 & AVR-GCC 开源工具链学习之 “独立按键与软件消抖”(第三坑)

本文为个人底层实操记录,基于慧净 HL-2 开发板、HL-1 智能小车底盘、ATmega16A-PU 单片机,全程采用纯寄存器裸机开发,不依赖任何封装库,搭配 AVR-GCC 开源编译工具链。完整记录独立按键硬件电路、机械抖动原理、两套软件消抖实现方案与实操踩坑排错流程。

共同成长,共同进步。 207

51单片机数字时钟Proteus仿真:Timer0时基、动态扫描与误差排查

在嵌入式入门和课程设计中,51单片机、定时器中断与数码管动态扫描是常见基础组合。Timer0依靠机器周期计数产生稳定时基,通过中断重装载初值实现秒级计时;动态扫描以分时位选和消隐抑制鬼影,按键消抖则用状态机提升交互可靠性。这些技术直接决定电子时钟的走时精度、显示稳定性和实物可用性,也广泛用于仪表、家电面板与实验装置。面对仿真能跑、实物翻车、日误差偏大等工程问题,需要从晶振频率、EA复位、位选驱动到误差补偿逐项排查。围绕51单片机数字时钟Proteus仿真工程,可系统梳理Timer0初值推导、2ms扫描时基、

weixin_29194255的博客 290

8051单片机实验报告全解析:GPIO、定时器、中断与串口通信实践指南

单片机是嵌入式系统设计的核心,而8051作为经典架构,其GPIO控制、定时器计数、中断响应和串口通信构成了最基本的硬件操作能力。GPIO实验让开发者理解引脚电平控制与外围设备驱动,定时器和中断则将CPU从繁琐的轮询中解放,提升系统实时性;串口通信则与晶振频率、波特率计算紧密相关,是数据交互的基础。掌握这些技术不仅有助于完成课程实验报告,更能为物联网节点、智能硬件原型等实际应用提供底层支撑。本文基于8051单片机实验报告,系统梳理从环境搭建到代码实现的完整链路,涵盖跑马灯、数码管扫描、按键消抖、定时器初值计算

weixin_33787529的博客 389

慧净电子 HL-1/HL-2 小车 & ATmega16A-PU & 裸机 + 寄存器 & AVR-GCC 学习之 “外部中断按键(INT0/INT1)+ 中断优先级 + 按键状态机”(第四坑)

本文基于慧净HL-2开发板和ATmega16A-PU单片机,探讨了外部中断按键(INT0/INT1)的寄存器级开发方法。文章详细解析了AVR中断优先级规则、关键寄存器配置,并针对机械抖动、中断标志清除等常见问题提出解决方案。通过结合Timer0时基和有限状态机,实现了按键消抖以及长短按识别功能,为智能小车等应用提供了高效的非阻塞式按键处理方案。所有代码均基于AVR-GCC工具链开发,可直接移植到实际项目中。

共同成长,共同进步。 548

OCV/AOCV/SOCV的介绍和应用

library中的cell delay是在某个固定的PVT(operating condition)下仿真得出的。,cell的delay并不是一个固定值,而是一个随机值,遵循高斯分布或门特卡洛分布,在STA中用OCV来模拟这一『特征』。OCV全称on chip variation,用于描述不同管子间由于工艺偏差、电压降、温度变化引起的delay变化。,也用于描述工艺偏差引起的net厚度宽度的变化从而导致net的电容电阻变化。优点:设置起来比较简单粗暴,对于不那么先进的工艺可行!的影响,更贴合实际。

m0_61003348的博客 8980

从蓝桥杯嵌入式赛题复盘到工程思维:我的按键状态机与PWM控制模块是如何设计的

本文分享了蓝桥杯嵌入式省赛中的按键状态机与PWM控制模块设计经验,详细解析了状态机模型、定时中断驱动实现及PWM频率平滑过渡算法。通过模块化设计和工程思维,将复杂功能转化为可维护的代码架构,为嵌入式开发者提供实用参考。

weixin_42532938的博客 387

SD-WAN组网案例——数据中心

SD-WAN组网案例——数据中心

2301_78457663的博客 706

真双口RAM---Quartus与Vivado开发环境区别对比

2、写和写冲突:表示两个端口写使能同时有效且写地址相同,此时需要关断一个写,把两个写端口都需要更新的值处理到一个写端口上面,任何的DP RAM 都不支持写和写冲突。以上述直方图统计使用为例,博主在仿真过程中发现,vivado真双口RAM--B端口读写延迟2个clk;1、读和写冲突:如果读和写同时有效,且读和写是同一个地址时,发生RAM读写冲突,此时会把最新的写数据直接赋给读数据,称为写穿通到读。

weixin_54470733的博客 3582

蓝桥杯2020国赛CT107D单片机答疑题深度复盘

单片机系统调试本质是硬件与软件协同的时序工程,核心在于理解I/O口电气特性、中断响应机制与外设驱动时序约束。CT107D开发板因锁存器控制、P0口上拉电阻开关、矩阵键盘电阻非对称等隐藏硬件特性,成为检验真实嵌入式工程能力的典型平台。掌握信号链路推演、故障树分析与最小化验证方法,不仅能应对蓝桥杯单片机国赛客观题中的‘答疑’类高压场景,更可迁移至工业现场的ECU诊断、IoT终端故障定位等实际应用。本文聚焦蓝桥杯2020国赛真题,结合LE锁存器时序、状态机消抖、数码管动态刷新等关键技术点,提供可实测、可复用的底层

weixin_34025051的博客 586

ROS机器人全覆盖路径规划实战:6种ipa算法对比与选型指南(附避坑经验)

本文深入对比了ROS中ipa_coverage_planning功能包集成的6种全覆盖路径规划算法,包括牛耕分解、栅格旅行商、神经网络、局部能量最小、轮廓线和凸感知放置。文章从覆盖率、重复率、计算效率、动态避障等核心工程指标出发,提供了基于不同场景(如静态/动态环境、规则/复杂布局)的实战选型指南,并分享了神经网络和局部能量最小等关键算法的参数调优与避坑经验,旨在帮助开发者根据实际需求选择并优化最合适的ipa覆盖算法。

perl8的博客 363

蓝桥杯单片机国赛代码复盘:51单片机多外设协同与状态机设计实战

在嵌入式系统开发中,单片机作为核心控制器,其程序设计关键在于如何高效管理有限资源并实现多任务协同。其基本原理是通过中断驱动和分时复用技术,在单线程CPU上模拟多任务并发执行,从而提升系统响应能力和资源利用率。这一技术价值在于构建稳定可靠的嵌入式应用基础,广泛应用于智能仪表、工业控制和人机交互等场景。本文以蓝桥杯单片机国赛项目为例,深入剖析了基于51单片机的**多外设协同**与**状态机设计**实战方案,通过模块化驱动、定时器调度和清晰的状态迁移,为解决综合性工程挑战提供了经过验证的架构思路与代码实现。

weixin_33860528的博客 419

机器视觉最全面试题总结

空洞卷积(Atrous Convolution)也叫做膨胀卷积、扩张卷积,最初的提出是为了解决图像分割在用下采样(池化、卷积)增加感受野时带来的特征图缩小,后再上采样回去时造成的精度上的损失。空洞卷积通过引入了一个扩张率的超参数,该参数定义了卷积核处理数据时各值的间距。可以在增加感受野的同时保持特征图的尺寸不变,从而代替下采样和上采样a. 是普通的卷积过程(dilation rate = 1),卷积后的感受野为3b. 是dilation rate = 2的空洞卷积,卷积后的感受野为5。

@bangbang的博客 9210

华为OD机试真题 新系统 2026-07-22 Java&Go&C 实现【最小代价完成论文评审】

某校有 n 篇论文需要分配给教师评审。 每篇论文 i 可由 files[i] 对应的教师列表中任一教师评审。 每篇论文至少需要一名教师评审。 每位教师 t 不论被分配多少篇论文,其评审费用固定为 cost[t]。 请给出参与评审教师数量最少时的总费用。 如果存在多种方案满足教师数量最少,则选择总费用最小的方案。

MISAYAONE的博客 149

51单片机全自动洗衣机控制系统设计与Proteus仿真实现

嵌入式系统开发中,状态机设计与外设驱动是核心基础技术。通过有限状态机对复杂流程进行建模,结合定时器中断、GPIO控制与PWM调速,可实现对电机、阀门等执行机构的精准控制。这种技术方案在智能家电、工业自动化等场景中应用广泛,能有效提升系统的可靠性与实时性。全自动洗衣机作为典型的机电一体化设备,其进水、洗涤、排水、脱水等工序恰好构成完整的状态转移链,是学习嵌入式控制的理想载体。本文以STC89C52RC单片机为核心,配合L298N电机驱动与Proteus仿真平台,详细阐述洗衣机控制系统的硬件选型、状态机框架搭建

weixin_34050005的博客 341

uniapp - 超详细实现播放 svg / svga 格式动画组件插件,用于直播间赠送礼物特效动画或项目动画特效较多的应用(新手小白保姆级教程,提供插件+详细运行示例+使用文档+注意事项+格式说明)

uniappsvga,uniapp播放svga动画,uniapp中使用svga动画详细教程,uniapp播放svga的插件,uniapp有没有调用svga格式动画的组件插件,uinappH5App小程序全端兼容的svga播放器免费好用插件,uniapp好用的svga格式动画插件,在uniapp中使用SVGAPlayer播放svga动画,uniapp中使用svga动画,编译到apph5,uniapp运行svg动画,uniapp怎么使用svga文件格式,uniapp播放svg格式的动画教程,un

🏆 前端领域优质创作者 1万+

蓝桥杯单片机国赛实战:模块化设计与状态机编程精解

在嵌入式系统开发中,模块化设计与状态机编程是构建稳定、可维护应用的核心思想。模块化通过将系统划分为独立的硬件驱动层(如数码管、按键、I2C设备驱动)和业务逻辑层,降低了代码耦合度,便于调试与复用;状态机则用于管理复杂的系统行为与用户交互,确保程序逻辑清晰、响应准确。这些技术能显著提升开发效率与系统可靠性,尤其适用于资源受限的单片机场景,如智能仪表、工控设备等。本文以蓝桥杯单片机国赛项目为例,深入剖析如何运用模块化与状态机思想,整合ADC/DAC数据采集、EEPROM存储等关键技术,实现一个完整的测量控制系统

weixin_33851177的博客 322

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

STM32数字时钟项目实战:从CubeMX配置到DS1302驱动与状态机调时

嵌入式开发中,定时器、GPIO和通信协议是构建一切应用的基础。通过一个完整的硬件项目,可以系统性地理解这些概念如何协同工作。定时器产生精准的时间基准,GPIO负责按键输入与显示控制,I2C等通信协议连接外部RTC芯片与OLED屏幕。DS1302作为经典实时时钟芯片,提供了掉电走时的能力;而状态机设计则让调时逻辑清晰可靠。本文以STM32数字时钟为载体,从CubeMX配置、时钟树设置、驱动分层到调试排错,全面展示了嵌入式工程实践的核心流程。无论初学者还是进阶者,都能从中掌握从零搭建一个可靠小系统的关键方法。这

weixin_33912246的博客 377

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

上一篇: 【图神经网络】个人综述分享
下一篇: 三维点云中语义分割、实例分割、全景分割的区别与联系
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值