RE: Přerušení časovačem na AtMega

Lukac Michal Michal.Lukac na fstroj.uniza.sk
Středa Říjen 11 10:11:51 CEST 2023


Ak je to robene priamo v Arduino prostredi tak tam je este myslim pouzite defaultne prerusenie pre TIM0OVF
pre generovanie casu v milisekundach, to urcitu dobu trva a ak to skace v intervale trvania tohoto prerusenia tak to moze byt dovod preco to skace.
Tak skusit zakazat TIMER0_OVF.

m.

From: Hw-list <hw-list-bounces na list.hw.cz> On Behalf Of Martin Záruba
Sent: Wednesday, October 11, 2023 7:41 AM
To: hw-list na list.hw.cz
Subject: Re: Přerušení časovačem na AtMega


To je na mě moc složité, já byl zvyklý programovat především PC i když kdysi i sálový počítač v assembleru. Ale tam byl všechno jinak.

Je to Arduino Mega2560. Potřebuji udělat přerušení každých 100uS (Nemusí to být přesně a hodilo by se mi, kdybych změnou nějaké konstanty mohl zvolit optimální hodnotu někde mezi 60 - 200 uS.

V přerušení bude tato sekvence:



byte hodA[50],hodC[50],hodL[50];
// Obsluha přerušení od časovače Timer/Counter1
ISR(TIMER1_OVF_vect) {
 for (byte i=0;i<=50;i++) {
   PORTA=hodA[i];
   PORTC=hodC[i];
   PORTL=hodL[i];
 }
 PORTA=0;
 PORTC=0;
 PORTL=0;
}

To přerušení jsem změřil, že trvá 28uS, takže by na ostatní mělo zbýt dost času. I když pole naplním hodnotami, aby vznikl široký pulz, cuká to stále, takže osciloskop za to nemůže.

A potřebuji aby alespoň jeden další port byl schopen klasické PWM, frekvence celkem není důležitá, vyhovuje cokoli mezi 200 Hz až 1kHz.

Ale hodiny mi běží na 16Mhz, proto těch 10kHz, jinak není šance to stihnout.

Já vlastně potřebuji udělat různě široké pulzy na 24 portech s opakovací frekvencí cca 5 - 20 kHz. Stačí mi ale 50 kroků. Nic lepšího mě nenapadlo, než přerušení časovačem a v obsluze to, co jsem popsal. Naplnění, těch polí už je snadné. Funkce je asi jasná, prostě příslušné bity prvků pole naplním 1 podle toho, jak dlouhý ten pulz má být. Jkmile má skončit, bity až do konce pole [50] jsou nulové.

Ty pulzy mi to generuje a šířka je stabilní, takže je vidět, že přerušovací rutina proběhne spojitě, ale pak ta prodleva je nestejná, ač by měla být ovlivněna jen nastavením časovače.

Jak mám změnit defaultní nastavení časovače1? To moje nastavení je zjevně blbě, ale nevím proč?

Martin Záruba
Dne 11.10.2023 v 0:29 Pavel Hudeček napsal(a):
https://ww1.microchip.com/downloads/en/devicedoc/atmel-2549-8-bit-avr-microcontroller-atmega640-1280-1281-2560-2561_datasheet.pdf
10.3.1 Default Clock Source
The device is shipped with internal RC oscillator at 8.0MHz and with the fuse CKDIV8 programmed, resulting in 1.0MHz system clock. The startup time is set to maximum and time-out period enabled. (CKSEL = "0010", SUT = "10", CKDIV8 = "0"). The default setting ensures that all users can make their desired clock source setting using any available programming interface.

Takže "nic nenastavoval" znamená 1 MHz

Pustil jsem wizard c codevisionu, naklikal 1 MHz CLK, mode CTC, přerušení od OCR1A a nechal vygenerovat:
(Používá jinou syntaxi přerušení, ale zbytek by měl fungovat)
--------------
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 1000,000 kHz
// Mode: CTC top=OCR0A
// OC0A output: Disconnected
// OC0B output: Disconnected
// Timer Period: 0,1 ms
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (1<<CS00);
TCNT0=0x00;
OCR0A=0x63;
OCR0B=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=(0<<OCIE0B) | (1<<OCIE0A) | (0<<TOIE0);


// Timer 0 output compare A interrupt service routine
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
// Place your code here

}
----------------
Takhle bych postupoval já, kdybych chtěl přerušení 10 kHz.

Kdybych chtěl fast PWM na 10 kHz a k tomu přerušení, tak:
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 1000,000 kHz
// Mode: Fast PWM top=OCR0A
// OC0A output: Disconnected
// OC0B output: Non-Inverted PWM
// Timer Period: 0,1 ms
// Output Pulse(s):
// OC0B Period: 0,1 ms Width: 0,049495 ms
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (1<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (1<<WGM00);
TCCR0B=(1<<WGM02) | (0<<CS02) | (0<<CS01) | (1<<CS00);
TCNT0=0x00;
OCR0A=0x63;
OCR0B=0x31;

Ale pak je otázka, co teda dělá to Vaše:
Pokud by to byla opravdu default nastavená 2560, tak by to po tom dělení 64 a ještě 24 mělo dávat 651,... Hz. Není to Arduino, tedy 2560 je již nastavená dle Arduino zvyklostí?

Ještě je otázka, jak bylo zobrazeno to
"cca 100uS ale chaoticky kolísá"
Protože krátké pulzíky dělají synchronizacím některých osciloskopů potíže. Zkusil bych do toho přerušení dát
PORTA=~PORTA;
Pak bude poloviční frekvence a střída 50 %, to snad žádný osciloskop nezkazí.

PH
Dne 10.10.2023 v 21:33 Martin Záruba napsal(a):

ATMega2560.

Jak zjistím CLK? Nic jiného jsem nenastavoval.

Martin Záruba
Dne 10.10.2023 v 20:26 Pavel Hudeček napsal(a):
Přerušení se samo zakáže vstupem do jeho obsluhy a samo povolí jejím ukončením, takže cli a sei vyhodit.

Dále by to chtělo vědět, která ATmega, případně i zda/jak má nastavené s CLK související fuse bity.

PH
Dne 10.10.2023 v 19:52 Martin Záruba napsal(a):

Nastavil jsem
  TCCR1A = 0; // Vynulování registru TCCR1A
  TCCR1B = 0; // Vynulování registru TCCR1B

  // Nastavení režimu Fast PWM (TOP = ICR1)
  TCCR1A |= (1 << WGM11);
  TCCR1B |= (1 << WGM13) | (1 << WGM12);

  // Nastavení hodinového děliče na 64 (frekvence časovače = frekvence CPU / 64)
  TCCR1B |= (1 << CS11) | (1 << CS10);

  // Nastavení intervalu pro generování přerušení (100 us) - pro frekvenci CPU 16 MHz
  // ICR1 = (F_CPU / (časový interval * hodinový dělič)) - 1
  ICR1 = 24; // 100 us při frekvenci CPU 16 MHz a hodinovém děliči 64

  // Povolení přerušení od časovače Timer/Counter1
  TIMSK1 |= (1 << TOIE1);


a rutina přerušení je zatím zcela triviální


ISR(TIMER1_OVF_vect) {
 cli(); // Vypnutí globálních přerušení
 PORTA=0;
 PORTA=0xFF;
 sei(); // Zapnutí globálních přerušení
}

Na všech bitech portu A jsou krásné obdélnikové pulzy. Ale perioda vyvolání pulzů je sice cca 100uS ale chaoticky kolísá. Co dělám blbě?




_______________________________________________

HW-list mailing list  -  sponsored by www.HW.cz<http://www.HW.cz>

Hw-list na list.hw.cz<mailto:Hw-list na list.hw.cz>

http://list.hw.cz/mailman/listinfo/hw-list
------------- další část ---------------
HTML příloha byla odstraněna...
URL: <http://list.hw.cz/pipermail/hw-list/attachments/20231011/04f0d5b8/attachment.htm>


Další informace o konferenci Hw-list