Pin toggle bei Atmega 8

Gast #1655591
Lesenswert?

Ich hab mal iwo gelesen, dass einige AVRs bei Schreiben einer 1 nach 
PORTin das entsprechende Pin togglen, sofern es als Ausgang gesetzt ist. 
Im Datenblatt des ATmega8 steht, das PORTin read-only ist.

Stimmt das mit dem Toggeln? Für welche AVRs geht das? Ist das ein 
undokumentiertes Feature?
Gast #1655741
Lesenswert?

Z.B. aus dem Atmega48 Datenblatt:
---------------Zitat-----------------------------------
The Port Input Pins I/O location is read only, while the Data Register 
and the Data Direction Register are read/write. However, writing a logic 
one to a bit in the PINx Register, will result in a toggle in the 
corresponding
bit in the Data Register.
---------------Zitatende-------------------------------
#1819795
Lesenswert?

mega644p kann das, mega128 kann es noch nicht. Gibt es ein #define, 
welches ich im C-Programm abfragen kann?

Ich möchte abhängig vom eingestellten Prozessor autom. die beiden Fälle 
unterscheiden.
1
PORTB ^= ( 1 << PB0 ); 
2

3
bzw.
4

5
PINB |= ( 1 << PB0 );

Wenn vom Prozessor her möglich, ist Weg über PINB der bessere, weil er 
weniger Takte kostet und kein read-modify-write durchführt (was ein 
Problem erzeugt, wenn zwischen "read" und "write" ein Interrupthandler 
oder ein anderer Thread das gleiche mit einem anderen Pin am selben Port 
versucht).
Gast #5243376
Lesenswert?

Hallo,
warum funktioniert bei einem Mega2560 zwar:

PINB |= ( 1 << PB0 );
oder
PINB |= (1 << PINB4);

(ohne die weiteren Portpins zu beeinflussen)

jedoch folgendes nicht:
(toggeln dieses Pins funktioniert schon, jedoch werden alle anderen Pins 
des Ports auf Low gezogen)

PINL |= (1 << PINL4);

die weiteren Varianten funktionieren wieder

PINL = (1<<PINL4);
PINL = (1<<PINL7)|(1<<PINL4);
PINL = 0x90;
PINL = 0x10;

oder retten in variable:
test = PINL;
test|= 0x10;
#5243418
Lesenswert?

Chris schrieb:
> jedoch folgendes nicht:
> (toggeln dieses Pins funktioniert schon, jedoch werden alle anderen Pins
> des Ports auf Low gezogen)
>
> PINL |= (1 << PINL4);

Weil man da in die Fallgrube tappt, daß SBI nicht auf PORTL geht.

Michael R. schrieb:
> Also ich toggle einen Pin folgendermaßen:
>  PORTB ^= ( 1 << PB0 );

Mache ich auch grundsätzlich so.
Die paar gesparten Zyklen sind es nicht wert, daß man in Fallgruben 
tappt und der Code schlechter zu verstehen ist.
#5243497
Lesenswert?

@Daniel (Gast)


>> Schau dir halt die Doku zu sbi/cbi an.

>Steht in der Doku auch drin warum es bei Port B funktioniert und bei
>Port L nicht?

Sicher. Weil sbi/cbi nur einen kleinen Teil der IO-Adressen ansprechen 
kann, Port L aber zu weit oben im Adressbereich liegt.
Gast #5244152
Lesenswert?

Vielen Dank an alle, habe mir dass mit PortL fast schon so gedacht.

Habe mittlerweile auch die richtigen Worte im Datenblatt gefunden.

8.4.1
General Purpose I/O Registers
The ATmega640/1280/1281/2560/2561 contains three Genera
l Purpose I/O Registers. These registers can be
used for storing any information, and they are particularly
 useful for storing global variables and Status Flags. Gen-
eral Purpose I/O Registers within the address range 0x00 - 0x1F are 
directly bit-accessible using the SBI, CBI,
SBIS, and SBIC instructions. See
“Register Description” on page 34
.

hätte mir jedoch gerne einen Hinweis unter folgendem Punkt gewünscht:

13.2.2
Toggling the Pin
Writing a logic one to PINxn toggles the value of PORTxn, independent on 
the value of DDRxn.
Note that the SBI instruction can be used to toggle one single bit in a 
port.

Somit gehe ich richtig in der Annahme, dass ich bis einschließlich PortG 
bit adressieren kann und ab PortH nicht mehr.

Gruss
Chris

verwendetes Datenblatt:
http://www.atmel.com/Images/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren