Потрібна допомога в розумінні дзеркального відображення таймера AVR ATMEGA / ATTINY


10

Я намагаюся використовувати Timer1 мікроконтролера Atmel AVR, або AtMega328, який використовується в Arduino, або ATTiny85, для виведення двох тактових сигналів, які є дзеркальними зображеннями один одного. Частота, яку я намагаюсь генерувати, є змінною від 1 МГц до 2 МГц або більше, яка занадто висока, щоб зробити це за допомогою коду для перемикання вихідних штифтів, якщо я не хочу робити майже нічого іншого в контролері. Тому я хочу використовувати вихід таймера безпосередньо на пов'язаних штифтах. Я використовую ланцюжок інструментів GCC, щоб не обмежуватися бібліотеками або мовою arduino.

Timer1 в Atmega328 пов'язаний з ним двома контактами, і я можу отримати з них два однакових сигналу від 1 МГц до 2 МГц. Хоча аркуш даних, схоже, говорить про те, що я можу отримати перевернуту форму хвилі, це мене бентежить. Я також можу отримати два сигнали, які є різними циклами роботи на 1 МГц, використовуючи параметри ШІМ з Timer1, але обидва сигнали одночасно виходять високими, коротший - раніше низьким. Це не служить моєму проекту. Мені навіть не потрібні зміни ширини імпульсу ШІМ, мені просто потрібні два однакові сигнали типу «годинник» протилежної фази, ось і все.

Я не прошу, щоб хто-небудь писав код для мене, щоб це зробити, мені просто потрібен хтось, який підкаже мені, який режим / прапорці таймера повинні дати мені просту перевернуту форму хвилі на одному з двох контактів, пов’язаних із таймером. Якщо можливо, я хочу уникати використання зовнішньої інвертуючої схеми для одного з виходів, якщо це не єдиний варіант.

Якщо це можливо взагалі в ATTiny, це буде ще краще. ATTiny також має два штирі, пов'язані з одним таймером, але я не впевнений, що у нього є ті ж параметри, що і у ATMega.

У мене вже є підключені до друкованої плати кристали та конденсатори 20 МГц, а тактова частота 20 МГц надійно працює на ATMega328. На платі ATTiny85 у мене є 8 МГц кристал, який також надійно працює.

Будь ласка, допоможіть. Дякую.


ОНОВЛЕННЯ : У відповідях та коментарях поки що є неправдиві припущення, тому, можливо, я повинен уточнити: Зауважте, що в своєму початковому дописі я зазначив, що я використовую тактовий сигнал 20 МГц, а не 8 МГц , а також, що мені не потрібна ШІМ .

Єдиним режимом, який дає досить високу вихідну частоту, здається, є режим CTC оскільки ШІМ-режими не працюють для виходу 2 МГц. Чи є спосіб перетворити або вихід T таймера 1, або вихід B в режимі CTC?

Тепер я перейшов на стандартний Arduino Uno (ATMega328, 16 МГц) замість власної плати 20 МГц, щоб перевірити свій код, і це мій код для приємної стійкої тактової частоти 2 МГц в режимі CTC з штифтів 9 і 10, таймер 1 вихідний штифт:

#define tick 9
#define tock 10

void setup() {
  pinMode(tick, OUTPUT);  
  pinMode(tock, OUTPUT); 

  TCCR1A = _BV(COM1A0) | _BV(COM1B0) ;   // activate both output pins 
  TCCR1B = _BV(WGM12)| 1;                // set CTC mode, prescaler mode 1

  // various frustrating attempts to invert OC1B failed. What do I put here?

  OCR1A = 3;                             // set the counter max for 2 MHz

}

void loop() {
}

Сліди осцилоскопа для обох штифтів однакові та синхронізовані, як я можу отримати будь-який із двох перевернутих сигналів? Здається, режим інвертування в аркуші даних нічого не робить в режимі CTC. Чи неправильно я читаю аркуш, чи змушений буде використовувати режим нижчої частоти та ШІМ?

Щоб додати конкретне запитання "баунті" до мого оригінального запиту:
Отже, які зміни мені потрібно внести до свого коду вище, щоб він давав ідеально перевернуті сигнали на штирі 9 і 11 на максимально можливій частоті для тактового частоти 16 МГц , чи це 2 МГц чи ні?

Я буду дотримуватися стандартного Arduino Uno поки що, щоб не було режиму помилок, що вводиться моєю домотканою дошкою, і щоб кожен, хто має ардуїно, міг спробувати мій код вище і підтвердити, що він працює як я вже згадував, а не як я потрібно!


1
Переглядаючи сторінку 97-98 аркуша даних atmega8L , є таблиця режимів роботи. Сторінка 108 зазначає "біти COM21: 0 контролюють, чи повинен генеруватися вихідний ШІМ чи інвертований (інвертований чи не перевернутий ШІМ)". Повідомте нас про ваш успіх!
Vorac

Чому б не використати простий транзисторний інвертор для дзеркальних виходів?
Джоні Б Хороший

Відповіді:


10

З листа даних ATtiny85:

Режим роботи, тобто поведінка таймерів / лічильників та вихідних штифтів порівняння, визначається комбінацією режиму генерації сигналу (WGM0 [2: 0]) та режиму порівняння вихідного сигналу (COM0x [1: 0]) біт. Біти режиму порівняння виходу не впливають на послідовність підрахунку, в той час як біти режиму генерації сигналу формують. Біти COM0x [1: 0] регулюють, чи повинен генеруватися вихідний ШІМ чи ні (інвертований чи не перевернутий ШІМ ).

У таблиці 11-5 показано, як встановити режим.

Mode   WGM  WGM  WGM  Timer/Counter Mode    TOP      Update of    TOV Flag
c0     02   01   00   of Operation                   OCRx at      Set on
==========================================================================
0      0    0    0    Normal                0xFF     Immediate    MAX(1)
1      0    0    1    PWM, Phase Correct    0xFF     TOP          BOTTOM
2      0    1    0    CTC                   OCRA     Immediate    MAX
3      0    1    1    Fast PWM              0xFF     BOTTOM       MAX
4      1    0    0    Reserved                                  
5      1    0    1    PWM, Phase Correct    OCRA     TOP          BOTTOM
6      1    1    0    Reserved                                  
7      1    1    1    Fast PWM              OCRA     BOTTOM       TOP

Вам потрібен режим швидкої ШІМ (тобто режим 3 або режим 7). Якщо ви хочете змінити робочий цикл, і це звучить так, як ви це робите, вам потрібен режим 7 та зміна робочого циклу, встановивши OCRA.

У таблиці 11-3 показано, як встановити режим порівняння виходу для режиму швидкого ШІМ.

COM0A1/   COM0A0/
COM0B1    COM0B0     Description
===============================================================================
0         0          Normal port operation, OC0A/OC0B disconnected.
0         1          Reserved
1         0          Clear OC0A/OC0B on Compare Match, set OC0A/OC0B at BOTTOM
                     (non-inverting mode)
1         1          Set OC0A/OC0B on Compare Match, clear OC0A/OC0B at BOTTOM
                     (inverting mode)

Тобто ви можете встановити, що вихід OC0A буде низьким, коли значення Таймера == OCR0A, і високим, коли значення Таймера == 0x00, встановивши COM0A1: COM0A0 = 0b10. Або навпаки, встановивши COM0A1: COM0A0 = 0b11. І так само для OC0B, OCR0B, COM0B0, COM0B1.

Частота ШІМ визначається тактовою частотою вводу-виводу (8 МГц, це звучить як для вас) та налаштуваннями доказового таймера. А рівняння подається як f_clk_IO / (N * 256) для режиму швидкого ШІМ.

Таким чином, ви можете використовувати OC0A для "нормальної" полярності та OC0B для "перевернутої" полярності, встановивши OCR0A та OCR0B на те саме значення і встановивши COM0A1: COM0A0 = 0b10 та COM0B1: COM0B0 до 0b11.

ОНОВЛЕННЯ

Зважаючи на те, що ви хочете якомога швидше перемикати вихід, і ви використовуєте Mega328, що працює на частоті 16 МГц, режим роботи CTC дозволить отримати частоту комутації:

f_OCnA = f_clk_IO / (2 * N * [1 + OCRnA) = 16e6 / (2 * 1 * [1 + 1]) = 4 МГц

Режим швидкої ШІМ дозволить вам перемикати шпильку на:

f_OCnxPWM = f_clk_IO / (N * [1 + TOP]) = 16e6 / (1 * [1 + 1]) = 8 МГц

Тому я все ще думаю, що вам потрібен швидкий ШІМ-режим. Зокрема, режим 3 з OCR0A = OCR0B = 0x80 протягом 50% робочого циклу. І встановіть біти COM0A на 0x3, а COM0B на 0x2, щоб зробити дві форми хвиль на інверсіях OC0A та OC0B.

Оновлення №2 Більше Mega328 Спробуйте цей код Arduino:

#define tick 9
#define tock 10

void setup(){

  pinMode(tick, OUTPUT);  
  pinMode(tock, OUTPUT); 

  // Setup Waveform Generation Mode 15
  // OC1A Compare Output Mode = inverting mode
  // OC1B Compare Output Mode = non-inverting mode
  // Timer Prescaler = 1
  // TOP = OCR1A = 1

  //COM1A[1:0] = 0b11, COM1B[1:0] = 0b10, WGM1[1:0] = 0b11
  TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(COM1B1) | _BV(WGM11) | _BV(WGM10);

  //WGM1[3:2] = 0b11, CS1[2:0] = 0b001
  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);

  OCR1A = 0x0001;
  OCR1B = 0x0001;
}

void loop(){

}

Дозвольте трохи пожувати це і побачити, чи працює він. Дякую.
ExcitingProjects

Після перечитання вашої відповіді, щоб спробувати її сьогодні, я бачу пару неправдивих припущень: я вказав тактову частоту 20 МГц (і тепер я перейшов на 16 МГц), а не "(8 МГц, це здається для вас)" . Також я уточнив, що мені не потрібна зміна ширини імпульсу ШІМ, тому не знаю, де ви вважали, "Якщо ви хочете змінити робочий цикл, і це звучить так, як вам" .
ExcitingProjects

@ExcitingProjects Я відмикав ваше твердження "На платі ATTiny85 у мене є 8 МГц кристал, і це також надійно працює". і моя відповідь посилається на ATtiny85. Я спробую і оновити свою відповідь у відповідь на ваше оновлене запитання.
vicatcu

@vicateu Дякую Я оновив питання, бачачи, що режим інвертування, здається, не має ефекту в режимі CTC, якщо я не пропускаю якийсь крок.
ExcitingProjects

@ExcitingProjects з аркуша даних ATmega328: "Для режимів, що не належать до ШІМ, біти COM0x1: 0 контролюють, чи слід вихід встановлювати, очищати чи змінювати при порівнянні"
vicatcu

1

Сім'я ATtinyX5 має PLL всередині, використовуйте її великий хлопчик.

Я також використовую внутрішній PLL для живлення тактового процесора і маю 16 МГц без XTAL. Це дорогоцінно, оскільки у вас всього 5 штифтів. (Я не рахую шпильку скидання). Також один PLL'ed PWM (OCR1B) працює на штифтах XTAL з додатковим вихідним додатком. Вам просто потрібно налаштувати запобіжники для 16 МГц Xtalless ATtiny ... Або просто дозволити процесору працювати в 8 МГц, але запускати ШІМ з тактовою частотою 64 МГц без зміни запобіжників.

Ви можете мати до 64 МГц тактову ШІМ (але 1 біт). Або роздільна здатність 125 кГц @ 8 біт. Ви можете зменшити дозвіл ШІМ і збільшити швидкість за допомогою зменшення регістру OCR1C.

Для 1 МГц потрібно встановити OCR1C на 63. Для 2 МГц вам потрібно встановити OCR1C на 31. Для 4 МГц вам потрібно встановити OCR1C на 15. ...

Просто ввімкніть PLL за допомогою цього коду:

PLLCSR |= (1 << PLLE);           //Start PLL
while( !(PLLCSR & (1<<PLOCK)) ); //Wait for PLL lock
//PLLCSR |= (1<<LSM );           //Low Speed PLL that clocks 32Mhz, not 64Mhz
PLLCSR |= (1 << PCKE);           //Enable PLL

Тепер у вас є тактова частота 64 МГц на ШІМ "OCR1B0 / OCR1A0".

Крім того, ви можете налаштувати OCR1 [A / B] 0 & XOCR1 [A / B] 0 для дзеркального виводу.

if(0){ //Synch mode
     //OCR1A & XOCR1A enable for Synch operation but not allow odd PWM values!
     TCCR1 |= (1 << PWM1A) | (0 << COM1A1) | (1 << COM1A0); 
     //Also ATtinyX5 has "Dead Time Generator", use it ;)
     DTPS1 = 3;   //8x Prescaler for dead time generator (maximum)
     DT1A = 0xff; //Clk dead on both channels (maximum)
     }
   else
     TCCR1 |= (1 << PWM1A) | (1 << COM1A1) | (0 << COM1A0);  //ONLY OCR1A enabled

Потрібно знати, що генератор мертвого часу з’їсть вихід ШІМ, якщо встановити OCR1A = 1. Вам потрібні більш високі значення, ніж мертвий час.

З повагою,

Ердем

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.