Квадратная волна 100 Гц с рабочим циклом 50% в цифровом выводе 3 и проверка с помощью вывода 4
Я застрял на этом на некоторое время, я пытаюсь генерировать прямоугольную волну 100 Гц с рабочим циклом 50% на выводе 3 и пытаюсь проверить ее с помощью провода на выводе 4; Я получаю 64000, но не 100 в последовательном мониторе.
#define LEDPIN 3
uint16_t val2= pulseIn(4, HIGH);
ISR(TIMER1_COMPA_vect) { digitalWrite(LEDPIN, !digitalRead(LEDPIN)); }
void setup() {
Serial.begin(9600);
pinMode(LEDPIN, OUTPUT);
// initialize Timer1 (the 16-bit timer) using channel A output compare
noInterrupts(); // disable global interrupts
// TIMER 1 for interrupt frequency 100 Hz:
cli(); // stop interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// set compare match register for 100 Hz increments
OCR1A = 19999; // = 16000000 / (8 * 100) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS12, CS11 and CS10 bits for 8 prescaler
TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei(); // allow interrupts
//TCCR1A = 0; // Timer/Counter Control Register 1A
//TCCR1B = 0; // (both control registers need to be configured)
//// set compare match register to desired timer count:
//OCR1A = 15624; // Output Compare Register 1A (i.e., for channel A)
//TCCR1B |= (1 << WGM12); // CTC (Clear Timer on Compare Match) mode
//TCCR1B |= (1 << CS10); // for 1,024 prescaler; UNO has a 16 MHz clock
//TCCR1B |= (1 << CS12);
//TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
interrupts(); // enable global interrupts:
}
void loop() {
uint16_t val = OCR1A/8;
ICR1 = val -1;
OCR1A = val/2 - 1 ; // 50% duty cycle for pin 3
//OCR1B = val/2 - 1 ; // 50% duty cycle for pin 4
//uint16_t val2= pulseIn(4, HIGH);
Serial.print(val2);
delay(1000);
Serial.print("\n");
}
@ram patel, 👍1
1 ответ
Вы написали:
uint16_t val2 = pulseIn(4, HIGH);
Нет смысла вызывать это здесь, так как таймер не был инициализирован. В этом контексте вы, вероятно, не можете ожидать ничего, кроме тайм-аута .
noInterrupts();
cli();
Эти два понятия являются синонимами. Не нужно повторяться. На самом деле, вообще не нужно блокировать прерывания.
sei();
interrupts();
То же.
OCR1A = 19999; // = 16000000 / (8 * 100) - 1
Предполагается, что это вызовет прерывания на частоте 100 Гц. Но если вам нужен выходной сигнал 100 Гц, вы должны запускать прерывания на частоте 200 Гц (два прерывания за цикл). Таким образом:
OCR1A = 9999; // = (16 MHz / 8) / (2 * 100 Hz) - 1
Затем,
// Установите биты CS12, CS11 и CS10 для 8 прескалеров
TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10);
Это настройка таймера 1 для внешнего источника синхронизации. Если вам
нужен прескалер ÷8, вы должны установить только бит CS11
. Проверьте данные.
uint16_t val = OCR1A/8;
ICR1 = val -1;
OCR1A = val/2 - 1 ; // 50% duty cycle for pin 3
Для меня это не имеет никакого смысла. Почему вы устанавливаете ICR1
? Почему
вы меняете OCR1A
, хотя он уже был настроен в setup()
?
Вы можете удалить все это. Вот loop()
Я использовал для тестирования:
void loop() {
Serial.println(pulseIn(3, HIGH));
delay(1000);
}
И он неоднократно печатал 4955
, что довольно близко к ожидаемому
значению (а именно 5000).
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
Спасибо за вашу помощь., @ram patel
TCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10);
делится на 8. Это смещение пары нулей. Это какTCR1B |= (0b010 << CS10);
но мне нравится `0b010<, @Dave X