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
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
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 | }
|
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.