首页 > 解决方案 > Arduino P10 显示和时间计数

问题描述

每个人,我正在使用,P10 Dot Matrix DisplayArduino Uno. 我正在使用此链接中的 P10 库。P10_LED我需要在显示模块上显示一小时倒计时。给定的库使用TimerOne库。因此,对于倒计时,我使用的是MsTimer2库,它使用了 arduino 的 timer2。

当我单独运行这两个库时,我在显示屏上的滚动是完美的,我的定时器库也产生了一个纯 1 秒的中断。现在我所做的是在我的项目中添加了两个库,并且我正在倒计时。但现在突然我的MsTimer2不产生纯 1 秒。

这是代码。

#include <MsTimer2.h>
#include <TimerOne.h>
#include"SPI.h"
#include <ledP10.h>

LedP10 myled;
uint8_t minute = 0, second = 0, hour = 1;
volatile bool xIsCountDone = false;
volatile bool xIsInterruptOcuured = false;
char time_buff[100];

void setup() 
{
    Serial.begin(9600);
    myled.init(3,4,8,9 ,3);
    sprintf((char*)time_buff, "    %d%d:%d%d:%d%d", (hour/10), (hour%10),(minute/10), (minute%10),(second/10), (second%10));
    Serial.println((char*)time_buff);
    myled.showmsg_single_static((char*)time_buff, 0);
    xIsInterruptOcuured = false;
    //myled.showmsg_single_scroll("this is single led test",2,8,0);
    MsTimer2::set(1000, count);
    MsTimer2::start();
}

void loop() {
  if (xIsInterruptOcuured == true)
  {
    sprintf((char*)time_buff, "    %d%d:%d%d:%d%d", (hour/10), (hour%10),(minute/10), (minute%10),(second/10), (second%10));
    Serial.println((char*)time_buff);
    myled.showmsg_single_static((char*)time_buff, 0);
    xIsInterruptOcuured = false;
  }
}

void count(){
  second--;
  if (second <= 0 || second > 59)
  {
    second = 59;
    minute--;
    if (minute <= 0 || minute > 59)
    {
      minute = 59;
      hour--;
      if (hour <= 0 || hour > 12)
      {
        xIsCountDone =true;
      }
    }
  }
  Serial.println(millis());
  xIsInterruptOcuured = true;
}

在中断例程中,我正在打印millis()以查看中断发生的毫秒数。结果是这样的。

15:33:02.684 -> 1199
15:33:04.371 -> 2396
15:33:06.059 -> 3592
15:33:07.746 -> 4783
15:33:09.434 -> 5986
15:33:11.121 -> 7181
15: 33:12.855 -> 8379
15:33:14.543 -> 9578
15:33:16.230 -> 10768
15:33:17.918 -> 11974
15:33:19.605 -> 13168 15:33:21.292 -> 14365
15:
3 22.980 -> 15562
15:33:24.667 -> 16751
15:33:26.402 -> 17955

当我只使用MsTimer2库时,结果是这样的。

15:37:21.241 -> 998
15:37:22.226 -> 1998
15:37:23.257 -> 2998
15:37:24.241 -> 3998
15:37:25.226 -> 4998
15:37:26.257 -> 5998
15: 37:27.241 -> 6998
15:37:28.225 -> 7998
15:37:29.257 -> 8998
15:37:30.241 -> 9998
15:37:31.225 -> 10998
15:37:32.256 -> 11998
15:37: 33.241 -> 12998
15:37:34.225 -> 13998
15:37:35.256 -> 14998

我的猜测,这是因为TimerOne图书馆而发生的,但我找不到解决方案。其中ledP10.cpp有一个回调方法timer1,它包含循环和可能的代码行。但是timer1的中断优先级是否高于timer2?但根据 ATmega328p 数据表,向量号。Timer2 小于 Timer1。这不是意味着 Timer2 具有更高的优先级吗?我的最终目标是倒计时一小时。对此问题的任何帮助或我遗漏的任何其他信息将非常有用,或者除了使用 timer2 中断之外的任何其他解决方案,我们将不胜感激。

问候。

编辑

这是我与 millis() 一起使用的代码,给了我大约 12 分钟的差异。

uint8_t new_buff[100];
unsigned long startMillis;  //some global variables available anywhere in the program
unsigned long currentMillis;
const unsigned long period = 1000;  //the value is a number of milliseconds
uint8_t minute = 0, second = 0, hour = 1;
char time_buff[100];
void setup() 
{
    myled.init(3,4,8,9,3);
    Serial.begin(9600);
    sprintf((char*)time_buff, "    %d%d:%d%d:%d%d", (hour/10), (hour%10),(minute/10), (minute%10),(second/10), (second%10));
    //Serial.println((char*)time_buff);
    myled.showmsg_single_static((char*)time_buff, 0);
    startMillis = millis();
}



void loop() {
  currentMillis = millis();  //get the current "time" (actually the number of milliseconds since the program started)
  if (currentMillis - startMillis >= period)  //test whether the period has elapsed
  {
    Serial.println(millis());
    second--;
    startMillis = currentMillis;  //IMPORTANT to save the start time of the current LED state.
    if (second <=0 || second > 59)  {
      second = 59;
      minute--;
      if (minute <=0 || minute > 59)  {
        minute = 59;
        hour--;
        if (hour <= 0 || hour > 12) {
          hour = 0;
        }
      }
    }
    sprintf((char*)time_buff, "    %d%d:%d%d:%d%d", (hour/10), (hour%10),(minute/10), (minute%10),(second/10), (second%10));
    myled.showmsg_single_static((char*)time_buff, 0);
    startMillis = currentMillis;
  }
}

标签: timerarduinodot-matrix

解决方案


此答案针对您的示例,使用millis(). 通过不设置相对于当前时间的下一次更新,您可以避免随着时间的推移累积错误。而是每次将其增加一秒。这样,主循环是否被中断阻塞几毫秒都没有关系。

另请注意,您不必分别保存小时、分钟和秒,您可以计算它们:

unsigned long nextMillis = 1000;
unsigned long targetTime = 1 * 60 * 60 * 1000; // 1 hour in milliseconds

void setup(){
    myled.init(3,4,8,9,3);
    Serial.begin(9600);
    updateMyLed(0);
}


void updateMyLed( unsigned long elapsedTime ){

    char buffer[100];       
    unsigned long timeLeftInSeconds = (targetTime - elapsedTime) / 1000;

    uint8_t hour = timeLeftInSeconds / 3600;
    timeLeftInSeconds -= hour * 3600;
    uint8_t minute = timeLeftInSeconds / 60;
    uint8_t second = timeLeftInSeconds - (minute * 60);

    sprintf((char*)buffer, "    %d%d:%d%d:%d%d", (hour/10), (hour%10), (minute/10), (minute%10), (second/10), (second%10));
    myled.showmsg_single_static((char*)buffer, 0);
}

void loop() {

    if( millis() >= nextMillis ){
        updateMyLed(nextMillis);
        nextMillis += 1000;
    }

}

推荐阅读