课程目录

【概述】0 什么是智能系统

【阶段一】1 PlatformIO环境配置和GPIO

【阶段一】2 PWM与电机控制

【阶段一】3 外部中断和定时器中断

【阶段一】4 串口与串口中断

【阶段一】5 I2C与MPU6050模块

【阶段一】6 基础小车设计

【阶段二】7 智能系统概述

3.1 中断引例

想象一个情景,周一早上有节早八。好消息是这是节水课,不收手机,坏消息是老师上课前要点名,不能不去。那么为了我们的身心愉悦,只能去得早点抢个后排。为此,你定了个早上7点的闹钟。周一到了,闹钟响了,你起床洗漱完之后,走在路上,看到路人玩手机,忽然间想起手机没拿,快乐的源泉忘带了。没办法了只能返身去取手机,之后再去教室占座。

3.2 什么是中断

想象到此结束,让我们来剖析一下整个过程,正常来说,我们不会再返回宿舍,而是直接到教室。如果从单片机角度来看,“直接到教室”这个过程,是主进程,“返回宿舍拿手机”就属于是中断任务,“看到路人玩手机,忽然间想起手机没拿”就是中断触发源,当中断被触发,就会打断主进程,转而去执行中断任务,只有在中断执行完之后,才会继续执行主进程。

3.2.1中断概念

  在单片机中,中断是指当 CPU 在正常处理主程序时,突然发生了另一件事件 A(中断发生)需要 CPU 去处理,这时 CPU 就会暂停处理主程序(中断响应),转而去处理事件 A(中断服务)。当事件 A 处理完以后,再回到主程序原来中断的地方继续执行主程序(中断返回)。这一整个过程称为中断。

3.2.2中断的作用和意义:

(1)实时响应:外部中断可以立即暂停当前任务并执行中断程序,因此可以实现对外部事件的实时响应。比如,当按下按钮时,可以立即触发中断处理程序,而不需要在主循环中轮询按钮状态。 (2)支持异步通信:在异步通信协议(如UART、SPI、I2C)中,外部中断可以用于处理接收和发送事件。例如,当接收到数据时,可以通过中断通知CPU读取数据,而不需要持续轮询通信接口的状态。(上课传纸条,加密,小A指代,不用盯着看) (3)节省CPU资源:外部中断的处理由硬件负责,不需要CPU持续监测输入状态。这样可以节省CPU的资源,使得CPU可以处理其他任务,提供更好的系统性能。 (4)增强系统安全性:外部中断可以用于实现安全机制,如硬件看门狗定时器(Watchdog Timer)。当系统出现异常时,看门狗定时器可以触发中断,强制系统复位或执行特定的安全操作,防止系统进入不可控状态。(喂狗)

(5)减少功耗:通过使用外部中断来检测外部事件,可以让系统进入低功耗状态,只有当中断事件发生时才唤醒系统处理。这在对功耗要求较高的应用中尤为重要,可以延长电池寿命或降低能耗。(熊冬眠)

(6)精准触发:外部中断可以通过配置边沿触发方式(上升沿、下降沿或双边沿)以及滤波选项,实现对特定事件的精确触发。这对于需要高精度的事件检测和计时非常有用,如测量脉冲宽度或计数器应用。

3.2.3中断优先级:

3.2.4中断触发源:

硬件中断(外部中断):外部事件或硬件信号触发,如GPIO中断、定时器中断、UART中断等
  • GPIO中断
    • ESP32的GPIO引脚可以配置为触发中断。当引脚状态发生变化(如上升沿、下降沿、高电平、低电平等)时,会触发中断。
    • 例如,当某个按钮按下时,GPIO引脚状态从高电平变为低电平,触发中断。
  • 硬件定时器中断
    • ESP32有多个硬件定时器,可以配置为在特定时间间隔或计数达到特定值时触发中断。
    • 例如,定时器每1秒触发一次中断,用于执行定时任务。
  • UART中断
    • 当UART(通用异步收发传输器)接收到数据或发送数据完成时,可以触发中断。
    • 例如,当UART接收到一帧数据时,触发中断以便处理接收到的数据。

………………………………………………………省略号……………………………………………………………

软件中断:由软件指令触发的,通常用于实现特定的功能或处理特定的任务。
  • 任务调度中断
    • ESP32在使用FreeRTOS作为实时操作系统时,任务调度器会根据任务的优先级和状态触发软件中断,以切换任务。
    • 例如,当一个高优先级任务就绪时,调度器会触发软件中断,切换到该任务执行。
  • 系统调用中断
    • 在某些情况下,操作系统或库函数会通过软件中断来执行特定的系统调用。
    • 例如,当应用程序调用某个系统函数时,可能会触发软件中断以执行底层操作。
  • 软件定时器中断
    • ESP32支持软件定时器,可以在特定时间间隔触发中断。
    • 例如,软件定时器每100毫秒触发一次中断,用于执行周期性任务。

3.2.5中断处理函数(Interrupt Service Routine,简称ISR ):

要注意中断处理函数的执行时间

  • 避免阻塞:在ISR中避免执行可能阻塞的操作,如延时函数(delay();)、复杂的计算或等待资源。
  • 快速执行:中断处理函数应该尽可能快速执行。长时间的中断处理会影响系统的响应速度和其他中断的处理。

3.3 GPIO中断

3.3.1 源代码

先贴一段代码:

#include <Arduino.h>

#define BUTTON 12
// 定义可以在外部中断函数内部使用的变量
bool flag = false;

void handle_interrupt() 
{
    flag = true;    
}

void setup() {
    pinMode(BUTTON, INPUT_PULLUP);
    // 配置中断引脚
    attachInterrupt(digitalPinToInterrupt(BUTTON), handle_interrupt, CHANGE);
}

void loop() {
  if (flag) 
  {
    // 软件去抖动
    delay(50);  // 延时50毫秒以消除抖动
    if (digitalRead(BUTTON) == LOW) {
        flag = false;
    }
  }
}

3.3.2 代码分析

让我们来逐行分析:

#define  BUTTON  14   

这行代码定义了一个宏 BUTTON,其值为 14。这意味着在代码中使用 BUTTON 的地方都会被替换为 14,这样做会有个好处,就是当你想改变触发的引脚的时候只需要改变一个地方,而不需要在整个工程里面逐行去修改IO口。

bool flag = false;
  • 引脚电平变化时,flag的值会改变。
void handle_interrupt() 
{        
  flag = true;
} 
  • 当外部中断触发时,这个函数会被自动调用,更改flag的值。
Serial.begin(115200);
  • 配置串口波特率为115200
pinMode(BUTTON, INPUT_PULLUP);
  • 配置BUTTON引脚模式为INPUT_PULLUP,默认输入高电平。
// 配置中断引脚
  attachInterrupt(digitalPinToInterrupt(BUTTON), handle_interrupt, CHANGE);
  • attachInterrupt
  • digitalPinToInterrupt(BUTTON)
  • handle_interrupt
  • CHANGE

指定中断触发模式为 CHANGE,即当引脚电平发生变化时触发中断。


让我们来详细看一下这个中断触发模式(源代码位于Arduino.h):

//Interrupt Modes
#define RISING    0x01
#define FALLING   0x02
#define CHANGE    0x03
#define ONLOW     0x04
#define ONHIGH    0x05
#define ONLOW_WE  0x0C
#define ONHIGH_WE 0x0D
  • RISING:检测上升沿(从低电平到高电平)。
  • FALLING:检测下降沿(从高电平到低电平)。
  • CHANGE:检测任何电平变化。
  • ONLOW:检测引脚为低电平。
  • ONHIGH:检测引脚为高电平。
  • ONLOW_WE:检测引脚为低电平,并持续触发中断。
  • ONHIGH_WE:检测引脚为高电平,并持续触发中断。

void loop() {
  if (flag) {
    // 软件去抖动
    delay(50);  // 延时50毫秒以消除抖动
    if (digitalRead(BUTTON) == HIGH) {
      Serial.println("外部中断触发了");
      flag = false;
    }
  }
}

loop 函数中检查标志位,进行简单的软件去抖动,确认按钮状态,并打印消息。

为什么我们这样操作,而不是采用如下形式呢?

void handle_interrupt() 
{        
    // 软件去抖动
    delay(50);  // 延时50毫秒以消除抖动
    if (digitalRead(BUTTON) == HIGH) {
    Serial.println("外部中断触发了");
} 
void loop() 
{
}

中断处理函数(ISR)应该尽可能快速执行,以避免影响系统的响应速度和其他中断的处理。delay(50) 会阻塞 ISR 50 毫秒,这会导致系统在这段时间内无法响应其他中断或执行其他任务,很不优雅。

3.3.3 红绿灯源代码

#include <Arduino.h>

#define BUTTON 4
#define RED_LED 15
#define YELLOW_LED 16
#define GREEN_LED 17

// 定义可以在外部中断函数内部使用的变量
bool flag = false;
bool running = false; // 流水灯运行状态
unsigned long previousMillis = 0; // 上一次切换时间
const long interval = 500; // 切换间隔时间(毫秒)
int currentLED = RED_LED; // 当前点亮的LED

void handle_interrupt() 
{
    flag = true;    
}

void setup() {
    pinMode(BUTTON, INPUT_PULLUP);
    pinMode(RED_LED, OUTPUT);
    pinMode(YELLOW_LED, OUTPUT);
    pinMode(GREEN_LED, OUTPUT);
    // 配置中断引脚
    attachInterrupt(digitalPinToInterrupt(BUTTON), handle_interrupt, CHANGE);
}

void loop() 
{
  if (flag) 
  {
    // 软件去抖动
    delay(50);  // 延时50毫秒以消除抖动
    if (digitalRead(BUTTON) == LOW) {
        running = !running; // 切换流水灯的运行状态
        flag = false;
    }
  }

  if (running) 
  {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) 
    {
        // 保存上一次切换时间
        previousMillis = currentMillis;

        // 关闭当前LED
        digitalWrite(currentLED, LOW);

        // 切换到下一个LED
        if (currentLED == RED_LED) 
        {
            currentLED = YELLOW_LED;
        } 
        else if (currentLED == YELLOW_LED) 
        {
            currentLED = GREEN_LED;
        } 
        else 
        {
            currentLED = RED_LED;
        }

        // 点亮下一个LED
        digitalWrite(currentLED, HIGH);
    }
  } 
  else 
  {
    // 关闭所有LED
    digitalWrite(RED_LED, LOW);
    digitalWrite(YELLOW_LED, LOW);
    digitalWrite(GREEN_LED, LOW);
  }
}

3.3.4 红绿灯代码分析

头文件和宏定义

#include <Arduino.h>
  • 包含Arduino的核心库,提供了Arduino的基本功能。
#define BUTTON 4
#define RED_LED 15
#define YELLOW_LED 16
#define GREEN_LED 17
  • 定义了按钮和三个LED的引脚编号。

全局变量

bool flag = false;bool running = false; // 流水灯运行状态
unsigned long previousMillis = 0; // 上一次切换时间
const long interval = 500; // 切换间隔时间(毫秒)
int currentLED = RED_LED; // 当前点亮的LED
  • flag:用于标志外部中断是否被触发。
  • running:表示流水灯是否在运行。
  • previousMillis:记录上一次LED切换的时间。
  • interval:LED切换的时间间隔,设置为500毫秒。
  • currentLED:当前点亮的LED引脚。

中断处理函数

void handle_interrupt() 
{
    flag = true;    
}
  • handle_interrupt():外部中断处理函数。当按钮状态发生变化时,flag被设置为true,表示中断被触发。

setup() 函数

void setup() {
    pinMode(BUTTON, INPUT_PULLUP);
    pinMode(RED_LED, OUTPUT);
    pinMode(YELLOW_LED, OUTPUT);
    pinMode(GREEN_LED, OUTPUT);
    // 配置中断引脚
    attachInterrupt(digitalPinToInterrupt(BUTTON), handle_interrupt, CHANGE);
}
  • pinMode(BUTTON, INPUT_PULLUP);:将按钮引脚设置为输入上拉模式。
  • pinMode(RED_LED, OUTPUT);:将红色LED引脚设置为输出模式。
  • pinMode(YELLOW_LED, OUTPUT);:将黄色LED引脚设置为输出模式。
  • pinMode(GREEN_LED, OUTPUT);:将绿色LED引脚设置为输出模式。
  • attachInterrupt(digitalPinToInterrupt(BUTTON), handle_interrupt, CHANGE);:将按钮引脚配置为外部中断,触发模式为CHANGE(电平变化时触发),中断处理函数为handle_interrupt

loop() 函数

void loop() 
{
  if (flag) 
  {
    // 软件去抖动
    delay(50);  // 延时50毫秒以消除抖动
    if (digitalRead(BUTTON) == LOW) {
        running = !running; // 切换流水灯的运行状态
        flag = false;
    }
  }
  • if (flag):检查flag是否为true,即是否触发了外部中断。
  • delay(50);:延时50毫秒以消除按钮的抖动。
  • if (digitalRead(BUTTON) == LOW):检查按钮是否被按下(低电平)。
  • running = !running;:切换流水灯的运行状态(启动或停止)。
  • flag = false;:重置flag,等待下一次中断。
if (running) 
  {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) 
    {
        // 保存上一次切换时间
        previousMillis = currentMillis;

        // 关闭当前LED
        digitalWrite(currentLED, LOW);

        // 切换到下一个LED
        if (currentLED == RED_LED) 
        {
            currentLED = YELLOW_LED;
        } 
        else if (currentLED == YELLOW_LED) 
        {
            currentLED = GREEN_LED;
        } 
        else 
        {
            currentLED = RED_LED;
        }

        // 点亮下一个LED
        digitalWrite(currentLED, HIGH);
    }
  } 
  else 
  {
    // 关闭所有LED
    digitalWrite(RED_LED, LOW);
    digitalWrite(YELLOW_LED, LOW);
    digitalWrite(GREEN_LED, LOW);
  }
}
  • if (running):检查流水灯是否在运行。
  • unsigned long currentMillis = millis();:获取当前时间。

millis() 是 Arduino 中的一个内置函数,用于返回自程序启动以来经过的毫秒数。这个函数非常有用,特别是在需要进行时间相关的操作时,例如定时器、延迟、时间戳等。

millis() 函数的作用

  1. 返回自程序启动以来的毫秒
    1. millis() 返回一个 unsigned long 类型的值,表示自程序启动以来经过的毫秒数。
    2. 这个值会随着时间的推移不断增加,直到达到 unsigned long(它的存储范围是从 0 到 2^32 – 1,即 0 到 4,294,967,295) 的最大值(大约 49.7 天),然后会从零重新开始。
  2. 非阻塞延迟
    1. delay() 函数不同,millis() 不会阻塞程序的执行。这意味着你可以在等待一段时间的同时执行其他代码。
    2. 例如,你可以使用 millis() 来实现一个定时器,而不需要使用 delay() 函数。
  • if (currentMillis - previousMillis >= interval):检查是否达到了切换时间间隔。
  • previousMillis = currentMillis;:更新上一次切换时间。
  • digitalWrite(currentLED, LOW);:关闭当前点亮的LED。
  • if (currentLED == RED_LED):根据当前点亮的LED切换到下一个LED。
  • digitalWrite(currentLED, HIGH);:点亮下一个LED。
  • else:如果流水灯未运行,关闭所有LED。

总结

这段代码通过外部中断控制流水灯的启动和停止。当按钮被按下时,流水灯会在红色、黄色和绿色LED之间循环切换,每次切换间隔为500毫秒。如果按钮再次被按下,流水灯将停止。代码中还包含了软件去抖动处理,以避免按钮抖动引起的误触发。

3.4 定时器

定时器就像是一个闹钟,它可以在设定的时间间隔后提醒你做某件事情。在电子设备中,定时器用于在特定的时间间隔后触发某些操作。

物理实体

代码层面

硬件定时器的优缺点:

优点:
  1. 精确性:硬件定时器通常非常精确,因为它们由专门的硬件电路实现,不受CPU负载的影响。
  2. 独立性:硬件定时器可以独立于CPU运行,即使CPU忙于其他任务,定时器也能准确计时。
  3. 实时性:硬件定时器适合需要高实时性的应用,如嵌入式系统和实时操作系统。
  4. 可靠性:由于不依赖于软件,硬件定时器在系统崩溃或软件错误时仍能工作。
缺点:
  1. 灵活性:硬件定时器的功能通常比较固定,不如软件定时器灵活。
  2. 资源限制:硬件定时器的数量和类型可能受限于硬件设计,无法像软件那样容易扩展,就4个。

软件定时器的优缺点:

优点:
  1. 灵活性:软件定时器可以根据程序的需要灵活地创建、配置和销毁。
  2. 可编程性:软件定时器可以通过编程实现复杂的定时任务和调度。
  3. 扩展性:软件定时器理论上没有数量限制,可以根据需要创建多个定时器。
  4. 成本:软件定时器不需要额外的硬件支持,可以节省成本。
缺点:
  1. 精确性:软件定时器的精确性受限于操作系统的调度和CPU的负载,可能不如硬件定时器精确。
  2. 依赖性:软件定时器依赖于操作系统和CPU的正常运行,如果系统崩溃或CPU过载,定时器可能无法正常工作。
  3. 实时性:软件定时器不适合需要极高实时性的应用,因为它们受操作系统调度的影响。

硬件定时器和软件定时器各有优劣,具体选择取决于你的应用需求。如果需要高精度、实时性和稳定性,建议使用硬件定时器。如果时间精度要求不高,或者只需要基本的定时功能,可以使用软件定时器来简化代码编写。

3.4.1 软件定时器中断

这里我们使用Ticker,这是一个内置的软件定时器库,它使用 FreeRTOS 的任务调度器来实现定时功能。与硬件定时器不同,Ticker 不需要硬件支持,代码层面,因此可以在任何支持 FreeRTOS 的平台上使用,而且定时器的数量也是没有限制的。

3.4.1.1 源代码

贴个代码

#include <Arduino.h>
#include <Ticker.h>

// 定义定时器对象
Ticker timer;
Ticker timer_once;

// 定义LED引脚
#define LED 16
#define LED_ONCE 17

// 定义定时器中断回调函数
void toggle(int pin) {
  digitalWrite(pin, !digitalRead(pin)); // 切换引脚状态
}

void setup() {
  // 初始化引脚模式
  pinMode(LED, OUTPUT);
  pinMode(LED_ONCE, OUTPUT);                         
  // 配置周期性定时器
  timer.attach(0.5, toggle, LED);
  // 配置一次性定时器
  timer_once.once(3, toggle, LED_ONCE);
}

void loop() {
  // 主循环中不需要执行任何操作
}
Ticker timer;
Ticker timer_once;
3.4.1.2 代码分析
  • 定义定时器对象
    • Ticker timer;:创建一个 Ticker 对象 timer,用于周期性定时器。
    • Ticker timer_once;:创建一个 Ticker 对象 timer_once,用于一次性定时器。
  • 定义定时器中断回调函数
    • void toggle(int pin):定义一个回调函数 toggle,接受一个整数参数 pin
    • digitalWrite(pin, !digitalRead(pin));:读取引脚的当前状态,并将其取反后写回引脚,从而切换引脚状态。
  • timer.attach(0.5, toggle, LED);:配置 timer,使其每隔 0.5 秒触发一次 toggle 函数,并将 LED 引脚作为参数传递给 toggle 函数。
  • timer_once.once(3, toggle, LED_ONCE);:配置 timer_once,使其在 3 秒后触发一次 toggle 函数,并将 LED_ONCE 引脚作为参数传递给 toggle 函数。
    • attach_ms(uint32_t milliseconds, callback_function)
      1. 以毫秒为单位设置定时器间隔,并绑定回调函数。
      2. 示例:timer.attach_ms(500, onTick); 每隔500毫秒触发一次 onTick 函数。
    • once(float seconds, callback_function)
      1. 设置定时器在指定时间后触发一次回调函数,然后停止。
      2. 示例:timer.once(2, onTick); 2秒钟后触发一次 onTick 函数,然后停止。
    • once_ms(uint32_t milliseconds, callback_function)
      1. 以毫秒为单位设置定时器在指定时间后触发一次回调函数,然后停止。
      2. 示例:timer.once_ms(1000, onTick); 1000毫秒后触发一次 onTick 函数,然后停止。
    • detach()
      1. 停止 timer,不再触发 onTick 函数
      2. 示例:timer.detach();

3.4.2 硬件定时器中断

硬件定时器 是 ESP32 芯片上的内置计时器,它们是专门设计用于定时和计时任务的硬件模块,通常具有更高的精确度和稳定性。它们不受软件的影响,可以在后台独立运行,不会受到其他代码的干扰。硬件定时器适用于需要高精度和实时性的定时任务,例如 PWM 输出、捕获输入脉冲等。

需要注意的是,ESP32 有 4 个硬件定时器

时钟频率

ESP32默认时钟频率是240MHz,可以简单理解成高低电平的方波信号,经过一系列分频操作,最终作为外设的时钟频率,用于定时器的时钟频率默认是80MHz。

分频器

预分频器的工作原理非常简单:它接收一个高频的输入时钟信号,并根据预设的分频系数(通常是一个整数),生成一个频率较低的输出时钟信号。例如,如果输入时钟频率为 F_in,分频系数为 N,则输出时钟频率 F_out 为:$$Fout=Fin/N$$

系数N我们一般是80,因为80MHz经过预分频器之后变成1MHz,周期就是1us,方便我们统计计算。

自动重装寄存器和计数器:

自动重装寄存器设定一个值a,计数器根据方式向上计数,向下计数。分别从0到a,或者从a到0。然后触发一次定时器中断。

3.4.2.1 源代码

贴个代码

#include <Arduino.h>

// 定义定时器编号和定时器组
#define TIMER_INTERVAL_MS 1000  // 定时器间隔时间(毫秒)
#define TIMER_DIVIDER 80        // 定时器分频器,用于将系统时钟频率转换为定时器时钟频率
#define RED_LED 15               // 红色LED引脚
// 定义可以在中断函数内部使用的变量
bool timerFlag = false;

// 中断处理函数
void IRAM_ATTR onTimer() 
{
    timerFlag = true;
}

void setup() 
{
    pinMode(RED_LED, OUTPUT);
    // 配置定时器
    hw_timer_t * timer = NULL;
    timer = timerBegin(0, TIMER_DIVIDER, true);  // 使用定时器0,分频器为80,向上计数
    timerAttachInterrupt(timer, &onTimer, true); // 将中断处理函数绑定到定时器
    timerAlarmWrite(timer, TIMER_INTERVAL_MS * 1000, true); // 设置定时器间隔时间(微秒)
    timerAlarmEnable(timer); // 启用定时器
}

void loop() 
{
    if (timerFlag) 
    {
        timerFlag = false;
        digitalWrite(RED_LED, !digitalRead(RED_LED));
    }
}
3.4.2.2 代码分析
// 中断处理函数
void onTimer() 
{
    timerFlag = true;
}
  • onTimer 函数是中断处理函数,当定时器中断触发时,这个函数会被调用。
  • onTimer 函数中,将 timerFlag 设置为 true,以通知主程序定时器中断已经触发。
void setup() 
{
    // 配置定时器
    hw_timer_t * timer = NULL;
    timer = timerBegin(0, TIMER_DIVIDER, true);  // 使用定时器0,分频器为80,向上计数
    timerAttachInterrupt(timer, &onTimer, true); // 将中断处理函数绑定到定时器
    timerAlarmWrite(timer, TIMER_INTERVAL_MS * 1000, true); // 设置定时器间隔时间(微秒)
    timerAlarmEnable(timer); // 启用定时器
}
  • timer:硬件定时器句柄。
  • timerBegin(0, TIMER_DIVIDER, true);:初始化定时器 0,分频器为 80,向上计数。
  • timerAttachInterrupt(timer, &onTimer, true);:将中断处理函数 onTimer 绑定到定时器。
  • timerAlarmWrite(timer, TIMER_INTERVAL_MS * 1000, true);:设置定时器的间隔时间(微秒),并启用自动重载。
  • timerAlarmEnable(timer);:启用定时器。

这里是整个硬件定时器的核心,让我们来详细看一下

void timerBegin(timer_num_t timer_num, uint32_t divider, bool count_up):初始化硬件定时器。参数说明:

  1. timer_num:定时器编号,可选值为 0-3 。
  2. divider:定时器的分频系数,用于设置定时器的时钟频率。较大的分频系数将降低定时器的时钟频率。可以根据需要选择合适的值,一般设置为 80 即可;
  3. count_up:指定定时器是否为向上计数模式。设置为 true 表示向上计数,设置为 false 表示向下计数。

timerAttachInterrupt(hw_timer_t *timer, void (*isr)(void *), void *arg, int intr_type):用于将中断处理函数与特定的定时器关联起来。

参数说明:

  1. timer;定时器指针;
  2. isr: 中断处理函数。
  3. arg: 传递给中断处理函数的参数(可选)。
  4. intr_type: 中断类型,可选值为 ture(边沿触发)或 false(电平触发)。

timerAlarmWrite(hw_timer_t *timer, uint64_t alarm_value, bool autoreload):用于设置定时器的计数值,即定时器触发的时间间隔。

参数说明:

  1. timer:定时器指针;
  2. alarm_value: 定时器的计数值,即触发时间间隔;
  3. autoreload: 是否自动重载计数值,可选值为 true(自动重载)或 false(单次触发)。

一些别的函数:

timerAlarmEnable(hw_timer_t *timer):用于启动定时器,使其开始计数;

timerAlarmDisable(hw_timer_t *timer):用于禁用定时器,停止计数;

timerAlarmRead(hw_timer_t *timer):获取定时器计数器报警值;

timerStart(hw_timer_t *timer):计数器开始计数;

timerStop(hw_timer_t *timer):计数器停止计数;

timerRestart(hw_timer_t *timer):计数器重新开始计数,从 0 开始;

timerStarted(hw_timer_t *timer):计数器是否开始计数。

作者 AM

发表回复