Guten Morgen, bin grad dabei die Daten die ich über eine I2C Schnittstelle einles im uC (LPC2129) zu verarbeiten und in Abhängigkeit der Größe sollen 1 bis 5 Leds brennen. Durch einen Taster soll dies geschehn. Weiß jemand wie man zu den IO ports, den notwendigen Taster und die 5 Leds initialisiert? Was müsste denn dafür alles gemacht werden? Wieviel IO Ports benötigt man denn um dies realisieren zu können? Bin noch nicht all zu lang in der Materie drinnen. Würd mich freun wenn mir jemand weiterhelfen könnte. Gruß
Steff wrote: > Weiß jemand wie man zu den IO ports, den notwendigen Taster und die 5 > Leds initialisiert? Was müsste denn dafür alles gemacht werden? Du hast bestimmt einen Example-Ordner in Deiner Compilerinstallation, lese darin. > Wieviel IO Ports benötigt man denn um dies realisieren zu können? Einfach mal zählen. > Bin noch nicht all zu lang in der Materie drinnen. Das heißt? Wieviel Projekte hast Du denn schon mit diesem 32Bit-Monsterboliden programmiert? Hast Du überhaupt schon mal was mit MCs gemacht? Hast Du überhaupt schon mal in C programmiert? > Würd mich freun wenn mir jemand weiterhelfen könnte. Bei 32-Bittern ist ein gewisses Grundverständnis (Datenblatt, Usermanual lesen können usw.) unbedingte Vorraussetzung. Solche Boliden sind ja keine Anfänger-Projekte. Peter
Da geb ich dir voll und ganz Recht. Ja hab ich schon, aber nicht alleine. Das Beispielprogramm hab ich auch schon angesehn. Bräuchte ja dann insgesmt 6 IOs. Weiß halt nicht welche ich überhaupt nehmen könnte. So wie ich das seh sind da garkeine 6. Wäre dir echt dankbar wenn du mir einbisschen auf die Sprünge helfen könntest.
Taster-Port als Eingang, die LED-Ports als Ausgang. Modus auf GPIO setzen, "neither pull-up nor pull-down" setzen und dann brauchste nur noch ein und ausschalten. Guck dir diesbezueglich im Datenblatt des Prozessors das Kapitel 8 oder 9 (glaube, eher 9, weiss es nich genau ausm Kopf) an, da werden die Register PINSEL und PINMODE erklaert. In Kapitel 10 dann die Register FIOxSET, FIOxCLR und FIOxDIR angucken, verstehen wie das funktioniert und dann nur noch die Applikation schreiben. Fertig
Steff wrote: > Bräuchte ja dann insgesmt 6 IOs. Weiß halt nicht welche ich überhaupt > nehmen könnte. So wie ich das seh sind da garkeine 6. ??? Also laut NXP hat der "46 fast GPIO lines". Peter
> und dann nur noch die Applikation schreiben. Fertig Wäre schön wenn das so einfach wäre*g* > Taster-Port als Eingang, die LED-Ports als Ausgang Hab die relevanten Seiten schon durchgelesen, werd daraus aber leider nicht schlau. Könntest du mir evtl. mal eine Initialisierung von einem Port und die des Tasters zeigen, wenns es nicht all zu aufwändig wird?
Das hier ist ein Teil von dem Beispielprogramm: Könnte ich das dann einfach dann so schreiben wie hier, nur dann einfach für 5 leds und einem Taster? // button.h #include <iolpc2129.h> #define BUT1_PRESSED IO0PIN_bit.P0_15 #define BUT2_PRESSED IO0PIN_bit.P0_16 Wieso kann ich das einfach so schreiben? IO0PIN_bit.P0_15 Wieso nehmen die grad port 15 und 16? // init buttons port void InitButtons(void); //buttons.c #include <iolpc2129.h> #include "buttons.h" // init buttons port void InitButtons(void) { IO0DIR_bit.P0_15 = 0; //set port0.15 as input IO0DIR_bit.P0_16 = 0; //set port0.16 as input } //led.c #include <iolpc2129.h> #include "led.h" //it's a simple delay void Delay (unsigned long a) { while (--a!=0); } // init led port void LedsInit(void) { IO0DIR_bit.P0_12 = 1; //set port0.12 to output IO0DIR_bit.P0_13 = 1; //set port0.13 to output } // single blink led 1 void Led1Blink(void) { IO0CLR_bit.P0_12 = 1; //on led Delay(500000); //delay IO0SET_bit.P0_12 = 1; //off led Delay(500000); //delay } // turn on led 1 void Led1On(void) { IO0CLR_bit.P0_12 = 1; //on led } // turn off led 1 void Led1Off(void) { IO0SET_bit.P0_12 = 1; //off led } // single blink led 2 void Led2Blink(void) { IO0CLR_bit.P0_13 = 1; //on led Delay(500000); //delay IO0SET_bit.P0_13 = 1; //off led Delay(500000); //delay } // turn on led 2 void Led2On(void) { IO0CLR_bit.P0_13 = 1; //on led } // turn off led 2 void Led2Off(void) { IO0SET_bit.P0_13 = 1; //off led }
Haengt ein wenig davon ab, was fuer ein Taster dranhaengt und wie toll du das haben willst. So richtig p*rno wird das natuerlich mit einem entprellten Taster, aber das lassen wir der einfachheit halber mal weg. Also, gehen wir davon aus, der Taster sitzt auf Pin P0.14:
1 | void SwitchInit (void) |
2 | {
|
3 | /* Set Pin to GPIO mode */
|
4 | PINSEL0 &=~(1 << 28); |
5 | PINSEL0 &=~(1 << 29); |
6 | |
7 | /* NO Pullup, NO Pulldown */
|
8 | PINMODE0 &=~(1 << 28); |
9 | PINMODE0 |= (1 << 29); |
10 | |
11 | /* Set Pin as Input */
|
12 | FIO0DIR &=~(1 << 14); |
13 | }
|
14 | |
15 | uint8_t SwitchRead (void) |
16 | {
|
17 | if (FIO0PIN & 0x00002000) |
18 | {
|
19 | return (1); |
20 | }
|
21 | else
|
22 | {
|
23 | return (0); |
24 | }
|
25 | }
|
Sollte so hinhauen, hoffe ich. Habs nich gestestet, sondern ausm Kopf gebastelt
sowas will ich auch mal von alleine hinbekommen, aber da wird noch sehr viel Zeit ins Land gehn.Danke das du dir so mühe machst. Wieso gehn denn die bei dem Beispielprogramm direkt auf die Ports?Was ist denn da anderst? Weil die schreiben ja nur IO0DIR_bit.P0_15 = 0; //set port0.15 as input Du schreibst ja FIO0DIR &=~(1 << 14); Wie schreibt man denn die Anweisung PINSEL0 &=~(1 << 28) ausführlich, das das ein Anfänger auch verstehn kann?
Steff wrote: > sowas will ich auch mal von alleine hinbekommen, aber da wird noch sehr > viel Zeit ins Land gehn.Danke das du dir so mühe machst. Das kommt schneller als du willst :) > Wieso gehn denn die bei dem Beispielprogramm direkt auf die Ports?Was > ist denn da anderst? > Weil die schreiben ja nur IO0DIR_bit.P0_15 = 0; //set port0.15 as > input > Du schreibst ja FIO0DIR &=~(1 << 14); Dein Beispiel hat eine LPC23xx.h Datei (so, oder so aehnlich). Darin sind die einzelnen Ports mit ihren Adressen angegeben. Zusaetzlich hat der Ersteller deines Beispiels sich die Muehe gemacht, saemltiche zusammengehoerigen Bits (wie z.B. die jeweiligen 2 Bits der Pinregister) zu Elementen in Strukturen zusammenzufassen. Daher kann dein Beispiel ueber Strukturen mehrere Bits direkt ansprechen. Es macht aber das gleiche wie meins auch. Ich persoenlich mag das so lieber, weil ich direkt sehe, was mit welchem Bit passiert. Ist aber Geschmacksache. Die Strukturen sind einfacher anzuwenden, vor allem, wenn sie jemand anders schon fertig erstellt hat. > Wie schreibt man denn die Anweisung PINSEL0 &=~(1 << 28) ausführlich, > das das ein Anfänger auch verstehn kann? PINSEL0 = (PINSEL0 & ~(1 << 28)); Soll heissen: PINSEL0 soll gleich PINSEL0 sein, nur dass das 28te Bit (per Shift) via ~1 (also 0) geUNDed wird. Irgendwas UND 0 ist immer 0, dadurch loescht man also ein einzelnes Bit. Den ODER-Operator vor das Gleichheitszeichen zu stellen erleichtert den Ueberblick. Wenn du dir mein Beispiel anschaust, kannst du anhand der Operatoren am Gleichheitszeichen immer sofort sehen, ob ein Bit gesetzt oder geloescht werden soll. Da ich die Code-Zeilen (sofern moeglich) auf die gleichzeichen "zentriere" (also so schreibe, dass sie immer untereinander stehen), sehe ich direkt, was passiert und muss den Operator nicht weiter hinten in der Zeile suchen.
Vielen vielen Dank für die super Erklärung. Könnte man das ung. so auch schreiben? das ist eigentlich das Beispielprogramm, aber mit mehreren Ausgängen und ein Eingang Das Programm von dir ist für mich noch einbisschen zu kompliziert. trotzdem sehr hilfreich. // init buttons port 0.17 void InitButtons(void) { IODIR0 &= ~(0x0001 << 17); //set port0.17 as input } void LedsInit(void) { IODIR0 |= (0x0001 << 18); //set port0.18 to output IODIR0 |= (0x0001 << 19); //set port0.19 to output IODIR0 |= (0x0001 << 20); //set port0.20 to output IODIR0 |= (0x0001 << 21); //set port0.21 to output IODIR0 |= (0x0001 << 22); //set port0.22 to output } void Led1On(void) { IOCLR0 |= (0x0001 << 18); //on led port0.18 } // turn off led 1 void Led1Off(void) { IOSET0 |= (0x0001 << 18); //off led port0.18 } Ist die Vergabe der Ports frei wählbar, hauptsache die sind im manual verfügbar?
>Ist die Vergabe der Ports frei wählbar, hauptsache die sind im manual >verfügbar? Was meinst du mit Vergabe? >IODIR0 |= (0x0001 << 18); //set port0.18 to output 32 bit sehen so aus 0x00000001. Nur der Vollständigkeit halber. Deshalb bleib beim Schieben mal lieber bei einer schnöden 1.
Sieht doch gut aus... Die HexAngabe laesst man normalerweise weg und schreibt nur ne 1 in die Klammern, aber das ist nur n schoenheitsding.. Programm sieht jedenfalls OK aus. Die Ports kannst du frei waehlen wie du willst, du musst teilweise nur auf deren Modus achten. Wenn ich mich recht erinnere, werden alle GPIOs auch im GPIO modus gestartet beim power-up. Willst du was anderes damit machen (z.B. das MCI Interface benutzen oder die UARTS), dann musst du natuerlich via PINSELx den Modus des Pins aendern. Was du jetzt noch machen koenntest (das wirkt professioneller) sind bitmasken fuer die einzelnen Ports. Statt:
1 | IODIR0 |= (0x0001 << 18); //set port0.18 to output |
2 | IODIR0 |= (0x0001 << 19); //set port0.19 to output |
3 | IODIR0 |= (0x0001 << 20); //set port0.20 to output |
4 | IODIR0 |= (0x0001 << 21); //set port0.21 to output |
5 | IODIR0 |= (0x0001 << 22); //set port0.22 to output |
koenntest du schreiben
1 | #define LED1MASK (1UL << 18)
|
2 | #define LED2MASK (1UL << 19)
|
3 | #define LED3MASK (1UL << 20)
|
4 | #define LED4MASK (1UL << 21)
|
5 | #define LED5MASK (1UL << 22)
|
6 | |
7 | void LEDInit (void) |
8 | {
|
9 | IODIR0 |= LED1MASK; //set port0.18 to output |
10 | IODIR0 |= LED2MASK; //set port0.19 to output |
11 | IODIR0 |= LED3MASK; //set port0.20 to output |
12 | IODIR0 |= LED4MASK; //set port0.21 to output |
13 | IODIR0 |= LED5MASK; //set port0.22 to output |
14 | }
|
Bei diesem Beispiel ist das noch vernachlaessligbar, aber bei groesseren Sachen sind solche Maskierungen recht hilfreich. Es erhoeht die Uebersicht, weil statt Bits da aussagekraeftige Symbole stehen und es ist leichter abaenderbar (im falle eines Redesigns oder wiederverwertung des codes auf einem aehnlichen Prozessor).
Damit hab ich gemeint ob ich einfach sagen kann das der Port 0.18 ein Ausgang ist?! Mit Vergabe meinte ich, das ich einfach eines der 46 IO ports als ein- oder Ausgng nehmen kann, also frei wählbar. Kann man das so machen? Wenn ich das dann so IODIR0 |= (0x00000001 << 18); schreib, würde das dann gehn das der port0.18 als Ausgang initialisiert wird?
Steff wrote: > Damit hab ich gemeint ob ich einfach sagen kann das der Port 0.18 ein > Ausgang ist?! Ja > Mit Vergabe meinte ich, das ich einfach eines der 46 IO ports als ein- > oder Ausgng nehmen kann, also frei wählbar. Kann man das so machen? Ja > Wenn ich das dann so IODIR0 |= (0x00000001 << 18); schreib, würde das > dann gehn das der port0.18 als Ausgang initialisiert wird? Ja. Das Shift macht nichts anderes, als den vorangesetzten Wert um die zu shiftenden Stellen nach Links zu bewegen. Beispiel (8Bit): |0000|0001| und die 1 wird um 3 geshiftet, dann steht da |0000|1000| Aber da du nur ein einziges Bit setzen willst, schreib einfach (1 << 18)
Achso. Schreib alles bisschen ausführlicher, aber danke für den Tipp. Neueinsteiger eben*g* In dem Programm sollen je nach Status 1 bis 5 leds brennen. Wie kann man denn am geschicktesten mehrere Leds aufeinmal zum brennen bringen? void Led1On(void) { IOCLR0 |= (0x0001 << 18); //on led port0.18 }
Am geschicktesten mit einer Maske:
1 | void Led1On(uint8_t ledmask) |
2 | {
|
3 | IOCLR0 &=~(0x1F << 18); // Set all LED Bits to 0 |
4 | |
5 | ledmask &= 0x1F; // set leading three bits of mask to 0 |
6 | |
7 | IOCLR0 |= (ledmask << 18); // Set LED Bits |
8 | }
|
Die erfahrerenen Programmierer moegen mich bitte korrigieren, falls das so nicht hinhaut. Ausm Stehgreif ohne groessere defines und Background wuerd ichs so versuchen. Vorteil: du kannst alle LEDs mit nur einem Funktionsaufruf setzen/loeschen
Matthias Nix wrote: > IOCLR0 &=~(0x1F << 18); // Set all LED Bits to 0 IOCLR0 = 0x1F << 18; // Set all LED Bits to 0 > IOCLR0 |= (ledmask << 18); // Set LED Bits IOSET0 = (ledmask << 18); // Set LED Bits
Bei meinem programm ist das halt so das es 5 unterschiedliche Schaltpunkte gibt, also eher selten alle EIN oder alle AUS sind. Dann bringt das mit der Maske eher weniger,oder? Ist es dann besser einfach für jeden Schaltpunkt die jeweiligen Leds ein bzw auszuschlten?
A. K. wrote: > Matthias Nix wrote: > >> IOCLR0 &=~(0x1F << 18); // Set all LED Bits to 0 > > IOCLR0 = 0x1F << 18; // Set all LED Bits to 0 > >> IOCLR0 |= (ledmask << 18); // Set LED Bits > > IOSET0 = (ledmask << 18); // Set LED Bits Deine Version hat aber doch einfluss auf alle andere Pins oder? 0x1F << 18 setzt alles ausserhalb der Maske auf 0, oder irre ich?
Was hat denn das uint8_t ledmask auf sich? Werden bei folgende Anweisung IOCLR0 &=~(0x1F << 18); einfach alle Ausgänge mit UND zusammengefast, deshalb werden dann die 5 bits 18 Stellen verschoben?
Morgen, Wäre echt nett wenn du dir mal anschaun könntest ob man das so schreibt. // Einschalten Led1 bis Led4 void Led1_4On(void) { IOCLR0 |= (0x0001 << 18); //on led1 IOCLR0 |= (0x0001 << 19); //on led2 IOCLR0 |= (0x0001 << 20); //on led3 IOCLR0 |= (0x0001 << 21); //on led4 Diese Anweisung sagt das gleiche aus wie die 4 oben,oder? //IOCLR0 |= (0x000F << 18); } Danke schonmal
Ja, macht das gleiche. Ist aber nicht besonders ueblich, es so zu machen, da man schon wieder genau gucken und rechnen muss um zu verstehen, was genau passiert.
Matthias Nix wrote: > Deine Version hat aber doch einfluss auf alle andere Pins oder? 0x1F << > 18 setzt alles ausserhalb der Maske auf 0, oder irre ich? Du irrst. IOCLR0=1; löscht Bit 0 und ändert sonst nichts, IOSET0=1; setzt Bit0 und ändert sonst nichts. Was meinst du denn warum die so heissen?
Ja dann mach ich es besser mit den Bitmasken, wie du es mir gestern gezeigt hast, dann wirds glaub gut aussehn. Für was steht denn in den Masken das UL?
A. K. wrote: > Matthias Nix wrote: > >> Deine Version hat aber doch einfluss auf alle andere Pins oder? 0x1F << >> 18 setzt alles ausserhalb der Maske auf 0, oder irre ich? > > Du irrst. IOCLR0=1; löscht Bit 0 und ändert sonst nichts, IOSET0=1; > setzt Bit0 und ändert sonst nichts. Was meinst du denn warum die so > heissen? JapJap, du hast recht, bei den Set und Clr Registern kann man das ja so machen, weil 0 schreiben keinen Effekt hat. Ich vergas :) War in Gedanken bei bei "normalen" Registern. @Steff: UL bedeutet UNSIGNED LONG und soll einfach garantieren, dass das ganze 32Bit konform behandelt wird, obwohl es sicherlich auch ohne gehen wuerde. Aber sicher ist sicher, is kacke zu debuggen, sowas :)
Schreibt man das dann eigentlich so: IOCLR0 |= (0x0001 << 18); //on led1 oder ohne dem ODER? IOCLR0 = (0x0001 << 18); //on led1
Steff wrote: > IOCLR0 |= (0x0001 << 18); //on led1 > IOCLR0 |= (0x0001 << 19); //on led2 > IOCLR0 |= (0x0001 << 20); //on led3 > IOCLR0 |= (0x0001 << 21); //on led4 Laß mal die ganzen |= weg und schreibe nur = Das |= ist unnötig, auch beim IOSET0. Ich bin mir auch nicht sicher, was man aus dem IOCLR zurückliest, 1-er Bits würden dann gelöscht. Peter
Danke, schon erledigt. In dem komischen Beispielprogramm schreiben die das mit |, aber es klingt viel logischer wenn es wegbleibt
Morgen, bins schon wieder. Weiß jemand wie man den Pin (P0.14), den ich für einen Button benutze wahlweiße als Taster für Kapazitätabfrage und für einen Interrupt um den uC aus dem Sleep Mode zu holen programmieren kann? Wenn der uC im Sleep Mode ist und man den Taster drückt soll er erst aufwachen und bei einer evtl. wiederholten Tastenbetätigung der Kapstatus abgefragt werden Kennt sich damit jemand aus?
Also so langsam solltest du mit Datenblatt und Tutorial selbst ein bisschen was hinbekommen. Erstmal musst du ueberhaupt kucken, ob der Pin P0.14 einen Interrupt auslösen kann (koennen naemlich nicht alle GPIOs). Dann guckst du im Datenblatt, was fuer ein Interrupt das sein wird, dann guckst du, wie du den entsprechenden Interrupt im Vector einstellen musst und dann schreibst du eine Interrupt Service Routine, die du im entsprechenden Interrupt hinterlegst. Wenn ich mich recht erinnere, ist das hier im ARM tutorial ganz gut erklärt.
Ja p0.14 kann einen interrupt auslösen. Bin halt ein kompletter Anfänger und hab noch nie so eine Interrupt Routine noch nie geschrieben, geschweige denn gesehn wie eine aussieht. Weisst du wo man evtl. eine anschaun kann?
Matthias Nix kennst du dich zufällig damit aus wie man Daten über i2C in ein dataflash schreibt oder hast du evtl. online eine Quelle wo es bisschen ausführlicher beschrieben ist als im Datenblatt, evtl mit Beispiel? Du hast doch immer so supper Tipps
Vielleicht kuckst du dann zu Beginn mal hier auf uC.net ins ARM tutorial. Da sind Beispielprogramme drin. Als zweites kannst du dich bei yahoo.de in der Gruppe LPC2000 anmelden, da gibts tonnenweise beispielcode und auch super Hilfe (aber alles auf Englisch). Als Neuling mit der 32Bit ARM Machine anzufangen, ist so besonders clever übrigens nicht. Wie weiter oben schonmal erwähnt, sollte man da zumindest etwas Erfahrung mitbringen. Mein Respekt, dass du dich da von Null durcharbeitest, haste trotzdem. Ne ISR (Interrupt Service Routine) kann ich dir jetzt ausm Kopf nicht zusammenfummeln, das muesste ich jetzt auch mitm Datenblatt basteln. Aber so schwer isses auch nicht. Schau ins tutorial, da sollte sowas drinstehen. Update: Hab noch nie mit I2C gearbeitet, sorry. Guck in die Yahoo Group, da gibts bestimmt was
ok danke, echt super nett von dir das du mir so hilfst. Ich leide glaub leicht an Selbstüberschätzung*g*
Also auf der yahoo Seite gibts schon einiges, aber leider für mich nichts brauchbares. Bräuchte irgendwie ein grundlegendes Beispiel oder sowas ähnliches. Mit EEproms kennst dich nichs so aus, oder etwa doch? Das mit i2C ist nicht mehr so wichtig. Die Daten sollen normal vom uC im EEprom abgelegt werden. Bin für jeden Rat dankbar
Wie is das eeprom angebunden? SPI, I2C? Irgendwas anderes? Um welches eeprom gehts? Was willst du wie darin ablegen?
Muss es einmal über I2C und einmal über SPI einbinden. Zuerst aber mal über SPI. Dort sollen die gemessenen Messdaten, die der uC über I2C einliest abgelegt werden. Was meinst du mit: Was willst du wie darin ablegen?
Was gibts es denn für Möglichkeiten in welcher Form die Daten abgelegt werden sollen?
Das ist ein Flash, kein eeprom. Im Datenblatt erfaehrst du alle Befehle, die noetig sind, um mit dem Speicher zu interagieren. Das Datenblatt der SPI-Schnittstelle des LPCs sagt dir, wie du die entsprechenden Register fuettern musst. Am sinnvollsten ist es, 2 Funktionen zu erstellen. Die eine baut die SPI befehle zum Schreiben auf dem Flash, die andere baut die befehle zum Lesen. Als Parameter wuerde ich Adresse, Databuffer und Datalength benutzen. So kannst du Algorithmen bauen, um auch laengere Datensaetze mit nur einem funktionsaufruf schreiben und lesen zu koennen. In der yahoo-Group sollte es aber einiges zum Thema SPI geben, da eigentlich alle DemoBoards der LPCs n Flash oder n EEPROM am SPI haengen haben. Sonst such mal speziell nach nem Board, das sowas hat (Olimex LPC2368 zB), der Prozessor ist zwar n anderer, das SPI arbeitet aber auf allen gleich
Ja das steht schon alles im Datenblatt.Weiß nur überhaupt nicht wie ich da vorgehen/anfangen soll. Hättest du evtl irgendein Beispiel parat, wie sowas aussehen könnte?
Schade. Oder wenigstens wie ich damit anfange und eine funktion aussehen könnte. Wär echt super nett von dir
werd dann mal ein neues Thread aufmachen. Hoffentlich kann mir da jemand weiterhelfen
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.