【雕爷学编程】Arduino 手册之时间函数micros()

在这里插入图片描述
在这里插入图片描述
什么是Arduino?
Arduino 是一款开源的电子原型平台,它可以让你用简单的硬件和软件来创建各种创意的项目。无论你是初学者还是专家,Arduino 都能为你提供无限的可能性。你可以用 Arduino 来控制传感器、灯光、马达、机器人、物联网设备等等,只要你能想到的,Arduino 都能帮你实现。

如果你想了解更多关于 Arduino 的信息,你可以访问 Arduino 的官方网站,那里有丰富的资源和教程供你参考。你也可以加入 Arduino 的社区,和来自世界各地的爱好者、学生、设计师和工程师交流心得和经验。此外,你还可以使用 Arduino 的在线编程工具,在云端编写代码并上传到你的开发板上。

Arduino 是一个不断发展和创新的平台,它有着广泛的应用领域和潜力。这里希望本手册能激发你对 Arduino 的兴趣和热情,让你享受 Arduino 带来的创造力和乐趣

在这里插入图片描述

维基百科的定义
Arduino 是一个开源嵌入式硬件平台,用来供用户制作可交互式的嵌入式项目。此外 Arduino 作为一个开源硬件和开源软件的公司,同时兼有项目和用户社群。该公司负责设计和制造Arduino电路板及相关附件。这些产品按照GNU宽通用公共许可证(LGPL)或GNU通用公共许可证(GPL)许可的开源硬件和软件分发的,Arduino 允许任何人制造 Arduino 板和软件分发。 Arduino 板可以以预装的形式商业销售,也可以作为 DIY 套件购买。

Arduino 2005 年时面世,作为意大利伊夫雷亚地区伊夫雷亚互动设计研究所的学生设计,目的是为新手和专业人员提供一种低成本且简单的方法,以建立使用传感器与环境相互作用的装置。初学者和爱好者可用Arduino制造传感器、简单机器人、恒温器和运动检测器等装置。

Arduino 这个名字来自意大利伊夫雷亚的一家酒吧,该项目的一些创始人过去常常会去这家酒吧。 酒吧以伊夫雷亚的 Arduin(Arduin of Ivrea)命名,他是伊夫雷亚边疆伯爵,也是 1002 年至 1014 年期间的意大利国王。

在这里插入图片描述

十六、Arduino时间函数 micros()
micros()函数是一种用于获取Arduino开发板运行当前程序的时间的函数。micros()的作用是返回一个无符号长整型(unsigned long)的值,表示从开发板开始运行当前程序到调用该函数时经过的微秒数。这个值会在大约70分钟后溢出(回到零),所以需要注意处理溢出的情况。使用micros()函数可以实现一些需要高精度计时或延时的功能,而不影响程序的其他部分。

micros()的使用范围:
1)当需要获取程序运行的时间或执行某个代码段所花费的时间时,例如获取程序启动时间、计算代码执行效率、实现微秒级别的延时等。
2)当需要实现非阻塞式的延时或定时功能时,例如让LED灯闪烁、控制舵机转动、发送定时信号等。
3)当需要实现多任务或伪并行的功能时,例如同时控制多个LED灯、读取多个传感器、响应多个事件等。

应用场景:
1)精确的定时:与millis()函数相比,micros()函数提供了更高的时间精度,约为4微秒。因此,当需要更高精度的定时功能时,可以使用micros()函数。例如,在需要精确控制信号的生成、精确测量时间间隔的应用中,micros()函数非常有用。
2)测量信号脉冲宽度:micros()函数可以用于测量信号脉冲的宽度。通过记录信号的上升沿和下降沿的时间戳,并使用micros()函数计算时间差,可以准确测量信号的脉冲宽度。这在许多传感器和通信模块的接口中是常见的应用。
3)时间敏感的控制:在某些应用中,需要对时间非常敏感,例如实时控制、精确的时间同步等。micros()函数可以提供更细粒度的时间分辨率,用于实现这些时间敏感的控制功能。

使用micros()时,需要注意以下事项:
1)micros()函数返回的值是无符号长整型(unsigned long),如果使用较小的数据类型(如int)进行运算,可能会导致逻辑错误。即使使用有符号长整型(long),也可能会遇到错误,因为其最大值是无符号长整型的一半。
2)micros()函数返回的值会在大约70分钟后溢出(回到零),所以在进行时间比较或计算时,需要考虑溢出的情况。一种常用的方法是使用无符号长整型进行减法运算,然后判断结果是否小于期望的时间间隔。
3)micros()函数不会受到微控制器定时器的重新配置的影响,所以可以保证其准确性。不同的Arduino核心可能使用不同的定时器来生成micros(),例如“Arduino AVR Boards”和“Arduino megaAVR Boards”核心使用Timer0,“Arduino ARM (32-bits) Boards”和“Arduino SAMD (32-bits ARM Cortex-M0+) Boards”核心使用SysTick定时器。

以下是Arduino时间函数micros()的几个实际运用程序案例:

案例一:使用micros()函数实现LED灯闪烁,而不使用delay()函数。具体的电路图和代码如下:

// 定义一个常量LED_PIN,表示连接到LED灯的数字引脚
#define LED_PIN 13

// 定义一个常量INTERVAL,表示LED灯闪烁的时间间隔(单位微秒)
#define INTERVAL 500000

// 定义一个全局变量previousMicros,表示上一次LED灯切换状态的时间,并初始化为0
unsigned long previousMicros = 0;

// 定义一个全局变量ledState,表示LED灯的当前状态,并初始化为LOW
int ledState = LOW;

void setup() {
    
    
  // 将LED_PIN引脚设为输出模式
  pinMode(LED_PIN, OUTPUT);
}

void loop() {
    
    
  // 定义一个局部变量currentMicros,表示当前时间,并调用micros()函数获取其值
  unsigned long currentMicros = micros();

   // 判断当前时间与上一次切换状态的时间之差是否大于等于闪烁间隔
   if (currentMicros - previousMicros >= INTERVAL) {
    
    
     // 如果是,则更新上一次切换状态的时间为当前时间
     previousMicros = currentMicros;

     // 判断LED灯的当前状态是否为LOW
     if (ledState == LOW) {
    
    
       // 如果是,则将其设为HIGH
       ledState = HIGH;
     } else {
    
    
       // 否则,将其设为LOW
       ledState = LOW;
     }

     // 将LED灯的状态写入LED_PIN引脚
     digitalWrite(LED_PIN, ledState);
   }
}

案例二:使用micros()函数实现舵机转动,而不使用delay()函数。具体的电路图和代码如下:

// 引入Servo库,用于控制舵机
#include <Servo.h>

// 定义一个常量SERVO_PIN,表示连接到舵机的数字引脚
#define SERVO_PIN 9

// 定义一个常量INTERVAL,表示舵机转动的时间间隔(单位微秒)
#define INTERVAL 1000000

// 定义一个全局变量previousMicros,表示上一次舵机转动的时间,并初始化为0
unsigned long previousMicros = 0;

// 定义一个全局变量servoAngle,表示舵机的当前角度,并初始化为0
int servoAngle = 0;

// 创建一个Servo对象,用于控制舵机
Servo servo;

void setup() {
    
    
  // 将Servo对象与SERVO_PIN引脚关联
  servo.attach(SERVO_PIN);
}

void loop() {
    
    
  // 定义一个局部变量currentMicros,表示当前时间,并调用micros()函数获取其值
  unsigned long currentMicros = micros();

   // 判断当前时间与上一次转动的时间之差是否大于等于转动间隔
   if (currentMicros - previousMicros >= INTERVAL) {
    
    
     // 如果是,则更新上一次转动的时间为当前时间
     previousMicros = currentMicros;

     // 判断舵机的当前角度是否为180度
     if (servoAngle == 180) {
    
    
       // 如果是,则将其设为0度
       servoAngle = 0;
     } else {
    
    
       // 否则,将其增加10度
       servoAngle += 10;
     }

     // 将舵机的角度写入Servo对象
     servo.write(servoAngle);
   }
}

案例三:使用micros()函数实现秒表功能,而不使用delay()函数。

// 定义两个常量START_PIN、STOP_PIN,表示分别连接到开始按钮和停止按钮的数字引脚
#define START_PIN 2
#define STOP_PIN 3

// 定义一个全局变量startTime,表示秒表开始计时的时间,并初始化为0
unsigned long startTime = 0;

// 定义一个全局变量stopTime,表示秒表停止计时的时间,并初始化为0
unsigned long stopTime = 0;

// 定义一个全局变量running,表示秒表是否正在运行,并初始化为false
boolean running = false;

void setup() {
    
    
  // 将START_PIN、STOP_PIN两个引脚设为输入模式,并启用上拉电阻
  pinMode(START_PIN, INPUT_PULLUP);
  pinMode(STOP_PIN, INPUT_PULLUP);

  // 初始化串口通信,波特率为9600
  Serial.begin(9600);
}

void loop() {
    
    
  // 定义一个局部变量startButtonState,表示开始按钮的当前状态,并读取START_PIN引脚的值赋给它
  int startButtonState = digitalRead(START_PIN);

   // 定义一个局部变量stopButtonState,表示停止按钮的当前状态,并读取STOP_PIN引脚的值赋给它
   int stopButtonState = digitalRead(STOP_PIN);

   // 判断开始按钮是否被按下(即START_PIN引脚为低电平)
   if (startButtonState == LOW) {
    
    
     // 如果是,则判断秒表是否正在运行
     if (running == false) {
    
    
       // 如果不是,则将秒表设为运行状态,并调用micros()函数获取当前时间赋给startTime
       running = true;
       startTime = micros();
     }
   }

   // 判断停止按钮是否被按下(即STOP_PIN引脚为低电平)
   if (stopButtonState == LOW) {
    
    
     // 如果是,则判断秒表是否正在运行
     if (running == true) {
    
    
       // 如果是,则将秒表设为停止状态,并调用micros()函数获取当前时间赋给stopTime
       running = false;
       stopTime = micros();
     }
   }

   // 判断秒表是否正在运行
   if (running == true) {
    
    
     // 如果是,则通过串口输出当前时间与开始时间之差(单位秒),保留两位小数
     Serial.print("Elapsed time: ");
     Serial.print((micros() - startTime) / 1000000.0, 2);
     Serial.println(" s");
   } else {
    
    
     // 否则,通过串口输出停止时间与开始时间之差(单位秒),保留两位小数
     Serial.print("Elapsed time: ");
     Serial.print((stopTime - startTime) / 1000000.0, 2);
     Serial.println(" s");
   }
}

案例四:精确的定时生成信号:

const int outputPin = 9;
const unsigned long pulseInterval = 1000; // 脉冲间隔为1毫秒

void setup() {
    
    
  pinMode(outputPin, OUTPUT);
}

void loop() {
    
    
  static unsigned long previousMicros = 0;
  unsigned long currentMicros = micros(); // 获取当前时间

  if (currentMicros - previousMicros >= pulseInterval) {
    
    
    previousMicros = currentMicros;

    // 在特定时间间隔内生成脉冲信号
    digitalWrite(outputPin, HIGH);
    delayMicroseconds(10); // 脉冲宽度为10微秒
    digitalWrite(outputPin, LOW);
  }
}

在此案例中,使用micros()函数实现了精确的定时生成信号的功能。通过记录上一次生成信号的时间(previousMicros)和设定的时间间隔(pulseInterval),在当前时间与上一次时间间隔超过设定值时,生成脉冲信号。

案例五:测量信号脉冲宽度:

const int inputPin = 2;
unsigned long pulseStartTime = 0;
bool pulseStarted = false;

void setup() {
    
    
  pinMode(inputPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(inputPin), handlePulse, CHANGE);
}

void loop() {
    
    
  if (pulseStarted) {
    
    
    unsigned long pulseEndTime = micros(); // 获取当前时间
    unsigned long pulseDuration = pulseEndTime - pulseStartTime;
    pulseStarted = false;

    // 执行基于脉冲宽度的操作
    if (pulseDuration > 1000) {
    
    
      // 宽度大于1毫秒的脉冲,执行某些操作
    }
  }
}

void handlePulse() {
    
    
  if (digitalRead(inputPin) == HIGH) {
    
    
    pulseStartTime = micros(); // 记录上升沿的时间
    pulseStarted = true;
  }
}

在此案例中,使用micros()函数实现了测量信号脉冲宽度的功能。通过中断处理函数(handlePulse)记录信号的上升沿时间,并在下降沿时计算脉冲宽度。如果脉冲宽度大于1毫秒,则执行某些操作。

案例六:时间敏感的控制:

const int ledPin = 13;
const unsigned long blinkInterval = 500; // 闪烁间隔为0.5秒

void setup() {
    
    
  pinMode(ledPin, OUTPUT);
}

void loop() {
    
    
  static unsigned long previousMicros = 0;
  unsigned long currentMicros = micros(); // 获取当前时间

  if (currentMicros - previousMicros >= blinkInterval) {
    
    
    previousMicros = currentMicros;

    // 在特定时间间隔内闪烁LED
    digitalWrite(ledPin, !digitalRead(ledPin));
  }
}

在此案例中,使用micros()函数实现了时间敏感的LED闪烁控制。通过记录上一次闪烁的时间(previousMicros)和设定的闪烁间隔(blinkInterval),在当前时间与上一次时间间隔超过设定值时,切换LED的状态,实现LED的闪烁效果。

这些案例展示了在Arduino中使用micros()函数的实际运用,包括精确的定时生成信号、测量信号脉冲宽度和时间敏感的控制。根据具体的应用需求,可以进一步灵活运用micros()函数来实现更多功能。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_41659040/article/details/132641773