Forum: Mikrocontroller und Digitale Elektronik Portausgänge shiften am Atmega 32


von Paavo V. (paavo_v)


Lesenswert?

Hallo zusammen, ich hab ein kleines Problem und hoffe ihr könnt mir 
helfen.
Ich will an meinem ATMEGA32 PORTA ( von PA0 bis PA7) jeweils eine "1" 
durchshiften...Prinzip Lauflicht...ABER irgendwie macht mein µC nciht 
das was er soll oder ich hab ein kleinen Denkfehler....
hier mein Quellcode:

#define F_CPU 8000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

ISR(TIMER1_COMPA_vect)
{
  PORTA = PORTA >>1 ;
  if(PORTA == 0x00)
    PORTA = 0x80;
}


int main(void)
{
DDRA |= 1<<PD0;
DDRA |= 1<<PD1;
DDRA |= 1<<PD2;
DDRA |= 1<<PD3;
DDRA |= 1<<PD4;
DDRA |= 1<<PD5;
DDRA |= 1<<PD6;
DDRA |= 1<<PD7;


while(1)
{

}

//Timer konfigurieren
TCCR1B |= (1<<WGM12) | (1<<CS11); //| (1<<CS10);//CTC Mode mit WGM12, 
Prescaler von 8 mit CS11
//TCNT1 = 64286;
TIMSK |= (1<<OCIE1A);
OCR1A |= 675;          //Vergleichswert zur BEstimmung von 1,25ms

TIMSK |= (1<<OCIE1A);
TCCR1A |= (1<<COM1A0);

sei();
}


ich will einfach nur, dass jeder Port etwa für 0,1ms einen high-Pegel 
hat.
Der Timer ist jetzt auf 800Hz eingestellt...der sollte natürlich auf 
100Hz stehen.
Noch besser wäre es wenn man diese Funktion ohne einen Timer Baustein 
bewerkstelligen kann, da ich die 3 Timer im Atmega eigentlich für was 
anderes benötige.

Danke schonmal für´s durchlesen...

LG Paavo

von icke (Gast)


Lesenswert?

Wie soll der uC denn den Timer konfigurieren?
Er bleibt in der while-Schleife hängen!

(Ich habe nicht geschaut, ob die Initialiesierung prinzipiell stimmt)

von Paavo V. (paavo_v)


Lesenswert?

-.- ohne kommentar....ja der Timer muss natürlich vor die 
while-schleife! sorry

von icke (Gast)


Lesenswert?

besser ist das ;)

von Martin K. (maart)


Lesenswert?

@Paavo: Wenn du das Atmel Studio benutzt hilft bei solchen "blöden" 
Fehlern schon mal der Debugmodus im Einzelschritt, da kannst du 
mitverfolgen was der Controller macht, oder eben nicht macht.

von Paavo V. (paavo_v)


Lesenswert?

geht trotzdem nicht=( also seh nix auf´m scope.

von Paavo V. (paavo_v)


Lesenswert?

@Martin ich arbeite mich gerade rein ins atmel studio, bin also noch 
echt ein noob!

von icke (Gast)


Lesenswert?

Ich bin im Moment nicht mit Atmegas vertraut, aber ich denke
OCR1A |= 675;
wird nicht klappen, da der Atmega nur 8 bit Register hat, also nur Werte 
bis 255 annehmen kann.
Du musst dir wohl einen anderen Vorteiler und eine andere Timerschwelle 
ausrechnen.

PS: Siehst du irgendetwas auf dem Scope?

PSS:

  if(PORTA == 0x00)
sieht auch nicht gut aus. Ich würde die Abfrage auf 0x01 machen.
Der Shifter ist glaube eh ein Kreisshifter (oder irre ich mich da?)

von Martin K. (maart)


Lesenswert?

Zumindest im Simulator läuft das Programm. Der Port wird ca. alle 0,68ms 
geshifted.

von Paavo V. (paavo_v)


Lesenswert?

Der Timer läuft im CTC Modus...TCCR1B |= (1<<WGM12)
Dersweiteren habe ich einen Rrescaler von 8 eingestellt hier nochmal die 
Zeile:

TCCR1B |= (1<<WGM12) | (1<<CS11);
//| (1<<CS10);
//CTC Mode mit WGM12, Prescaler von 8 mit CS11

Das mit dem Timer haut schon in da ich ihn am PD5 messen kann mit hilfe 
des scopes...!
Ich will ja eigentlich nur den gesamten PORTA aktivieren. Dass macht er 
auch mit DDRA = 0xFF // somit sind alle Pins als Ausgänge definiert.
...if(PORTA = 0x00)PORTA 0x80; ist nur dafür gedacht, dass er wieder von 
vorne anfängt zu zählen und nicht ins nirvana shiftet:D

von Peter II (Gast)


Lesenswert?

icke schrieb:
> if(PORTA == 0x00)
> sieht auch nicht gut aus. Ich würde die Abfrage auf 0x01 machen.
> Der Shifter ist glaube eh ein Kreisshifter (oder irre ich mich da?)

es is ja C und dort gibt es keinen Kreisshifter. Das ist schon so ok.

von Paavo V. (paavo_v)


Lesenswert?

@AMrtin
wie im simulator läuft das Programm? :D
Ich seh bloss nix am scope und würde wenigstens gerne dort was sehen:D

@Peter II
:D ok passt

von Martin K. (maart)


Lesenswert?

Paavo Varniery schrieb:

> Das mit dem Timer haut schon in da ich ihn am PD5 messen kann mit hilfe
> des scopes...!

Wenn du PA5 schreiben wolltest, ist alles ok und ich habe nichts gesagt.
Wie gesagt, im Simulator läuft es.

von Paavo V. (paavo_v)


Lesenswert?

@Matrtin nochmal...wie kannst du eine ISR im Atmelstudio simulieren? BTW 
ich nutze ATMelstudio 6

von Paavo V. (paavo_v)


Lesenswert?

Ja PA5 sollte es heißen! Will alles am PORTA machen:D

von Martin K. (maart)


Angehängte Dateien:

Lesenswert?

Ich auch.
Einfach einen Breakpoint in die ISR setzen.
Im Bild wo der gelbe Pfeil ist mit der linken Maustaste klicken.
Dieses Programm benutze ich:
1
#define F_CPU 8000000
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <util/delay.h>
5
6
ISR(TIMER1_COMPA_vect)
7
{
8
  PORTA = PORTA >>1 ;
9
  if(PORTA == 0x00)
10
  PORTA = 0x80;
11
}
12
13
14
int main(void)
15
{
16
  DDRA |= 1<<PD0;
17
  DDRA |= 1<<PD1;
18
  DDRA |= 1<<PD2;
19
  DDRA |= 1<<PD3;
20
  DDRA |= 1<<PD4;
21
  DDRA |= 1<<PD5;
22
  DDRA |= 1<<PD6;
23
  DDRA |= 1<<PD7;
24
25
26
  
27
  //Timer konfigurieren
28
  TCCR1B |= (1<<WGM12) | (1<<CS11); //| (1<<CS10);//CTC Mode mit WGM12,  Prescaler von 8 mit CS11
29
  //TCNT1 = 64286;
30
  TIMSK |= (1<<OCIE1A);
31
  OCR1A |= 675;          //Vergleichswert zur BEstimmung von 1,25ms
32
33
  TIMSK |= (1<<OCIE1A);
34
  TCCR1A |= (1<<COM1A0);
35
36
  sei();
37
  while(1)
38
  {
39
40
  }
41
42
}

von Spess53 (Gast)


Lesenswert?

Hi

>Ich bin im Moment nicht mit Atmegas vertraut, aber ich denke
>OCR1A |= 675;
>wird nicht klappen, da der Atmega nur 8 bit Register hat, also nur Werte
>bis 255 annehmen kann.

Als 8-Bit-Register heißt das OCR1AL und OCR1AH. OCR1A ist für den 
Compiler ein 16-Bit-Register.

>TCCR1A |= (1<<COM1A0);

Dann solltest du aber auch OC1A (PD5) auf Ausgang setzen.

MfG Spess

von Paavo V. (paavo_v)


Lesenswert?

Ich debugge und gehe dann mit "step into" jeden schritt durch aber ich 
komm nicht in die ISR?! auch wenn ich dort ein breakpoint setze!

von Martin K. (maart)


Lesenswert?

Benutzt du exakt mein Programm?
Gut, das Studio ist schon mal zickig.
Mach mal Folgendes:
- Den Breakpoint so setzen wie bei mir
- Alt+F5 (= Start debuging and break)
- jetzt sollte der Cursor in der ersten Zeile der main-Funktion stehen.
- F5 (=Run) drücken.
- nach einer kurzen Weile sollte der Cursor beim gesetzten Breakpoint in 
der ISR stehen bleiben.

von Paavo V. (paavo_v)


Lesenswert?

KOMMANDO zurück und vielen dank für die Zahlreichen kommentare ABER wenn 
man beim Flashen die falsche Datei nimmt kann es ja nicht gehen!:D:D:D
Eine sehendes auge für den blinden bitte:D

LG

von Martin K. (maart)


Lesenswert?

Hach ist das schön! Auch anderen passiert dieser Fehler ;-)
Funktioniert das Debuggen denn jetzt auch? Das sollte eigentlich 
unabhängig vom zu flashen file laufen.

von Paavo V. (paavo_v)


Lesenswert?

Ja alles super=) NUR wenn ich schiffte müsste doch auf jedem Port der 
Highpegel etwas woanders liegen oder?
Der Pegel sieht jetzt so aus....

____-_______-_____

aber ich will eigentlich einen Pegel haben , der wirklich 100 Hz an 
jedem Pin bleibt!

so dass ich insgesamt eine rotation von 800HZ habe.

von Paavo V. (paavo_v)


Angehängte Dateien:

Lesenswert?

Es ist auch komisch, dass mir die simulation das im Bild anzeigt und ich 
aber mit dem Scope ein efrequenz von 1250 Hz messe=(=(

von Martin K. (maart)


Lesenswert?

Das war früher(tm) mit dem alten Atmel Studio einfacher. Du musst hier 
manuell den Wert auf den gewünschten Wert setzen.

von Paavo V. (paavo_v)


Lesenswert?

Nur zum verständnis...
Wenn ich den Timer1 nehme und im CTC modus betreibe und mit einem 
Prescaler von 8 rangehe und meine Taktfreuenz vom CPU bei 8Mhz liegt und 
ich eine Frrequenz von 800 Hz haben will rechne ich doch wie folgt oder?

ORC1A = (zeit *(CPU_takt/Prescaler)-1

oder?

von Martin K. (maart)


Lesenswert?

Du schreibst hier:
1
OCR1A |= 675;          //Vergleichswert zur BEstimmung von 1,25ms
Wie kommst du darauf? Der µC läuft mit 8MHz, der Timer 1:8 also mit 
1MHz,
also kommt der Interrupt alle 0,675 Millisekunden. Der richtige Wert 
wäre 1250.
Oh noch was: OCR1A |= 675;
GAAAANZ gefährliches Eisen! Was soll hier die Oder-Verknüpfung?
OCR1A enthält genau nur dann den Wert 675, wenn es vorher Null war. Wird 
hier in diesem Fall zwar funktionieren, später kann dir soetwas aber mal 
das Genick brechen.

von Spess53 (Gast)


Lesenswert?

Hi

>also kommt der Interrupt alle 0,675 Millisekunden. Der richtige Wert
>wäre 1250.

Genaugenommen sind es 1249.

MfG Spess

von Martin K. (maart)


Lesenswert?

Ja, hast Recht.

von Paavo V. (paavo_v)


Lesenswert?

Ich habe auch 1249 errechnet! Aber damit bekomme ich leider auf dem 
Scope keine 800 Hz zusehen...Danke martin für den Tip mit der ODer 
-Verknüpfung! Das habe ich gar nicht gesehen...die sollte da nicht hin!

von Spess53 (Gast)


Lesenswert?

Hi

>Ich habe auch 1249 errechnet! Aber damit bekomme ich leider auf dem
>Scope keine 800 Hz zusehen...

Und wo gemessen? An einem Pin von PortA solltest du Impulse mit einer 
Frequenz von 100 Hz messen. Am OC1A-Pin (PD5) müssen 400 Hz 
symmetrisches Rechteck rauskommen. Dann passt das Ganze.

MfG Spess

von Paavo V. (paavo_v)


Lesenswert?

Hwy:D
Also ich messe jetzt an PD5 eine Frequenz von 800Hz mit einem 
Vergleichswert von OCR1A =624,5; fragt mich nicht wie aber es 
geht...=)=)
Von der Taktung sieht es jetzt genau so aus wie ich es haben will...Also 
800Hz an PD5 und an PA0-7 jeweils einen Impuls der dann 7 Takte von PD5 
abwartet eh er wieder kommt!
Super super super=)

Nächste frage die ich habe ist, in welchen Register kann bzw muss ich 
eine 32bit große Bitfolge abspeichern...ich hab eigentlich ein 64 Bit 
wort wie ich es aufteile hab ich in C schon realisiert..nur muss ich dem 
Atmega doch sagen wo er es ablegen soll oder?

Kann ich eine Bitfolge einfach an PD4 rauschicken? Oder einen 
beliebeigen Pin?

LG

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.