Как контролировать мигание светодиода во время работы таймера?
Когда я нахожусь в 30-секундном режиме ожидания, я хочу включать и выключать светодиод с интервалом в 5 секунд.
Как я могу сделать то, что хочу, используя функцию read_counter()
?
Проблема здесь в том, что я уже нахожусь в функции таймера с помощью функции read_counter()
.
void wait_function() {
timer_init();
while(read_counter()<30000) { //30 секунд ожидания
// Светодиод мигает с интервалом в 1 секунду ???
}
}
Примечание: Функция read_counter() увеличивается каждые 1 миллисекунду с помощью вектора ISR COMPA. Я пробовал много раз и не мог найти стабильного решения. Пример:
if (read_counter() % 1000) PORTB^=(1<<LED);
Обновление: Мой новый код:
while((TIFR1 & (1 << OCF1A))==0) //4secondIf я делаю этот цикл 8 раз, он
//составляет 32 секунды.
{
if(TCNT1%15624==0) //за 15624=1 секунду,
PORTA^=(1<<0);
//led_blink_1s
}
Но это не работает.Должен ли я использовать функцию задержки util?
3 ответа
Ваш цикл ожидания выполняется намного быстрее, чем один раз в миллисекунду, и даже быстрее в секунду. Таким образом, чтобы получить только одно "событие" в секунду, вам нужно обнаружить изменение второго.
void wait_function() {
timer_init();
for (int second = 0; second < 30; ++second) { // 30 секунд ожидания
// Дождитесь следующей секунды
int old_second = read_counter() / 1000;
int new_second;
do {
new_second = read_counter() / 1000;
} while (new_second == old_second);
// Светодиод мигает с интервалом в 1 секунду
PORTB ^= 1 << LED;
}
}
Однако вы можете подумать о рефакторинге своего таймера. Вы можете поместить деление в ISR, а затем установить флаг, если прошла секунда. В цикле ожидания вы можете дождаться флага, сбросить его и переключить светодиод.
ПРАВКА:
Если у вас есть (псевдо) код, как это:
while (!timed_out) {
if (timer % ticks_per_second == 0) {
do_something();
}
}
у вас будет следующее ошибочное поведение: предполагается, что цикл выполняется 1 миллион раз в секунду, а таймер увеличивается на 20000 раз в секунду.
- Например, таймер начинается с 1000 и только что увеличился.
- Цикл выполняется 50 раз, пока таймер не увеличится до 1001.
- Это происходит многократно, пока таймер не получит 20000, что будет после (20000 - 1001) * 50 = 949950 циклов.
- Теперь цикл будет выполняться 50 раз, в то время как таймер все еще находится на отметке 20000.
- Условие
истинно
при каждом повторении, поэтомуdo_something()
будет выполняться 50 раз подряд. - Затем таймер увеличивается до 20001, и условие становится
ложным
.
Это именно то, что вы наблюдаете: если условие if
становится истинным
, его оператор будет выполняться повторно.
Поскольку связь между частотой повторения цикла и частотой таймера не является предполагаемым значением (но аналогична) и даже зависит от выполняемых инструкций, состояние выходного сигнала субъективно случайно. Если команда XOR выполняется четным числом, светодиод не меняется, а если он выполняется нечетным числом, светодиод меняется.
я обновил свой код, но он работает неправильно., @harun caliskanoglu
У вас все еще есть та же ошибка: пока выполняется цикл "while", условие "if" будет истинным много раз в секунду. Как и угаданное число, предположим, что цикл выполняется 1 миллион раз в секунду. Условие TCNT1% 15624==0
будет выполняться примерно 60 раз подряд каждую секунду. Кроме того, TCNT1
будет переполнен на 65535 до 0., @the busybee
Если счетчик считывания уже увеличивается один раз в миллисекунду, используйте его для определения времени мигания светодиода:
void wait_function() {
timer_init();
bool LED_State = LOW
while(read_counter()<30000) { //30 секунд ожидания
// Светодиод мигает с интервалом в 1 секунду ???
if (read_counter % 1000 == 0) { //Переключите 1000 на 500 здесь, если он мигает слишком медленно
LED_State = !LED_State;
digitalWrite(LEDPin, LED_State ? HIGH : LOW);
}
}
}
Этот код включит светодиод на одну секунду, затем выключит на одну секунду и т. Д. (Для общего времени цикла 2 секунды.) Если вы хотите, чтобы полный цикл включения-выключения длился 1 секунду, уменьшите значение оператора if с 1000 до 500.
Мое решение:
uint16_t st_led=0;
uint16_t et_led=0;
while((TIFR1 & (1 << OCF1A))==0) //30 секунд
{
st_led=TCNT1;
et_led=st_led;
while((et_led-st_led)<=15624) //1 секунда
{
et_led=TCNT1;
}
PORTA ^= (1<<ledno);
}
TIFR1=(1<<OCF1A);
TCCR1B=0;
- 4-битный счетчик вверх и вниз
- Светодиод Arduino PWM с замиранием в сборке
- Изменчивая переменная не обновляется с таймера ISR
- Прерывания TIMER1 CTC не работают с avr-gcc
- Не удается получить OC1B (контакт 10) для вывода
- Несколько условий оператора if
- Светодиоды: разница между общим анодом и общим катодом
- Как сделать очень долгую функцию delay(), несколько часов
подсчитайте шесть 5-секундных интервалов ... это не полностью описывает, как светодиод должен мигать "включите и выключите светодиод с 5-секундными интервалами"., @jsotola
это не вопрос о программном или аппаратном обеспечении arduino, поэтому он не по теме, @Juraj
`if (read_counter() / 5000 % 2) PINB^=(1<, @Gerben
я обновил свой код, но он работает неправильно., @harun caliskanoglu