Как подсчитать количество нарастающих фронтов на DS3231 rtc?
Я использую DS3231 rtc, и мне нужно получить от него точность в миллисекундах, поэтому я решил использовать генерируемые им часы с частотой 32 кГц. Я написал код, который будет подсчитывать нарастающие и спадающие фронты с помощью прерывания с (параметрами RISING или FALLING), но я получаю только нули на своей плате Serial для подсчета.
Вот код, который я использую:
#include <DS3231.h>
#include <RTClib.h>
#include <Wire.h>
#include "rtc.h"
#define InterruptPin 3
volatile long lcnt = 0;
RTC_DS3231 rtc;
void setup() {
Wire.begin();
Serial.begin(74880); // инициализируем последовательный порт
pinMode(InterruptPin, INPUT_PULLUP);
rtc.begin();
rtc.adjust(DateTime(F(__DATE__),F(__TIME__)));
attachInterrupt(digitalPinToInterrupt(InterruptPin), fcnt, FALLING);
}
void loop() {
unsigned long a=millis();
if (a<1000){
Serial.println(lcnt);
}
}
void fcnt(){
lcnt+=1;
}
Я просто хочу проверить, сколько у меня нарастающих фронтов за 1 с. Странно то, что раньше этот код работал, а теперь нет ^^'... Не знаю, изменил ли я что-то по ошибке или удалил что-то полезное.
Может ли кто-нибудь помочь мне решить эту небольшую проблему?
Большое спасибо за ваше время!
@JamesONeil, 👍1
Обсуждение2 ответа
Я не уверен, почему вы получаете 0 как таковой, но ваша методология прерываний и переменных оставляет желать лучшего (вероятно, причина "учебников", которым вы следовали).
Меня больше всего беспокоит то, что вы используете 32-битную "длинную" переменную в прерывании и ссылаетесь на нее непосредственно вне прерывания. Arduino — это 8-битная система, а это означает, что все обращения к этой переменной требуют множества инструкций для упорядочивания (разделение на 4 8-битных значения, манипулирование ими, рекомбинация и т. д.). Из-за этого никакие операции с этой переменной не являются «атомарными».
Вы должны сделать их атомарными. Если вы этого не сделаете, то вполне возможно, что прерывание сработает и изменит значение в середине того, что вы делаете с этим значением.
Самый простой способ сделать его атомарным — отключить прерывания, затем скопировать значение в другую переменную и/или изменить его, а затем снова включить прерывания.
Вот пример, который я считаю стабильным:
#include <DS3231.h>
#include <RTClib.h>
#include <Wire.h>
#include "rtc.h"
#define InterruptPin 3
volatile uint32_t lcnt = 0;
RTC_DS3231 rtc;
void setup() {
Wire.begin();
Serial.begin(74880); // инициализируем последовательный порт
pinMode(InterruptPin, INPUT_PULLUP);
rtc.begin();
rtc.adjust(DateTime(F(__DATE__),F(__TIME__)));
attachInterrupt(digitalPinToInterrupt(InterruptPin), fcnt, FALLING);
}
void loop() {
static uint32_t ts = millis();
uint32_t a = millis();
if (a - ts >= 1000) {
ts = a;
noInterrupts();
uint32_t currentCount = icnt;
icnt = 0;
interrupts();
Serial.println(currentCount);
}
}
void fcnt(){
lcnt+=1;
}
Это должно напечатать количество импульсов за последовательные 1-секундные периоды.
Спасибо за ваш ответ, я загрузил ваш код, и я все еще получаю только нули каждую секунду на моем экране..., @JamesONeil
@JamesONeil Тогда вам следует трижды проверить свою проводку., @Majenko
Я уже использую одно прерывание от ds3231 для будильника на контакте SQW, чтобы разбудить мою Arduino, и он отлично работает, поэтому проблема может исходить только от контакта тактовой частоты 32 кГц. Я дважды проверил свою проводку, и ничего там не было..., @JamesONeil
Я использовал тот же код, что и ваш, просто изменил тип данных с uint32_t на unsigned long, и все заработало. Может быть, вы можете попробовать то же самое.
- RtcDateTime' не называет тип
- Сбой Arduino во время последовательной печати без очевидной причины
- Будет ли адаптер питания 12В постоянного тока, 1А подавать слишком большую мощность и повредит Arduino Mega 2560?
- RTC и SD работают отдельно, а не вместе
- Ошибка модуля часов реального Времени-DS3231
- Возникла проблема с переобъявлением символа другого типа
- Как запрограммировать Robotdyn Mega 2560 PRO MINI?
- Отключите автоматический сброс Mega 2560 на последовательном мониторе, открытом с помощью резистора 60 Ом.
попробуйте отключить подтягивающий резистор на входном контакте, @jsotola