Увеличение частоты PWM по всем 6-ти пинам
- Войдите на сайт для отправки комментариев
Ср, 04/12/2019 - 15:37
Не нашёл ответа на форуме, в основном обсуждается разрядность PWM более 8 бит, задача иная нужно Шимить 6 пинов с увеличением частоты, можно с дискретностью позволяемой делителями Таймеров, разрядность 8 бит.
Реализуемо?
Да, кто ж не даёт-то? Если просто нужно (типа из звуковых частот уйти), так в статье про разрядность у меня и таблицы частот есть. Если же хочется гибко управлять частотой, так там же таймеры в три строки конфигурируются (см. #12 в той же статье). Да и вроде библиотека была типа PWM.h
Да, кто ж не даёт-то? Если просто нужно (типа из звуковых частот уйти), так в статье про разрядность у меня и таблицы частот есть. Если же хочется гибко управлять частотой, так там же таймеры в три строки конфигурируются (см. #12 в той же статье). Да и вроде библиотека была типа PWM.h
так читал я и даже про проблему 0 и 255 значения, мне надо синхронно, на всех шести пинах, именно частоту а не разрядность, по режиму FAST PWM получается для Таймера 2 использовать делители из ряда Таймера 0,1, по коду не понял )))
Так там же написано как частоту менять.
Насчёт синхронности раньше речи не было. Целиком синхронно? Или скважность может отличаться? Насколько синхронно? Какое расхождение допустимо?
Так там же написано как частоту менять.
Насчёт синхронности раньше речи не было. Целиком синхронно? Или скважность может отличаться? Насколько синхронно? Какое расхождение допустимо?
вообще-то показатель PWM разный, сейчас делаю очень просто, загружая в счетчики нужное вычисленное значение, расхождение в пределах времени исполнения кода весьма допустимо )))
Так настраиваю таймера:
TCCR1A |= _BV(COM1A1); // connect pin 9 to timer 1 channel A TCCR1A |= _BV(COM1B1); // connect pin 10 to timer 1 channel B TCCR2A |= _BV(COM2A1); // connect pin 11 to timer 2 channel A ...Так загружаю нужным значением PWM
или хотя бы по четырём каналам )))
Ну, а в чём тогда проблема? Настраивайте все 6 так - в чём беда-то? Я думал Вам надо суперсинхронность, хотел с этим поэкспериментировать.
Ну, а в чём тогда проблема? Настраивайте все 6 так - в чём беда-то? Я думал Вам надо суперсинхронность, хотел с этим поэкспериментировать.
супер синхронность желательна (даже очень желательна) по двум каналам )))
А частоту ШИМ - просто загружая соответствующие предделители?
Конечно.
супер синхронность желательна (даже очень желательна) по двум каналам )))
А по двум каналам она всегда будет абсолютно синхронна, если каналы от одного таймера. Проблема заставить все таймеры синхронно работать.
супер синхронность желательна (даже очень желательна) по двум каналам )))
А по двум каналам она всегда будет абсолютно синхронна, если каналы от одного таймера. Проблема заставить все таймеры синхронно работать.
если есть возможность попробовать по четырём, буду признателен!!!
если есть возможность попробовать по четырём, буду признателен!!!
возьми СТМ-ку, там таймеры 4х канальные
если есть возможность попробовать по четырём, буду признателен!!!
возьми СТМ-ку, там таймеры 4х канальные
ограничен 328 чипом )))
Ну, я попробую, но не сейчас. Может, завтра.
Ну, я попробую, но не сейчас. Может, завтра.
мне абсолютно не срочно и по шиму, если можно 1 килогерц и 7-8 килогерц
Только учти, что изменение частоты ШИМ на пинах связанных с Timer0 приведет к неправильной работе delay и millis. Если какие из используемых библиотек завязаны на это, то придется их править.
Только учти, что изменение частоты ШИМ на пинах связанных с Timer0 приведет к неправильной работе delay и millis. Если какие из используемых библиотек завязаны на это, то придется их править.
да я посматриваю в сторону atmega328pb, на третий таймер перевести, сериальный порт мне не нужен
Ну, в общем, я не понял в чём у Вас затык.
Настраивается таймер на частоту PWM просто подбором нужного делителя.
При этом на двух каналах одного таймера о синхронизации думать не надо. У каналов одинаковая частота и ноль они проходят вместе, значит никакого фазового сдвига не будет.
Если нужно строго синхронизовать два (или все три) таймера, то можно их выключить (обесточить), настроить, не забыв прописать 0 (или любое, но одинаковое для всех таймеров) значение в регистр счётчика, а потом включить все одновременно одной командой процессора. Они дружно стартуют и никакого фазового сдвига между ними не будет.
Вот пример на приблизительно 1 кГц и приблизительно 8 кГц (для 8 кГц закомментируйте строку №1)
#define ONE_KHZ // // Делители таймеров на 1 кГц // #ifdef ONE_KHZ // на самом деле 980Гц constexpr byte prescaler0 = bit(CS00) | bit(CS01); constexpr byte prescaler1 = bit(CS10) | bit(CS11); constexpr byte prescaler2 = bit(CS22); // // Делители таймеров на 8 кГц // #else // 8кГц (на самом деле 7812.5 Гц) constexpr byte prescaler0 = bit(CS01); constexpr byte prescaler1 = bit(CS11); constexpr byte prescaler2 = bit(CS21); #endif // // Настройка таймера 0 на FastPWM // void setupTimer0(void) { TCCR0A = bit(COM0A1) | bit(COM0B1) | bit(WGM01) | bit(WGM00); TCCR0B = prescaler0; TCNT0 = 0; // нужно, чтобы все таймеры стартовали синхронно OCR0A = 80; // уставнока скважности OCR0B = 150; // уставнока скважности TIMSK0 = 0; } // // Настройка таймера 1 на FastPWM // void setupTimer1(void) { TCCR1A = bit(COM1A1) | bit(COM1B1) | bit(WGM10); TCCR1B = bit(WGM12) | prescaler1; TCNT1 = 0; // нужно, чтобы все таймеры стартовали синхронно OCR1A = 60; // уставнока скважности OCR1B = 200; // уставнока скважности TIMSK1 = 0; } // // Настройка таймера 2 на FastPWM // void setupTimer2(void) { TCCR2A = bit(COM2A1) | bit(COM2B1) | bit(WGM21) | bit(WGM20); TCCR2B = prescaler2; TCNT2 = 0; // нужно, чтобы все таймеры стартовали синхронно OCR2A = 85; // уставнока скважности OCR2B = 170; // уставнока скважности TIMSK2 = 0; } void setup(void) { Serial.begin(57600); Serial.print("Fun is here"); pinMode(3, OUTPUT); pinMode(11, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); // // Обесточить ВСЕ таймеры // PRR |= (bit(PRTIM0) | bit(PRTIM1) | bit(PRTIM2)); // setupTimer0(); setupTimer1(); setupTimer2(); // // Запустить ВСЕ таймеры одной командой процессора // PRR &= ~(bit(PRTIM0) | bit(PRTIM1) | bit(PRTIM2)); } void loop(void){}В меге есть специальные регистр, который даёт возможность синхронизировать сразу всё таймеры
void setup() { pinMode (11,OUTPUT); pinMode (9,OUTPUT); pinMode (6,OUTPUT); GTCCR=(1<<TSM)|(1<<PSRASY)|(1<<PSRSYNC); TCNT0=0; TIMSK0=0; TCCR0A=(1<<COM0A1)|(1<<WGM00)|(1<<WGM01); TCCR0B=(1<<CS00); OCR0A=127; TCNT1=0; TIMSK1=0; TCCR1A=(1<<WGM10)|(1<<COM1A1); TCCR1B=(1<<WGM12)|(0<<WGM13)|(1<<CS10); ICR1=0; OCR1A=127; TCNT2=0; TIMSK2=0; TCCR2A=(1<<COM2A1)|(1<<WGM20)|(1<<WGM21); TCCR2B=(1<<CS20); OCR2A=127; GTCCR=0; } void loop() {}Благодарю! Сегодня поэкспериментирую!
В меге есть специальные регистр, который даёт возможность синхронизировать сразу всё таймеры
void setup() { pinMode (11,OUTPUT); pinMode (9,OUTPUT); pinMode (6,OUTPUT); GTCCR=(1<<TSM)|(1<<PSRASY)|(1<<PSRSYNC); TCNT0=0; TIMSK0=0; TCCR0A=(1<<COM0A1)|(1<<WGM00)|(1<<WGM01); TCCR0B=(1<<CS00); OCR0A=127; TCNT1=0; TIMSK1=0; TCCR1A=(1<<WGM10)|(1<<COM1A1); TCCR1B=(1<<WGM12)|(0<<WGM13)|(1<<CS10); ICR1=0; OCR1A=127; TCNT2=0; TIMSK2=0; TCCR2A=(1<<COM2A1)|(1<<WGM20)|(1<<WGM21); TCCR2B=(1<<CS20); OCR2A=127; GTCCR=0; } void loop() {}О меге я думал, тем более, что там два процессора, на 32U4 реализовать разбор протокола обмена, а на самой меге всё остальное
OCR1A = 60 и пр. OCRnA - установка частоты.
О меге я думал
Видимо, dmax имел в виду ATmega, т.к. в 328 такое тоже есть - сейчас посмотрел. Не пробовал, но в даташите написано.
есть специальные регистр, который даёт возможность синхронизировать сразу всё таймеры
Спасибо, буду знать.
может скважности?
А, да... Сорри. Фокус с TOP в OCRxA - это при PWM с фазовой коррекцией. Там OCRxA определяет частоту, а OCRxB - скважность. Сегодня только всю голову изломал этим.
PS, ан нет - Fast PWM-у тоже можно сделать произвольный TOP и задавать частоту: https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM -> Fast PWM Mode with OCRA top. Што-то меня этот PWM запутал опять, надо пойти поспать.
всё получается
void TIM16_WriteTCNT1(unsigned int i) { unsigned char sreg; unsigned int i; /* Save global interrupt flag */ sreg = SREG; /* Disable interrupts */ _CLI(); /* Set TCNT1 to i */ TCNT1 = i; /* Restore global interrupt flag */ SREG = sreg; }есть специальные регистр, который даёт возможность синхронизировать сразу всё таймеры
Спасибо, буду знать.
может имеет смысл в базу знаний по ШИМ на сайт добавить?
Может и имеет, но в принципе ... даташит надо внимательнее читать :)
Может и имеет, но в принципе ... даташит надо внимательнее читать :)
Там столько букв, столько букв, а чтобы разобраться и запомнилось, надо проверять на пробных скетчах...
void TIM16_WriteTCNT1(unsigned int i) { unsigned char sreg; unsigned int i; /* Save global interrupt flag */ sreg = SREG; /* Disable interrupts */ _CLI(); /* Set TCNT1 to i */ TCNT1 = i; /* Restore global interrupt flag */ SREG = sreg; }раз пишут, что надо заворачивать, значит надо заворачивать )))
Может и имеет, но в принципе ... даташит надо внимательнее читать :)
Евгений Петрович, не сыпьте соль на рану, что поделать, если последний зачет по аглицкому, в далеком СССР, был сдан за красивый, старинный словарь из "Старой Книги", а когда понадобилось, тут уже, то дед Альцгеймер зайдет шашками подвигать, то бабушка Деменция, с пирожком, чайку попить.))))
Гугель, неправославный, иногда вроде помогает, но слабо.((((
Долго втыкал, чем в 16-битном таймере WGM mode 10 отличается от WGM mode 11. Так вот, если кому-то интересно, тестовый скетч (двухлучевой осциллограф поможет увидеть):
#include <util/atomic.h> // Выбираем режим // WGM #10 (PWM, Phase Correct, TOP = ICR1) - PWM на каналы A и B с одной и той же частотой // или // WGM #11 (PWM, Phase Correct, TOP = OCR1A) - PWM на один канал B //#define WGM_MODE_10 // TOP таймера const uint16_t timerTop = 255; int8_t pwmStep = 1; uint16_t pwmValue = 5; const uint32_t shortPause = 25; const uint32_t longPause = 5000; void setup() { pinMode(9, OUTPUT); pinMode(10, OUTPUT); TCCR1A = TCCR1B = 0x00; OCR1B = OCR1A = 0x00; #ifdef WGM_MODE_10 // Режим канала A - неинвертированный TCCR1A |= (1 << COM1A1) | (0 << COM1A0); // Режим канала B - неинвертированный TCCR1A |= (1 << COM1B1) | (0 << COM1B0); // WGM режим #10 TCCR1A |= (1 << WGM11); TCCR1B |= (1 << WGM13); ICR1 = timerTop; #else // Режим канала A - неподключен к пину OC1A TCCR1A |= (0 << COM1A1) | (0 << COM1A0); // Режим канала B - неинвертированный TCCR1A |= (1 << COM1B0) | (1 << COM1B1); // WGM режим #11 TCCR1A |= (1 << WGM11) | (1 << WGM10); TCCR1B |= (1 << WGM13); OCR1A = timerTop; #endif // Делитель частоты /64 TCCR1B |= (1 << CS10) | (1 << CS11); } void loop() { uint8_t flipFlop = false; static uint8_t fireLed = false; // Изменение скважности pwmValue += pwmStep; if (timerTop == pwmValue || 0x00 == pwmValue) { pwmStep = -pwmStep; flipFlop = true; fireLed = !fireLed; } #ifdef WGM_MODE_10 // Вычисление новых значений скважности для каналов А и B uint16_t newOCR1A = pwmValue; uint16_t newOCR1B = timerTop - pwmValue; // Атомарная установка новых значений регистров ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { OCR1A = newOCR1A; OCR1B = newOCR1B; } #else // Вычисление новых значений скважности для канала B uint16_t newOCR1B = pwmValue; // Атомарная установка нового значения регистра ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { OCR1B = newOCR1B; } // Канал A используем, как хотим. digitalWrite(9, fireLed); #endif // При смене направления - пауза дольше delay(flipFlop ? longPause : shortPause); }А если кратко, то:
1) Применяя ICR1 в качестве TOP мы можем использовать два канала (A, B) для PWM с разной скважностью на произвольной частоте.
2) Применяя OCR1A в качестве TOP мы можем получить один канал (B) для PWM на произвольной частоте и один (A) - для других нужд. А так же использовать таймер захвата - ICR1-то не занят.
Закину картинки для наглядности:

#define ONE_KHZ // // Делители таймеров на 1 кГц // #ifdef ONE_KHZ // на самом деле 980Гц constexpr byte prescaler0 = bit(CS00) | bit(CS01); constexpr byte prescaler1 = bit(CS10) | bit(CS11); constexpr byte prescaler2 = bit(CS22); // // Делители таймеров на 8 кГц // #else // 8кГц (на самом деле 7812.5 Гц) constexpr byte prescaler0 = bit(CS01); constexpr byte prescaler1 = bit(CS11); constexpr byte prescaler2 = bit(CS21); #endif // // Настройка таймера 0 на FastPWM // void setupTimer0(void) { TCCR0A = bit(COM0A1) | bit(COM0B1) | bit(WGM01) | bit(WGM00); TCCR0B = prescaler0; TCNT0 = 0; // нужно, чтобы все таймеры стартовали синхронно OCR0A = 80; // уставнока скважности OCR0B = 150; // уставнока скважности TIMSK0 = 0; } // // Настройка таймера 1 на FastPWM // void setupTimer1(void) { TCCR1A = bit(COM1A1) | bit(COM1B1) | bit(WGM10); TCCR1B = bit(WGM12) | prescaler1; TCNT1 = 0; // нужно, чтобы все таймеры стартовали синхронно OCR1A = 60; // уставнока скважности OCR1B = 200; // уставнока скважности TIMSK1 = 0; } // // Настройка таймера 2 на FastPWM // void setupTimer2(void) { TCCR2A = bit(COM2A1) | bit(COM2B1) | bit(WGM21) | bit(WGM20); TCCR2B = prescaler2; TCNT2 = 0; // нужно, чтобы все таймеры стартовали синхронно OCR2A = 85; // уставнока скважности OCR2B = 170; // уставнока скважности TIMSK2 = 0; } unsigned long mill; unsigned int chas = 0; unsigned int mins = 0; unsigned int seks = 0; void setup(void) { Serial.begin(115200); Serial.println("Fun is here"); Serial.println(" "); pinMode(3, OUTPUT); pinMode(11, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); // // Обесточить ВСЕ таймеры // PRR |= (bit(PRTIM0) | bit(PRTIM1) | bit(PRTIM2)); // setupTimer0(); setupTimer1(); setupTimer2(); // // Запустить ВСЕ таймеры одной командой процессора // PRR &= ~(bit(PRTIM0) | bit(PRTIM1) | bit(PRTIM2)); mill = millis(); // Запустим часики } void loop(void){ if(millis()-mill >=1000){ seks++; mill=mill+1000; //Именно так, нам нужна долговременная точность часиков для проверки Serial.print(chas); Serial.print(":"); Serial.print(mins); Serial.print(":"); Serial.println(seks); } if(seks==60){ mins++; seks=0; } if(mins==60){ chas++; mins=0; } }и шимим
#define ONE_KHZ // // Делители таймеров на 1 кГц // #ifdef ONE_KHZ // на самом деле 980Гц constexpr byte prescaler0 = bit(CS00) | bit(CS01); constexpr byte prescaler1 = bit(CS10) | bit(CS11); constexpr byte prescaler2 = bit(CS22); // // Делители таймеров на 8 кГц // #else // 8кГц (на самом деле 7812.5 Гц) constexpr byte prescaler0 = bit(CS01); constexpr byte prescaler1 = bit(CS11); constexpr byte prescaler2 = bit(CS21); #endif // // Настройка таймера 0 на FastPWM // void setupTimer0(void) { TCCR0A = bit(COM0A1) | bit(COM0B1) | bit(WGM01) | bit(WGM00); TCCR0B = prescaler0; TCNT0 = 0; // нужно, чтобы все таймеры стартовали синхронно OCR0A = 80; // уставнока скважности OCR0B = 150; // уставнока скважности TIMSK0 = 0; } // // Настройка таймера 1 на FastPWM // void setupTimer1(void) { TCCR1A = bit(COM1A1) | bit(COM1B1) | bit(WGM10); TCCR1B = bit(WGM12) | prescaler1; TCNT1 = 0; // нужно, чтобы все таймеры стартовали синхронно OCR1A = 60; // уставнока скважности OCR1B = 200; // уставнока скважности TIMSK1 = 0; } // // Настройка таймера 2 на FastPWM // void setupTimer2(void) { TCCR2A = bit(COM2A1) | bit(COM2B1) | bit(WGM21) | bit(WGM20); TCCR2B = prescaler2; TCNT2 = 0; // нужно, чтобы все таймеры стартовали синхронно OCR2A = 85; // уставнока скважности OCR2B = 170; // уставнока скважности TIMSK2 = 0; } unsigned long mill; unsigned int chas = 0; unsigned int mins = 0; unsigned int seks = 0; volatile byte pwm1 = 80; volatile byte pwm2 = 150; volatile byte pwm3 = 60; volatile byte pwm4 = 200; volatile byte pwm5 = 85; volatile byte pwm6 = 170; void setup(void) { Serial.begin(115200); Serial.println("Fun is here"); Serial.println(" "); pinMode(3, OUTPUT); pinMode(11, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); // // Обесточить ВСЕ таймеры // PRR |= (bit(PRTIM0) | bit(PRTIM1) | bit(PRTIM2)); // setupTimer0(); setupTimer1(); setupTimer2(); // // Запустить ВСЕ таймеры одной командой процессора // PRR &= ~(bit(PRTIM0) | bit(PRTIM1) | bit(PRTIM2)); mill = millis(); // Запустим часики } void loop(void){ if(millis()-mill >=1000){ seks++; mill=mill+1000; //Именно так, нам нужна долговременная точность часиков для проверки OCR0A = ++pwm1; // уставнока скважности таймер 0 OCR0B = ++pwm2; // уставнока скважности OCR1A = ++pwm3; // уставнока скважности таймер 1 OCR1B = ++pwm4;; // уставнока скважности OCR2A = ++pwm5; // уставнока скважности таймер 2 OCR2B = ++pwm6; // уставнока скважности if(seks==60){ mins++; seks=0; } if(mins==60){ chas++; mins=0; } if(chas==24){ chas=0; } if(chas<10){ Serial.print("0"); } Serial.print(chas); Serial.print(":"); if(mins<10){ Serial.print("0"); } Serial.print(mins); Serial.print(":"); if(seks<10){ Serial.print("0"); } Serial.println(seks); } }Вот пример на приблизительно 1 кГц и приблизительно 8 кГц (для 8 кГц закомментируйте строку №1)
#define ONE_KHZ // // Делители таймеров на 1 кГц // #ifdef ONE_KHZ // на самом деле 980Гц constexpr byte prescaler0 = bit(CS00) | bit(CS01); constexpr byte prescaler1 = bit(CS10) | bit(CS11); constexpr byte prescaler2 = bit(CS22); // // Делители таймеров на 8 кГц // #else // 8кГц (на самом деле 7812.5 Гц) constexpr byte prescaler0 = bit(CS01); constexpr byte prescaler1 = bit(CS11); constexpr byte prescaler2 = bit(CS21); #endif // // Настройка таймера 0 на FastPWM // void setupTimer0(void) { TCCR0A = bit(COM0A1) | bit(COM0B1) | bit(WGM01) | bit(WGM00); TCCR0B = prescaler0; TCNT0 = 0; // нужно, чтобы все таймеры стартовали синхронно OCR0A = 80; // уставнока скважности OCR0B = 150; // уставнока скважности TIMSK0 = 0; } // // Настройка таймера 1 на FastPWM // void setupTimer1(void) { TCCR1A = bit(COM1A1) | bit(COM1B1) | bit(WGM10); TCCR1B = bit(WGM12) | prescaler1; TCNT1 = 0; // нужно, чтобы все таймеры стартовали синхронно OCR1A = 60; // уставнока скважности OCR1B = 200; // уставнока скважности TIMSK1 = 0; } // // Настройка таймера 2 на FastPWM // void setupTimer2(void) { TCCR2A = bit(COM2A1) | bit(COM2B1) | bit(WGM21) | bit(WGM20); TCCR2B = prescaler2; TCNT2 = 0; // нужно, чтобы все таймеры стартовали синхронно OCR2A = 85; // уставнока скважности OCR2B = 170; // уставнока скважности TIMSK2 = 0; } void setup(void) { Serial.begin(57600); Serial.print("Fun is here"); pinMode(3, OUTPUT); pinMode(11, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); // // Обесточить ВСЕ таймеры // PRR |= (bit(PRTIM0) | bit(PRTIM1) | bit(PRTIM2)); // setupTimer0(); setupTimer1(); setupTimer2(); // // Запустить ВСЕ таймеры одной командой процессора // PRR &= ~(bit(PRTIM0) | bit(PRTIM1) | bit(PRTIM2)); } void loop(void){}а вот с регистром PRR всё не так однозначно оказалось (((
В смысле? Что неоднозначно?
Видимо он обесточил ближайшую подстанцию этим регистром...
В смысле? Что неоднозначно?
да как-то исчезает ШИМ на пинах, подстанцию вроде не обесточивал )))
Ну, пример "от димакса" точно работает - я проверял говнокодом в лупе, прежде чем тиснуть в газету пост.
... void loop() { delay(5000); cbi(TCCR1B, CS11); cbi(TCCR2B, CS21); delay(5000); GTCCR = (1 << TSM) | (1 << PSRASY) | (1 << PSRSYNC); TCNT1 = 0x00; TCNT2 = 0x00; sbi(TCCR1B, CS11); sbi(TCCR2B, CS21); GTCCR = 0; delay(5000); cbi(TCCR1B, CS11); cbi(TCCR2B, CS21); delay(5000); TCNT1 = 0x00; TCNT2 = 0x00; sbi(TCCR1B, CS11); sbi(TCCR2B, CS21); delay(5000); } ...Да оба примера нормально работают, я оба проверял.
у меня тоже, я о PRR...
Да оба примера нормально работают, я оба проверял.
Если что-то может не заработать, у меня оно обязательно не заработает, вернули прибор, думал он неисправен, добавил в скетч мигание диодом, не мигает
#define PIN_ZUM 13 #define ONE_KHZ // // Делители таймеров на 1 кГц // #ifdef ONE_KHZ // на самом деле 980Гц constexpr byte prescaler0 = bit(CS00) | bit(CS01); constexpr byte prescaler1 = bit(CS10) | bit(CS11); constexpr byte prescaler2 = bit(CS22); // // Делители таймеров на 8 кГц // #else // 8кГц (на самом деле 7812.5 Гц) constexpr byte prescaler0 = bit(CS01); constexpr byte prescaler1 = bit(CS11); constexpr byte prescaler2 = bit(CS21); #endif // // Настройка таймера 0 на FastPWM // void setupTimer0(void) { TCCR0A = bit(COM0A1) | bit(COM0B1) | bit(WGM01) | bit(WGM00); TCCR0B = prescaler0; TCNT0 = 0; // нужно, чтобы все таймеры стартовали синхронно OCR0A = 80; // уставнока скважности OCR0B = 150; // уставнока скважности TIMSK0 = 0; } // // Настройка таймера 1 на FastPWM // void setupTimer1(void) { TCCR1A = bit(COM1A1) | bit(COM1B1) | bit(WGM10); TCCR1B = bit(WGM12) | prescaler1; TCNT1 = 0; // нужно, чтобы все таймеры стартовали синхронно OCR1A = 60; // уставнока скважности OCR1B = 200; // уставнока скважности TIMSK1 = 0; } // // Настройка таймера 2 на FastPWM // void setupTimer2(void) { TCCR2A = bit(COM2A1) | bit(COM2B1) | bit(WGM21) | bit(WGM20); TCCR2B = prescaler2; TCNT2 = 0; // нужно, чтобы все таймеры стартовали синхронно OCR2A = 85; // уставнока скважности OCR2B = 170; // уставнока скважности TIMSK2 = 0; } void setup(void) { Serial.begin(57600); Serial.print("Fun is here"); pinMode(3, OUTPUT); pinMode(11, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); // // Обесточить ВСЕ таймеры // PRR |= (bit(PRTIM0) | bit(PRTIM1) | bit(PRTIM2)); // setupTimer0(); setupTimer1(); setupTimer2(); // // Запустить ВСЕ таймеры одной командой процессора // PRR &= ~(bit(PRTIM0) | bit(PRTIM1) | bit(PRTIM2)); start_Buzzer(); } /*******************ПИЩАЛКА ********************/ void start_Buzzer(){ pinMode(PIN_ZUM,OUTPUT); attachInterrupt(1, Buzzer, RISING ); // analogWrite(pinINT1,0x80); //установим на пине частоту //490 гц скважность 2 } /* * void stop_Buzzer(){ detachInterrupt(1); digitalWrite(PIN_ZUM,LOW); } /* */ void Buzzer(void){ static int i=1000; if(!i--) { digitalWrite(PIN_ZUM, ! digitalRead(PIN_ZUM)); i=1000; } } void loop(void){}У меня мигает на полгерца примерно
У меня мигает на полгерца примерно
а Ардуино какая? испытываю на нано
я жеж говорю, точнее DIMAX, если у ua6em что-то имеет теоретическую возможность не заработать, оно обязательно не заработает )))
я сначала грешным делом подумал, что мне осциллограф спалили, но тут что-то другое, разберусь, отпишу...
другой компьютер, другая нано (рободин), загрузчик не перешивался, если не запускать синхронно (закомментировать строки 68 и 76) шим есть, светодиод моргает раз в секунду где-то, снять комментарии - после заливки разовая короткая вспышка и всё, шима нет... ЧЯДНТ...пните в нужном направлении, что посмотреть, была мысль, что проблема в загрузчике, здесь же он не менялся...
В смысле?
Пепелац улетел.... А далее никаких "в смысле" не существует.
"не могу понять" (c) Шейнин, записки следователя...
Если остановку таймеров выносить после их иницализации, то код работает, если до - нет
IDE 1.8.9 arduino nano ROBODYN
void setup(void) { Serial.begin(57600); Serial.print("Fun is here"); pinMode(3, OUTPUT); pinMode(11, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); // // Обесточить ВСЕ таймеры // //PRR |= (bit(PRTIM0) | bit(PRTIM1) | bit(PRTIM2)); // setupTimer0(); //PRR |= (bit(PRTIM0) | bit(PRTIM1) | bit(PRTIM2)); setupTimer1(); //PRR |= (bit(PRTIM0) | bit(PRTIM1) | bit(PRTIM2)); setupTimer2(); // // Запустить ВСЕ таймеры одной командой процессора // PRR |= (bit(PRTIM0) | bit(PRTIM1) | bit(PRTIM2)); PRR &= ~(bit(PRTIM0) | bit(PRTIM1) | bit(PRTIM2)); start_Buzzer(); }Долго втыкал, чем в 16-битном таймере WGM mode 10 отличается от WGM mode 11. Так вот, если кому-то интересно, тестовый скетч (двухлучевой осциллограф поможет увидеть):
#include <util/atomic.h> // Выбираем режим // WGM #10 (PWM, Phase Correct, TOP = ICR1) - PWM на каналы A и B с одной и той же частотой // или // WGM #11 (PWM, Phase Correct, TOP = OCR1A) - PWM на один канал B //#define WGM_MODE_10 // TOP таймера const uint16_t timerTop = 255; int8_t pwmStep = 1; uint16_t pwmValue = 5; const uint32_t shortPause = 25; const uint32_t longPause = 5000; void setup() { pinMode(9, OUTPUT); pinMode(10, OUTPUT); TCCR1A = TCCR1B = 0x00; OCR1B = OCR1A = 0x00; #ifdef WGM_MODE_10 // Режим канала A - неинвертированный TCCR1A |= (1 << COM1A1) | (0 << COM1A0); // Режим канала B - неинвертированный TCCR1A |= (1 << COM1B1) | (0 << COM1B0); // WGM режим #10 TCCR1A |= (1 << WGM11); TCCR1B |= (1 << WGM13); ICR1 = timerTop; #else // Режим канала A - неподключен к пину OC1A TCCR1A |= (0 << COM1A1) | (0 << COM1A0); // Режим канала B - неинвертированный TCCR1A |= (1 << COM1B0) | (1 << COM1B1); // WGM режим #11 TCCR1A |= (1 << WGM11) | (1 << WGM10); TCCR1B |= (1 << WGM13); OCR1A = timerTop; #endif // Делитель частоты /64 TCCR1B |= (1 << CS10) | (1 << CS11); } void loop() { uint8_t flipFlop = false; static uint8_t fireLed = false; // Изменение скважности pwmValue += pwmStep; if (timerTop == pwmValue || 0x00 == pwmValue) { pwmStep = -pwmStep; flipFlop = true; fireLed = !fireLed; } #ifdef WGM_MODE_10 // Вычисление новых значений скважности для каналов А и B uint16_t newOCR1A = pwmValue; uint16_t newOCR1B = timerTop - pwmValue; // Атомарная установка новых значений регистров ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { OCR1A = newOCR1A; OCR1B = newOCR1B; } #else // Вычисление новых значений скважности для канала B uint16_t newOCR1B = pwmValue; // Атомарная установка нового значения регистра ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { OCR1B = newOCR1B; } // Канал A используем, как хотим. digitalWrite(9, fireLed); #endif // При смене направления - пауза дольше delay(flipFlop ? longPause : shortPause); }А если кратко, то:
1) Применяя ICR1 в качестве TOP мы можем использовать два канала (A, B) для PWM с разной скважностью на произвольной частоте.
2) Применяя OCR1A в качестве TOP мы можем получить один канал (B) для PWM на произвольной частоте и один (A) - для других нужд. А так же использовать таймер захвата - ICR1-то не занят.
кстати увидел у DIMAX (я о строке 43)