Может ли Arduino uno регулировать входную квадратную волну, фазу и частоту только с помощью таймера-счетчика?
Требования:
- У меня есть входной импульсный вход 4 кГц
- Разделите его частоту пополам
- Произвольно отрегулируйте фазу
- Произвольно регулировать пошлину
- Выведите наружу модифицированный импульс
Мое решение (CPU):
uint8_t cnt = 0;
uint16_t t1 = 235;
uint16_t t2 = 5;
String cmd;
void setup() {
pinMode(3, OUTPUT);
pinMode(2, INPUT);
Serial.begin(9600);
delay(500);
attachInterrupt(digitalPinToInterrupt(2), rising_edge, RISING);
Serial.println("PWM init");
}
void loop() {
if (Serial.available() > 0) {
cmd = Serial.readString();
if (cmd.substring(0,8) == "setdelay"){
t1 = cmd.substring(9).toInt();
Serial.print("setting delay to ");
Serial.print(t1);
Serial.println(" us");
}
else if (cmd.substring(0,7) == "sethigh"){
t2 = cmd.substring(8).toInt();
Serial.print("setting high time to ");
Serial.print(t2);
Serial.println(" us");
}
Serial.flush();
}
}
void rising_edge() {
cnt = cnt + 1;
if (cnt >= 2) { //разделить на 2
delayMicroseconds(t1);
digitalWrite(3,HIGH);
delayMicroseconds(t2);
digitalWrite(3,LOW);
cnt = 0;
}
}
Однако это сильно использует процессор, и мне нужно использовать процессор для чего-то другого.Можно ли реализовать все это с помощью ТК ?
Заранее спасибо !
@7E10FC9A, 👍2
Обсуждение1 ответ
Лучший ответ:
это сильно использует процессор, и мне нужно использовать процессор для чего-то еще
Проблема с этим кодом заключается в том, что is сильно использует процессор для напряженного ожидания, а не для выполнения полезной работы. Вы должны попытаться избавиться от этих циклов ожидания:
Serial.ReadString()
: см. Сообщение в блоге Majenko Reading Serial на ArduinodelayMicroseconds()
: для этого вы действительно можете использовать таймер.
Для генерации импульсов вы можете сохранить примерно ту же логику, что и ваш существующий код: выводить один импульс каждый раз , когда на входе ощущается восходящее ребро. Этот импульс может быть удобно сгенерирован Таймер 1 на выводе 9 с помощью ШИМ - режима и остановкой таймера после одного цикла. Я бы использовал инвертирующий режим ШИМ с таймером , начинающимся с нуля на входном импульсе:
в
микросекундах t1 сопоставление устанавливает высокое значение выходного сигнала
при
t1+t2
микросекундах переполнение таймера устанавливает низкий уровень выходного сигнала, а прерывание переполнения останавливает и сбрасывает таймер
Вот предварительная, непроверенная реализация:
// Установите тайминги импульсов. Вызывается из loop() по запросу пользователя.
void set_timings(uint16_t t1, uint16_t t2)
{
uint16_t ocr1a = t1 * 16 - 1; // начальное время в НИЗКОМ состоянии
uint16_t icr1 = (t1 + t2) * 16 - 1; // период таймера
noInterrupts(); // защита критической секции
OCR1A = ocr1a;
ICR1 = icr1;
interrupts();
}
// Настройка таймера 1. Вызывается из setup().
void setup_timer() {
DDRB |= _BV(PB1); // установить вывод digital 9 = PB1 = OC1A в качестве выхода
TCCR1A = _BV(COM1A0) // ШИМ на OC1A, режим инвертирования
| _BV(COM1A1) // то же самое
| _BV(WGM11); // режим 14: быстрый ШИМ, top = ICR1
TCCR1B = _BV(WGM12) // то же самое
| _BV(WGM13) // то же самое
| 0; // остановлено
TCNT1 = 0; // сброс
TIFR1 = _BV(TOV1); // очистить флаг переполнения
TIMSK1 = _BV(TOIE1); // включить прерывание переполнения
set_timings(235, 5); // начальные тайминги
}
// Прерывание, вызванное восходящим фронтом входа.
void on_rising_edge() {
static uint8_t count;
if (++count % 2) return; // разделить на 2
TCCR1B |= _BV(CS10); // таймер запуска, часы @ F_CPU
}
// Остановите и сбросьте таймер, когда он переполнится.
ISR(TIMER1_OVF_vect) {
TCCR1B = 0; // стоп
TCNT1 = 0; // сброс
}
- ATmega328P - проблема с использованием таймера 2 для генерации тона
- максимальная частота ШИМ на основе прерываний при 500 Гц
- Генерация стабильной частоты
- Можно ли сгенерировать точный тактовый импульс 15 кГц с помощью ардуино?
- Светодиод Arduino PWM с замиранием в сборке
- Изменчивая переменная не обновляется с таймера ISR
- генерировать два сдвинутых по фазе ШИМ-импульса, запускаемых внешним сигналом с частотным разделением, с помощью Arduino uno?
- Точность синхронизации Arduino nano
Вы можете использовать входящие тактовые импульсы в качестве внешнего (асинхронного) тактового источника для timer2. Для начала посмотрите регистр АССР в таблице данных. Вы не можете изменить рабочий цикл только с помощью этого метода. Хотя вы используете дополнительный таймер в "режиме одного выстрела", но это все равно потребует прерываний., @Gerben