Stap 3: ChipKIT Microcontrollers met PIC32 chips
Laten we beginnen met mijn persoonlijke favoriete familie van microcontrollers, de chipKIT. (Indien u wenst, de verkorte schets voor de Arduino UNO is in de volgende stap, maar de logica hier zal worden verklaard.) Met behulp van de Microchip PIC32 32-bits processors, de chipKIT heeft veel meer geheugen, bijna tweemaal zoveel I/O pinnen, en loopt veel sneller dan de vergelijkbare Arduino boards Arduino boards, dus als u die extra oomph moet, zou ik adviseren u kijken naar het krijgen van een. (Het is ook een goed idee om vertrouwd te raken met zo veel apparaten mogelijk om zelf te maken zo bruikbaar mogelijk aan een werkgever, als dat uw doel.)
Elke I/O pin op een microcontroller is verbonden met ten minste drie verschillende registers. (Pinnen die verschillende functies die banden met hen hebben hebben verscheidene meer, bijvoorbeeld PWM en I2C/SPI/UART.) Van de drie gaat hier, is het TRISx-register die bepaalt dat of de PIN-code is als een invoer of een uitvoer, waarbij "x" aanwijst welke TRIS werken we met omdat er verschillende zijn (de pinMode() functie wordt ingesteld TRISx). Instellen van een beetje in TRISx zoals een 1 zal de corresponderende pin als input, en hieruit dat het de instelling volgt zoals een 0 de pincode als uitgang instellen zal. Het volgende is het LATx-register, dat is waar we het toewijzen van een pincode instellen als uitgang hoog (1) en laag (0) (digitalWrite() wordt ingesteld LATx). De laatste is het PORTx-register, en dit is waar we de huidige stand van de pin kunt lezen wanneer het is ingesteld op een ingang (digitalRead() leest PORTx). Een '1' bit in de PORTx geeft aan dat de corresponderende invoer pin is het opsporen van een hoge waarde van logica. Elk journaal wordt bijgewerkt met de perifere bus klok, terwijl de code wordt uitgevoerd, zodat de status van uw invoer/uitvoer real-time zullen. Technisch u kunt lezen/schrijven voor alle drie van deze registers, maar je echt alleen wilt schrijven naar het TRISx registreren één keer in uw setup() verklaring aan het begin van uw schets. U kunt ophalen van de staat van zowel LATx als PORTx en gebruiken die gegevens zo nodig, maar een 1 schrijven naar het register van de LATx voor een pin die is aangewezen als een input zal niets doen omdat het niet uitvoeren (u deze instellen als een ingang met het TRISx-register). Nog verward?
Houden op de trucking, zal het zinvol.
Om te initialiseren TRISx in setup(), moet u eerst weten welke register en bits zijn gebonden aan welke pinnen. Met behulp van de pin-out tabel (zie bijgevoegd PDF-bestand hieronder) voor de chipKIT Uno32, kunnen we zien dat pinnen 26→33 heel mooi om te registreren zijn toegewezen E, bits 0→7. (Ik vind het gemakkelijker te gebruiken van opeenvolgende bits in een register. Later zullen we moeten doen sommige bitsgewijze bewerkingen, en het vereenvoudigt dingen.) Het moet zinvol dan dat we TRISE, stukjes 0→7 zal stellen. Terugkijkend op de code, vastbesloten wij dat pinnen 26→29 zou LEDs en 30→33 zou de schakelaars. Pins 26→29 kaart te TRISE bits 0→3. LED's zijn output, dus stukjes 0→3 krijgen een 0. Pins 30→33 kaart te TRISE bits 4→7. Switches zijn input, zodat bits 4→7 krijgen een 1. Het register stukje-bij-beetje kijken, moeten we de laatste 8 bits van TRISE als 1111 0000. Neem een tweede om ervoor te zorgen dat u begrijpen waarom.
We kunnen gewoon de waarde, toewijzen met een hex waarde van 0xF0 of een binaire waarde van 0b11110000, rechtstreeks naar TRISE met de lijn
TRISE = 0XF0;
maar we lopen het risico per ongeluk de andere meer significante bits in het register te wijzigen. Vergeet niet dat we te maken met 16-32-bits registers met het PIC32 hebben. (Uit tabel 4-27 op pg 73 van het gegevensblad voor de PIC32MX320F128, ik weet dat TRISE alleen me in staat toegang tot de minst significante bits van 10 stelt, maar ik kies ervoor om het hele 16-bits register als een kwestie van goede praktijken te beschermen.) We moeten ervoor zorgen dat wij alleen de exacte bits die we nodig hebben terwijl de andere bits in welke staat zij momenteel in zodat we niet per ongeluk jack dingen op instelt. Hiervoor gebruiken we een techniek genaamd maskeren en sommige bitsgewijze logische operatoren. Laten we zeggen dat TRISE met een waarde van 0b1101 begint 0010 1001 1011. Met behulp van de bit-gewijze logische operator OR "|", wij of TRISE met 0b0000 0000 1111 0000 (0x00F0). Wanneer we wel, daar waar een '1', het resultaat zal altijd een. Als er een '0', zal het resultaat worden bepaald door de staat van de andere operand. Terug naar ons voorbeeld, als we OR 0b1101 0010 1001 1011 met 0b0000 0000 1111 0000 we met 0b1101 eindigen 0010 1111 1011. We kunnen zien dat bits 4→7 zijn nu alle 1's, dat is wat we wilden.
Met behulp van soortgelijke logica en de AND-operator, we nemen vervolgens TRISE en en het met 0b1111 1111 1111 0000. Elke keer we en met een '0', het resultaat is altijd een 0. ANDing met een '1' resulteert in de status van de andere operand. Dus we 0b1101 hebben 0010 1111 1011, en met 0b1111 1111 1111 0000 en het resultaat is 0b1101 0010 1111 0000. De laatste vier bits, 0→3, zijn nu 0, die weer is wat we wilden. Merk op dat de 8 meest significante bits links onaangeroerd. De twee operaties (en/of) zonder het resultaat kan worden teruggedraaid. De twee coderegels hiervoor zijn als volgt:
TRISE = TRISE | 0x00F0; 0b0000 0000 1111 0000
TRISE = TRISE & 0xFFF0; 0b1111 1111 1111 0000
Als het het gemakkelijker maakt, kunnen de waarden van de Hexuitdraai/bin als int variabelen voordat setup()worden toegewezen.
Nu dat we TRISE instellen, (pinMode()) we kunnen nu schrijven onze lusinstructie() . Terugkijkend op de kortere, vereenvoudigde versie van de code in de laatste stap, merken dat zijn we het lezen van de staat van de invoer pin (digitalRead() = PORTE) en het toewijzen aan de uitgang-pins (digitalWrite() = LATE). Zo laat = PORTE, maar met een lichte aanpassing. Vergeet niet dat de knoppen zijn gekoppeld aan de PORTE bits 4→7 en de LED's zijn gebonden aan LATE bits 0→3. Als we laat schrijven = PORTE, schrijven we de staat van PORTE bits 4→7 te LATE bits 4→7, niet laat bits 0→3. We willen verschuiven van de PORTE gegevens over naar de recht 4 ruimten zodat deze overeenkomt met de plaatsing van de bits in LATE. Anders gezegd, als PORTE 0b0010 leest 1101 1111 0000, bits 4→7 zijn allemaal hoog. We verschuiven de gegevens direct aan 4 bits (0b0000 0010 1101, 1111) en deze nieuwe waarde toewijzen aan LATE, instellen van de bits 0→3 hoog en alle 4 LEDs oplichten. Een bitsgewijs verplaatsen is eenvoudig voor de processor te doen en heeft geen invloed op de huidige gegevens op PORTE aanwezig. De PORTE-gegevens wordt daadwerkelijk gekopieerd naar een tijdelijke register en dat is degene die indien nodig wordt gemanipuleerd. De enige manier voor PORTE waarden wijzigen is de knopstatussen wijzigen. Hier is de regel code:
LAAT = PORTE >> 4;
U zult merken dat ik niet proberen ben te doen elke maskeren hier bij het toewijzen van PORTE te laat. De reden is dat LATE wordt niet voor iets anders dan de uitvoer gebruikt, en als de specifieke bit in TRISE is niet ingesteld als uitgang, een 1 op dat beetje in LATE geen effect hoeft. Hetzelfde geldt voor PORTE wanneer het proberen om het te lezen. U kunt een knop koppelen aan elke bit in PORTE, maar tenzij u PORTE als input in TRISE toewijst, het indrukken van de knop de waarde in het register niet gewijzigd. Wijzigingen zijn dolende en willekeurige omdat de PIN-code geen pull-up /-down weerstand heeft.
Met behulp van 4 opeenvolgende bits in PORTE, is het uitpakken van de gegevens een simpele kwestie van de verschuiving van bitwise, die een belachelijk goedkope operatie is wat betreft de chip is in termen van tijd en middelen die nodig zijn. Als wij hadden gebruikt bits verspreid en registers rond het bord, zouden we moeten doen wat maskeren en ANDing en ORing, maar kunnen we de gegevens. Wij hebben ook vermeden bellen pinMode(), digitalRead()en digitalWrite(), dus onze code minder ruimte op chip nemen moet omdat deze achtergrondbestanden niet hoeft te worden geladen. Laten we eens kijken hoeveel ruimte we nu nodig hebben.
Hier is de code:
/* chipKIT register manipulation with 4 switches and 4 LEDs * Uno32/uC32 - 4 switches on pins 30-33, 4 LEDs on pins 26-29. * Max32 - 4 switches on pins 30-33, 4 LEDs on pins 34-37. * DP32 - 4 switches on pins 0-3, 4 LEDs on pins 5-8. * CMOD - 4 switches on pins 35-38, 4 leds on pins 20-23. */ void setup() { // Uno32, Uc32, and Max32 TRISE = TRISE & 0xFFF0; // digital pins 26->33 (37->30 Max32) map to TRISE = TRIES | 0x00F0; // register E, bits 0->7, respectively. A '1' // defines the pin as input, '0' as output. // We use the bitwise AND (&) first to set bits // 0-3 as 0 (output) and then bitwise OR (|) to // set bits 4-7 as input. This allows the remaining // bits to be unaffected and avoid unwanted operation // and only set the 8 pins we want. You could write // TRISE = 0xnnnn to set just the bits you want // (where n is any hex digit) but there is no way // of knowing how the other bits in the register // will be affected. It may do nothing, it may not. // DP32 only // TRISB = TRISB & 0x17FF; // digital pins 0->3 and 5->8 map to // TRISB = TRISB | 0x03A0; // register B, bits 5,7->9 and 11,13->15 // respectively. The same logic as above applies // here with setting the TRIS register. // CMOD only // TRISB = TRISB & 0xFFF0; // digital pins 20->23 and 35->38 map to register, // TRISB = TRISB | 0x01E0; // bits 0->3 and 5->8 respectively. The same logic // as above applies here with setting the TRISx // register. } void loop() { // Uno32, Uc32, and Max32 LATE = PORTE >> 4; // write the status of the switches on PORTE to // the LEDs on LATE, but bit shifted right by 4 bits. // So RE7-4 map to RE3-0. // DP32 only // LATB = PORTB << 6; // CMOD only // LATB = PORTB >> 5; }
Deze code neemt 10 lijnen w/o opmerkingen, en de meeste daarvan zijn de vereiste installatie-() en lus() structuren. Er zijn slechts 3 werkelijke coderegels. 3.
Compileren van dit in MPIDE voor de chipKIT Uno32 vereist 4792 bytes, een vermindering van 1532 bytes van de kortere versie in de vorige stap die 6324 bytes kosten.
De volgende stap toont dezelfde code maar speciaal voor de ATMEL-chip.