mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AT91SAM7S - Timer und / oder Interrupt in C


Autor: Peter Pippinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo NG,

ich habe jetzt herausgefunden, wie ich mein Projekt abschließen möchte. 
Dazu benötige ich 2 !getrennte! Funktionen, die immer zu einer 
bestimmten Zeit ausgeführt werden.

Der Zeitpunkt der Ausführung der beiden Funktionen sollte höchste 
Priorität haben.

Vereinfacht suche ich folgendes (zeitlich stark unter die Lupe 
genommen):

- Hauptprogramm läuft in einer Endlosschleife.
- LED1 soll alle "geraden" Sekunden (2,4,6,8...) blinken (C-Funktion 1).
- LED2 soll alle "ungeraden" Sekunden (1,3,5,7...) blinken (C-Funktion 
2).

Diese beiden Funktionen sollen das Hauptprogramm für deren Laufzeit 
unterbrechen und dann wieder fortsetzen.

Bitte gebt mit konkrete Beispiele, wie soetwas zu machen ist. Am besten 
mit einem Beispiel.

Vielen Dank!
Peter

Autor: Peter Pippinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...ich bins nochmal:

jetzt weiß ich noch genauer, was ich brauche:

"Nur" einen Timer, der eine LED jede Sekunde anschaltet, bzw. 
ausschaltet. Das Problem: ich weiß nicht, wie ich vogehen muss, um 
diesen Timer zu programmieren. Irgendwie muss ich ja auch sagen, welche 
Funktion beim Timer ausgelöst werde soll, oder?...

Kann mir bitte jemand aufzählen, was ich alles machen muss, damit ich 
diesen einen Interrupt bekomme?

Danke für jeden Tip! Ist echt ultra wichtig.
Peter

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guckst du Seite von Martin Thomas und schaust Interrupt Beispiele an. Da 
wirst du geholfen. Das wurde dir aber schon einige Male geraten, 
vielleicht hilft es ja diesmal.

Autor: Ronny (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Initialisierung:

Den gewünschten Timer mit der geforderten Zählgeschwindigkeit 
initialisieren. Wie das geht,steht im Datenblatt des Controllers und in 
diversen Atmel App-Notes.Da zu lesen will und werde ich dir nicht 
abnehmen.

Beispiel:

20MHz Systemtakt mit einem Prescaler von 10000 ergibt 2kHz.Wenn man 
jetzt die Compare-Einheit des Timers auf 2000 setzt,wird ein Interrupt 
nach 2000 Zählschritten ausgelöst (entspricht dann eben 1s).Im Interrupt 
schaltest du die entsprechende LED und setzt den Timer (falls dieser 
sich nicht beim auftreten eines Compare/Match-Interrupts selbst auf 0 
setzen kann).

Hauptschleife:

Nix mehr zu machen.Wenn du dort noch eine andere Anwendung laufen 
hast,musst du aber aufpassen wenn du den Timer oder die LEDs ausserhalb 
des ISR ansprichst.

Autor: Peter Pippinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Karl
>Guckst du Seite von Martin Thomas und schaust Interrupt Beispiele an. Da
>wirst du geholfen. Das wurde dir aber schon einige Male geraten,
>vielleicht hilft es ja diesmal.

ach, jetzt komm´ schon. Sei doch nicht gleich so patzig...

Ich habe mir das Zeug schon angesehen. Leider ist mir das alles zu 
"aufgeblasen". Möchte doch nur einen einzigen Timer haben. Mir ist das 
immer ein bischen zu viel. Lieber habe ich ein Beispiel, wo weniger 
drinnen ist, als ich brauche. Eine LED mit einem Timer blinken zu lassen 
sollte doch nicht so schwer sein.

@Ronny
hast Du es eventuell ein bischen genauer (Pseudocode?). Mir ist das 
prinzipiell schon klar, dass ich den Interrupt irgendwo initialisieren 
muss und wie der dann letztendlich arbeitet. Mir würde ja schon ein 
Beispiel genügen, welches per timer einfach eine Variable hochzählt.

Habe mir auch die Tastenentprellung im MP3-Player-Projekt angesehen. 
Allerdings ist mir das auch zuviel Info...

Wäre nett, wenn jemand eine kleines Timer-Interrupt-Demo hätte.

Vielen Dank,
Peter

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt schon, dass Martin mehr als eine LED blinken lässt. Allerdings 
lassen sich die nötigen Funktionen anhand von Kommentaren und 
Funktionsnamen relativ leicht identifizieren. Den Rest des Programms 
kann man dann ja wegkürzen. Zum Verständniss ist das Studium der 
Funktionen und des Datenblatts einfach unerlässlich.

Autor: Peter Pippinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>...Allerdings
>lassen sich die nötigen Funktionen anhand von Kommentaren und
>Funktionsnamen relativ leicht identifizieren. Den Rest des Programms
>kann man dann ja wegkürzen. Zum Verständniss ist das Studium der
>Funktionen und des Datenblatts einfach unerlässlich.

"Relativ leicht": relativ leicht ist eben auch relativ schwer.

Was ich ein wenig im diesem Forum vermisse sind Beispiele. Dabei möchte 
ich aber auch nicht falsch verstanden werden. Ein kleiner Tip ist 
immerhin besser als gar nichts. Ich bin halt einfach von anderen Foren 
anderes gewohnt. Mir ist auch klar, dass niemand für mich meine 
"Hausaufgaben" macht. Allerdings ist so eine Sache wie ein 
Timer-Interrupt für mich eine komplett abgeschlossene Einheit. Wenn ich 
wüsste, wie man auf dem ARM7 einen Timer-Interrupt programmiert, und 
jamand danach fragt, würde ich ihm ein kleines Beispiel geben. Dazu 
kommt, dass es für den ARM7 meiner Meinung nach nur sehr wenig im 
Internet zu finden gibt. Wenn ich mir da Beispielsweise mySQL, PHP, 
FreeBSD etc. ansehe, da sieht die Welt schon ganz anders aus.

Das ist halt nur so wie ich mir das vorstelle. Da haben andere mit 
Sicherheit andere Meinungen darüber. Ein Verweis auf das Datenblatt ohne 
praktische Beispiele in C ist für mich da eher weniger hilfreich...

Und dann kommt noch hinzu: Wenn das Projekt fertig ist, und als Open 
Source im Internet steht, kann es vielleicht anderen Leuten wieder 
weiterhelfen iregendetwas zu lernen...

MfG
Peter

Autor: gerhard (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
hallo peter,
deine behauptung, es gäbe keine beispiele für den at91sam7s finde ich 
etwas gewagt.
ich hatte dich schon bei deinen ersten postings auf www.at91.com 
verwiesen.
dort findest du für nahezu jeden peripherie block des at91sam7s ein 
beispiel.
im anhang mal das für den pit, der für deine anwendung geeignet sein 
sollte.

gruss
gerhard

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dass es für ARMe keine Beispiele im Netz gibt halte ich auch für eine 
sehr unüberlegte Äußerung. Mittleriweile wurden einige Quellen genannt 
(die man auch bequem per google finden kann).

Wenn ich meine Projekte hier hätte, hättest auch eines bekommen, das nur 
eine LED blinken lässt. Jetz hab ich mir gerade noch die schon genannten 
Beispiele angeschaut und kann fast nur noch den Kopf schütteln (hab 
schon länger nichts mehr mit ARM7 gemacht). Ausreichend dokumentiert, 
sprechende Namen (AT91F_AIC_ConfigureIt(), AT91F_AIC_EnableIt()), 
tipp-top defines, Kommentar zu jeder Funktion. Was willst du eigentlich 
noch? Ich wüsste garnicht, was man da noch erklären sollte.

Schau dir an, was in den Funktionen gemacht wird (mit dem Datenblatt). 
Ist ja nicht so, dass du das Rad von neuem erfinden musst, das wurde 
schon alles gemacht. Wenn du dir mal zwei Stunden Zeit nehmen würdest um 
dich da durchzubeißen, es nachzuvollziehen und dir Notizen zu machen, 
dauert das mit Sicherheit nicht länger als im Forum über schlechten 
Support zu klagen.

Autor: Ronny (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Keine Beispiele für ARM7....der war gut.

Mal im Ernst: Der Timer der meisten Controller ist mit weniger als 4 
Kontroll-Registern konfigurierbar.Und die stehen praktischerweise im 
Datenblatt bei sogut wie allen Herstellern auf direkt 
aufeinanderfolgenden Seiten erklärt.Die musst du lesen,egal wie viel 
Code du dir anschaust.

Kompliziert sind 2 Dinge:

1. Wie definiere ich eine Funktion als Interruptfunktion?

  Das ist Compiler abhängig.Da hilft meist ein Blick in die 
Beispiel-Codes
  die zum Compiler mitgeliefert werden. Meist ist da auch schon ein
  imer-Beispiel drin.Und eins für die UART.Und eins...

2. Wie setze ich in C einzelne Bits bzw lösche diese?

  Beides geht mit Bitweise Operationen. Gesetzt wird mit ODER:

  cVar |= MASKE;

  Gelöscht mit AND:

  cVar &= ~MASKE;

Autor: Peter Pippinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, jetzt habe ich mir mal aus dem Beispiel ein bisschen was 
zusammengebastelt, was allerdings nicht funktioniert. Die 
write_char_USART0('!'); sollte eigentlich jetzt regelmäßig ein "!" via 
RS232 senden. Wenn ich die Interrupt-Handler-Funktion im Main direkt 
aufrufe, kommt auch ein "!", was darauf schließen lässt, dass die 
Funktion funktioniert. Allerdings scheint der Timer-Interrupt nicht zu 
laufen. Es kommen keine "!" an...

Bitte dringend um Hilfe!

Vielen Dank!

--------------------------------------------------------------

#define RTTC_INTERRUPT_LEVEL  0
#define PIV_200_MS     6000

unsigned int AT91F_AIC_ConfigureIt (
  AT91PS_AIC pAic,
  unsigned int irq_id,
  unsigned int priority,
  unsigned int src_type,
  void (*newHandler) (void) )
{
  unsigned int oldHandler;
    unsigned int mask ;

    oldHandler = pAic->AIC_SVR[irq_id];

    mask = 0x1 << irq_id ;
    pAic->AIC_IDCR = mask ;
    pAic->AIC_SVR[irq_id] = (unsigned int) newHandler ;
    pAic->AIC_SMR[irq_id] = src_type | priority  ;
    pAic->AIC_ICCR = mask ;

    return oldHandler;
}

void Periodic_Interval_Timer_handler(void)
{
    unsigned int status;
    status = AT91C_BASE_PITC->PITC_PIVR;
    status =status;
    write_char_USART0('!');
}

void AT91F_AIC_EnableIt (
  AT91PS_AIC pAic,
  unsigned int irq_id )
{
    pAic->AIC_IECR = 0x1 << irq_id ;
}

main()
{
.
.
.

  AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_SYS, 
RTTC_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE, 
Periodic_Interval_Timer_handler);

  AT91C_BASE_PITC->PITC_PIMR = AT91C_PITC_PITEN | AT91C_PITC_PITIEN | 
PIV_200_MS;

  AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SYS);

.
.
.
}

Autor: Peter Pippinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo NG,

ich bekomme es einfach nicht hin. Kann mir nicht vielleicht jemand 
helfen?

Habe eben ein Example der IAR-Workbench versucht. Aber das läuft einfach 
nicht. Ich brauche doch "nur" einen Timer...

Danke für jede Hilfe.
Peter

Autor: Peter Pippinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt habe ich noch eine Frage. Im Manual steht folgendes über den PIT:

The PIT provides a programmable overflow counter and a reset-on-read 
feature. It is built around two counters: a 20-bit CPIV counter and a 
12-bit PICNT counter. Both counters work at Master Clock /16.

Ich möchte aber am Ende eine Funktion, die mit 1MHz läuft. Wenn jetzt 
mein ARM aber mit 55 MHz läuft, kann ich doch den Timer nie auf 1MHz 
bringen, oder? Weil 55/16 gibt keine ganze Zahl.

Autor: gerhard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,
so sollte die init. des pit funktionieren:
// System-Interrupt im AIC init.
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,
                      AT91C_ID_SYS,
                      SYSTEM_INTERRUPT_LEVEL,
                      AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE,
                      SystemIrqHandler);

// interrupt mode und Interval einstellen, Timer starten
AT91C_BASE_PITC->PITC_PIMR = AT91C_PITC_PITEN | AT91C_PITC_PITIEN | PIV_VALUE;

// System Interrupt freigeben
AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SYS);




für PIV_VALUE setzt du den entsprechenden wert ein mit dem dein pit 
timer interrupt ablaufen soll.

im SystemIrqHandler muß der interrupt des pit entsprechend behandelt 
werden.

noch fragen?

gruss
gerhard

gruss
gerhard

Autor: Peter Pippinger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@gerhard
leider funktioniert das nicht :-(


-> SYSTEM_INTERRUPT_LEVEL ist bei mir nicht definiert. Was kommt da 
rein?


-> würde der IRQ-Handeler so passen?

void SystemIrqHandler(void)
{
    write_char_USART0('!');
}

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
AFAIR muss man den Interrupt auch noch quittieren. Ich weiß allerdings 
nicht mehr, ob es dafür eine fertige Funktion gibt, oder ob man ein 
Register im AIC direkt beschreiben muss.

Autor: gerhard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,
der irq-handler muß so aussehen:
void SystemIrqHandler(void)
{
// Interrupt Acknowledge
dwStatus = AT91C_BASE_PITC->PITC_PIVR;
}
wenn noch interrupts von anderen peripherie blöcke, deren irq auf den 
system interrupt hängen, behandelt werden sollen, dann muß im 
SystemIrqHandler noch unterschieden werden woher der interrupt kam.
(siehe auch datenblatt kapitel 24.6.3 Interrupt Sources).


SYSTEM_INTERRUPT_LEVEL ist wie der name schon sagt der prioritäten level 
für den system interrupt und kann von 0 (niedrigste priorität) bis 7 
(höchste priorität) eingestellt sein.

p.s. bevor du dich mit interrupts beschäftigst solltest du das kapitel 
"24. Advanced Interrupt Controller (AIC)" mal gelesen und auch 
verstanden haben. andernfalls ist das scheitern vorprogrammiert.

gruss
gerhard

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.