каждый, я использую, P10 Dot Matrix Display
с Arduino Uno
. Я использую библиотеку P10 по этой ссылке. P10_LED и мне нужно отобразить обратный отсчет за один час на модуле дисплея. Данная библиотека использует библиотеку TimerOne . Так что для обратного отсчета я использую библиотеку MsTimer2 , которая использует таймер arduino.
Когда я по отдельности запускаю обе библиотеки, моя прокрутка на дисплее идеальна, и моя библиотека таймеров также генерирует чистуюПрерывание 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 -> 119915: 33: 04.371 -> 239615: 33: 06.059 -> 359215: 33: 07.746 -> 478315: 33: 09.434 -> 598615: 33: 11.121 -> 718115: 33: 12.855 -> 837915: 33: 14.543 -> 957815: 33: 16.230 -> 1076815: 33: 17.918 -> 1197415: 33: 19.605 -> 1316815: 33: 21.292 -> 1436515: 33: 22,980 -> 1556215: 33: 24.667 -> 1675115: 33: 26.402 -> 17955
Когда я использую только библиотеку MsTimer2
, результаты выглядят примерно так:
15: 37: 21.241 -> 99815: 37: 22.226 -> 199815: 37: 23.257 -> 299815: 37: 24.241 -> 399815: 37: 25.226 -> 499815: 37: 26.257 -> 599815: 37: 27.241 -> 699815: 37: 28.225 -> 799815: 37: 29.257 -> 899815: 37: 30.241 -> 999815: 37: 31.225 -> 1099815: 37: 32.256 -> 1199815: 37: 33.241 -> 1299815: 37: 34.225 -> 1399815: 37: 35.256 -> 14998
Полагаю, это происходит из-за библиотеки TimerOne
, но я не смог найти решение. В ledP10.cpp
есть метод обратного вызова для timer1
, который содержит циклы и может содержать строку кода. Но приоритет прерываний по таймеру1 выше, чем по таймеру2? Но согласно спецификации ATmega328p, вектора нет. для Timer2 меньше, чем Timer1. Разве это не означает, что Timer2 имеет более высокий приоритет? Моя конечная цель - сделать часовой отсчет. Будем благодарны за любую помощь с этой проблемой или любую дополнительную информацию, которую я пропускаю, которая будет полезна или любое другое решение, кроме использования прерывания timer2.
С уважением.
EDIT
Вот код, который я использовал с 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;
}
}