Forum: Mikrocontroller und Digitale Elektronik ATtiny861A: Timer0 und PA4 als Ausgang


von Bernd (Gast)


Lesenswert?

Hallo,

ich habe eine Schaltung mit ATtiny861A aufgebaut, in der Port PA4 als 
Ausgang (DATA) verwendet wird, über den alle 10ms ein Byte seriell 
(bit-banging) ausgegeben werden soll.

Wenn ich meine Ausgabefunktion in einer einfachen Programmschleife 
aufrufe, funktioniert alles und ich kann das ausgegebene Bitmuster am 
Oszi sehen. Wenn ich stattdessen aber die Ausgabefunktion timergesteuert 
über einen Interrupt von Timer0 anstoße, dann sehe ich an PA4 nur einen 
permanenten High-Pegel. Da das CLK-Signal an einem anderen Portpin 
vorhanden ist, bin ich sicher, dass der Interrupt auch ausgelöst und die 
Ausgabefunktion aufgerufen wird.

Nun hat ja der Port PA4 als Alternativfunktion ICP0 ("Input Capture 
Pin"). Ich war bisher davon ausgegangen, dass diese nur dann aktiviert 
wird, wenn "Input Capture Enable" (ICEN0) gesetzt ist. Es scheint mir 
aber eher so zu sein, dass bei Benutzung von Timer0 der Port PA4 immer 
automatisch als Eingang umkonfiguriert wird.

Daher meine Frage: Ist es bei Verwendung von Timer0 möglich, PA4 
trotzdem als Ausgang zu benutzen?

Gruß,
Bernd

von Kai S. (kai1986)


Lesenswert?

Hallo,

allgemein muss jede Alternativfunktion aktiviert werden. Zum PA4 steht 
im Datenblatt, das er sogar als Ausgang konfiguriert sein kann und 
trotzdem vom Timer als Input Capture verwendet werden kann. Es ist bei 
den AVRs zudem auch Standard, das über das PIN Register der tatsächliche 
Zustand der Ausgänge zurückgelesen werden kann.
Ich würde eher auf ein Fehler im Quellcode tippen, den hast du aber 
"noch" nicht angehängt.

Gruß Kai

von Bernd (Gast)


Lesenswert?

Kai S. schrieb:
> Zum PA4 steht
> im Datenblatt, das er sogar als Ausgang konfiguriert sein kann und
> trotzdem vom Timer als Input Capture verwendet werden kann.

???
Wo genau steht das? So eine klare Aussage dazu konnte ich bisher im 
Datenblatt nicht finden.

Der Code sieht in etwa so aus.
Sobald USE_INTERRUPT definiert ist, funktioniert es nicht mehr. CLK 
taktet dann immer noch, aber DATA bleibt stumm.
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
#ifdef USE_INTERRUPT
5
#include <avr/interrupt.h>
6
#endif
7
8
// PB1 = CLK, PA4 = DATA
9
void write_data(uint8_t data)
10
{
11
    int8_t i;
12
13
    for (i = 0; i < 8; i++) {
14
        PORTB &= ~_BV(PB1); // set CLK low
15
16
        if (data & 1)       // set DATA bit
17
            PORTA |= _BV(PA4);
18
        else
19
            PORTA &= ~_BV(PA4);
20
21
        data >>= 1;
22
23
        PORTB |= _BV(PB1);  // set CLK high
24
    }
25
26
    PORTB &= ~_BV(PB1);     // set CLK low
27
}
28
29
void init(void)
30
{
31
    // set port pin directions
32
    DDRA = 0b00011111;
33
    DDRB = 0b01001111;
34
35
    #ifdef USE_INTERRUPT
36
    // set up timer 0
37
    TCCR0A = _BV(CTC0);             // clear timer on compare match
38
    TCCR0B = _BV(CS02) | _BV(CS00); // prescaler = 1/1024
39
    OCR0A  = 10;                    // compare value (~10ms)
40
    TIMSK  = _BV(OCIE0A);           // enable timer 0 compare match A interrupt
41
    sei();                          // enable interrupts globally
42
    #endif
43
}
44
45
#ifdef USE_INTERRUPT
46
ISR(TIMER0_COMPA_vect)
47
{
48
    write_data(42);
49
}
50
#endif
51
52
int main(void)
53
{
54
    init();
55
56
    while (1)
57
    {
58
        #ifndef USE_INTERRUPT
59
        write_data(42);
60
        _delay_ms(10);
61
        #endif
62
    }
63
64
    return 0;
65
}

von Kai S. (kai1986)


Lesenswert?

Hallo,

hab erst jetzt wieder Zeit gefunden. Nachdem ich keinen Fehler in deinem 
Code gefunden habe, hab ich ihn auf einem ATTiny461A (861A hatte ich 
keinen fürs Steckbrett) getestet und bei mir funktioniert er 
einwandfrei. Sowohl mit als auch ohne USE_INTERRUPT definiert. Einzige 
Änderung, die ich vornehmen musste, war in der Zeile
1
   TCCR0A = _BV(CTC0);             // clear timer on compare match

das CTC0 auf WGM00 ändern, da mein Atmel Studio 5.0 das in der 
Definitionsdatei falsch drin stehen hat (WGM00 war meine ich die alte 
Bezeichnung).

Falls du in der Hardwarebeschaltung was an dem µC hängen hast, würde ich 
da nochmal schauen, ob dein Problem mit dem Highpegel an PA4 vielleicht 
daher kommt.

Gruß Kai

von Bernd (Gast)


Lesenswert?

Hallo Kai,

Vielen Dank für den Test und die Rückmeldung.

Ich habe hier mittlerweile auch weiterprobiert und beginne so langsam an 
meinem Verstand zu zweifeln. Ich habe versuchsweise einen anderen noch 
freien Port (PB5) anstatt PA4 benutzt - keine Änderung im Verhalten!
Natürlich würde man dann als nächstes auf ein mögliches Problem in der 
externen Beschaltung tippen - aber warum funktioniert es dann (sowohl 
mit PA4 als auch mit PB5), solange ich keinen Interrupt verwende???

Ich werde den ATtiny wohl auch mal aufs Steckbrett befördern, ansonsten 
habe ich wirklich keine Idee mehr.

Gruß,
Bernd

von Bernd (Gast)


Lesenswert?

Aaaahhh!!!

Wie so oft: Ganz blöder Fehler!

Zum einen habe ich meinen Beispielcode etwas zu sehr vereinfacht. Im 
echten Code wird natürlich keine Konstante (42), sondern der Inhalt 
einer Variablen ausgegeben. Ich hatte nur schlicht und ergreifend 
vergessen, diese als volatile zu deklarieren, daher wurde immer nur ihr 
Initialwert (0xff) ausgegeben.

Mea culpa und nochmals Danke für Deine Mühe, Kai.

Gruß,
Bernd

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.