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
...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
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.
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.
@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
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.
>...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
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
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.
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;
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); . . . }
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
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.
hallo, so sollte die init. des pit funktionieren:
1 | // System-Interrupt im AIC init.
|
2 | AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, |
3 | AT91C_ID_SYS, |
4 | SYSTEM_INTERRUPT_LEVEL, |
5 | AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE, |
6 | SystemIrqHandler); |
7 | |
8 | // interrupt mode und Interval einstellen, Timer starten
|
9 | AT91C_BASE_PITC->PITC_PIMR = AT91C_PITC_PITEN | AT91C_PITC_PITIEN | PIV_VALUE; |
10 | |
11 | // System Interrupt freigeben
|
12 | 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
@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('!'); }
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.
hallo, der irq-handler muß so aussehen:
1 | void SystemIrqHandler(void) |
2 | {
|
3 | // Interrupt Acknowledge
|
4 | dwStatus = AT91C_BASE_PITC->PITC_PIVR; |
5 | }
|
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
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.