Forum: Mikrocontroller und Digitale Elektronik AVR16EB14 ist irgendwie zu schnell


von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ich versuche gerade, einen Bausatz, den wir bislang mit ATtiny24 
ausgerüstet haben, auf AVR16EB14 umzubauen.

Dazu gehört ein periodischer Timer-Interrupt, Wunschfrequenz ist 600 Hz.

Wenn ich in der Overflow-ISR einen IO-Pin einen Impuls ausgeben lasse, 
dann messe ich allerdings 2,4 kHz.

Rechnung: der interne RC-Oszillator läuft mit voreingestellten 20 MHz, 
die als Haupttakt durch 24 geteilt werden. (So schnell muss das Teil eh 
nicht sein, und es spart Strom.) Das macht 833 kHz. Um auf 600 Hz 
Periodendauer für Timer E0 zu kommen, wird dessen Periodenregister auf 
1388 gesetzt, oder 0x56c.

Der Compiler rechnet das anhand einiger symbolischer Konstanten so aus, 
aber das Compilat passt eigentlich:
1
    // 20 MHz high frequency RC oscillator / 24 => 0.866 MHz main system clock
2
    CLKCTRL.MCLKCTRLB =  CLKCTRL_PEN_bm | CLKCTRL_PDIV_DIV24_gc;
3
 25e:   87 e1           ldi     r24, 0x17       ; 23
4
 260:   80 93 61 00     sts     0x0061, r24     ; 0x800061 <__RODATA_PM_OFFSET__+0x7f8061>
5
6
00000264 <.Loc.147>:
7
    CLKCTRL.MCLKTIMEBASE = 1; // actually 1.2 µs, must be larger than 1 µs
8
 264:   91 e0           ldi     r25, 0x01       ; 1
9
 266:   90 93 66 00     sts     0x0066, r25     ; 0x800066 <__RODATA_PM_OFFSET__+0x7f8066>
10
11
0000026a <.Loc.149>:
12
13
    /* TCE0: interrupt each 1/F_TIMER */
14
    TCE0.PER = F_CPU / F_TIMER;
15
 26a:   2c e6           ldi     r18, 0x6C       ; 108
16
 26c:   35 e0           ldi     r19, 0x05       ; 5
17
 26e:   20 93 26 0a     sts     0x0A26, r18     ; 0x800a26 <__RODATA_PM_OFFSET__+0x7f8a26>
18
 272:   30 93 27 0a     sts     0x0A27, r19     ; 0x800a27 <__RODATA_PM_OFFSET__+0x7f8a27>
19
20
00000276 <.Loc.151>:
21
    TCE0.CMP0 = F_CPU / F_TIMER / DIM_DUTYCYCLE; /* dimmed LED turnoff time */
22
 276:   25 e4           ldi     r18, 0x45       ; 69
23
 278:   30 e0           ldi     r19, 0x00       ; 0
24
 27a:   20 93 28 0a     sts     0x0A28, r18     ; 0x800a28 <__RODATA_PM_OFFSET__+0x7f8a28>
25
 27e:   30 93 29 0a     sts     0x0A29, r19     ; 0x800a29 <__RODATA_PM_OFFSET__+0x7f8a29>
26
27
00000282 <.Loc.153>:
28
    TCE0.INTCTRL = TCE_CMP0_bm | TCE_OVF_bm;  /* overflow and compare 0 interrupts */
29
 282:   81 e1           ldi     r24, 0x11       ; 17
30
 284:   80 93 0a 0a     sts     0x0A0A, r24     ; 0x800a0a <__RODATA_PM_OFFSET__+0x7f8a0a>
31
32
00000288 <.Loc.155>:
33
    TCE0.CTRLA = TCE_ENABLE_bm;
34
 288:   90 93 00 0a     sts     0x0A00, r25     ; 0x800a00 <__RODATA_PM_OFFSET__+0x7f8a00>

Dummerweise hat der 14-Pinner kein Pin für CLKOUT, einen AVR16EBxx mit 
größerer Pinanzahl habe ich gerade nicht da. Sonst hätte ich einfach 
schon mal den Haupttakt direkt messen können.

Hat jemand auf Anhieb eine Idee, warum das Teil viermal so schnell ist 
wie geplant?

von Rainer W. (rawi)


Lesenswert?

Jörg W. schrieb:
> Hat jemand auf Anhieb eine Idee, warum das Teil viermal so schnell ist
> wie geplant?

Hast du dich vielleicht mit PBDIV und PEN in MCLKCTRLB vertan?

von Georg M. (g_m)


Lesenswert?

12.3.9 Configuration Change Protection
CLKCTRL - Registers Under Configuration Change Protection

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Georg M. schrieb:
> 12.3.9 Configuration Change Protection
> CLKCTRL - Registers Under Configuration Change Protection

Bingo, danke!

Damit kommt er dann mit dem default clock 20 MHz / 6 hoch, 4mal so viel 
wie gewünscht.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Inzwischen ist die Portierung komplett.

Was noch als Häkchen auffiel: bei der Xmega-artigen Architektur des 
AVR16EB14 muss man viele Interruptflags mit der Hand löschen – nur, 
falls jemand später den Thread nochmal findet.

: Bearbeitet durch Moderator
von Falk B. (falk)


Lesenswert?

Jörg W. schrieb:
> AVR16EB14 muss man viele Interruptflags mit der Hand löschen

Da hast du aber kleine und schnelle Hände! ;-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Falk B. schrieb:
> Jörg W. schrieb:
>> AVR16EB14 muss man viele Interruptflags mit der Hand löschen
>
> Da hast du aber kleine und schnelle Hände! ;-)

Ich mach das stilecht mit 'ner Morsetaste. :-)

von Christian E. (cerker)


Lesenswert?

Programmierst du wenigstens auch damit? Du brauchst doch nur ein 
Phased-Array, welches mit der Modulation der Taste ein exakt passendes 
Interferenzpattern erzeugt was dann die entsprechenden Bits im Flash 
setzt oder löscht.

https://xkcd.com/378/

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.