MicroController Register Manipulation (5 / 6 steg)
Steg 5: Så vad är poängen då?
Det bör vara ganska klart att skriva direkt till registren kan spara utrymme i ditt chip minne. Den förkortade skissen tar också mindre tid att köra helt enkelt eftersom det finns inget bibliotek att leta upp till varje funktion samtal. För de allra flesta applikationer, kommer detta inte någon verklig användning eftersom att eliminera en funktion som pinMode() inte kommer att spara mycket utrymme eller tid i en komplex skiss. Men i vissa program handläggningstiden är ett stort bekymmer, och minska den bortkastad tid i biblioteksfiler gör det möjligt för fler klockcykler ska vara tillgängliga för andra saker. Vad jag menar med detta är att även om du måste inkludera ett bibliotek funktion, och därför tar plats i minnet med det, om du inte kalla det mycket ofta och i stället använda registren direkt, åtminstone du sparar tid (men inte utrymme) av inte tittar upp.
Ett annat alternativ är förmågan att använda stift på sätt de inte kan ha varit ursprungligen avsett, men utan några biverkningar. Till exempel jämföra stiften är associerad med PWM på den chipKIT Uno32 har en extra register knutna som knyter in i produktionen jämför modulen (OCMP) kallas output register (OCxR). OCMP har några fler register som handlar om tidpunkten för PWM-signal, men OCxR är faktiska signal output registret, liknande LATx (PIC32) eller PORTx (ATMEL) register. PWM perioden beräknas genom att multiplicera... (lätt men förvirrande matematiska saker här)... och att värdet matas in i perioden registrera (bända). Bända berättar timer register (TMRy) som driver de särskilda OCMP när du ska återställa tillbaka till 0, men du måste lägga till en extra 1. Intermittensen sedan skrivs till det sekundära jämför register (OCxRS), som är i grunden en buffert eftersom detta värde överförs nästan omedelbart till jämför (OCxR), men du kan inte skriva det direkt eftersom OCxR är skrivskyddad.
Exempel: om bända har värdet 5 och OCxRS är laddad med värdet 2, OCxR först laddas med 2 också. TMRy börjar räkna på 0. 1, OCx ger ett högt värde och stannar där. Vid tiden 2, ingenting förändras, OCx har varit hög för 1 räkning. Vid tiden 3 sjunker OCx lågt eftersom det har varit högt för 2 räknas. På tiden 3, 4 och 5 ingenting förändras men TMRy = bända, så att den återställs och börjar sedan tillbaka på 0 på nästa räkna. 1 klocka Markera passerar, som är räkna 0 igen, och vid räkna 1, OCx utgångar hög igen. Här är siffran 16-18 från avsnitt 16: utdata jämföra PIC32 familj referensmanual:
Att bända till 5 och OCxRS till 2 ger faktiskt en arbetscykel med 33% (2/6) och inte 40% (2/5). Det är där det extra 1 kommer in. Det får läggas till värdet av bända. Detta är bara ett enkelt exempel, och om bända och OCxRS var mycket större, skillnaden i %'s skulle vara mycket, mycket mindre.
Tja, det var enkelt var det? Ja, nr jag kunde höra kugghjulen lamslagits på "För exempel..." Du skulle ha sett utseendet på mina klasskamrater ansikten när professorn visade oss detta första gången. Men det är därför vi har bibliotek. Allt det här hanteras av biblioteken när vi berättar för servo att vända med en viss hastighet eller vi vill spela en melodi med olika toner. Men 1) vi är begränsade till endast att kunna använda PWM stift och 2) bibliotek tar plats i minnet. Vad gör vi om vi behöver fler PWM alternativ? Använda registren.
Följande skiss är en enkel tone generator. Jag tänker inte göra ett servo exempel eftersom jag rekommenderar inte att använda servon utan servo.h biblioteket, men med en del arbete det är definitivt möjligt. Det är alldeles för lätt att förlänga över servo bortom det är inre hållplatser. Om du vill göra det, måste du skriva alla bakgrunden saker att servo.h handtag i skissen, men längre skisser kommer att resultera i olika PWM perioder eftersom varje rad tar lite tid.
Innan vi ser skissen, några snabba enkla matte. Först bestämma hur produktionen ofta du vill. Dividera 1 med din frekvens för att få din period, och därefter dela det på mitten. Kontrollera att värdet är i mikrosekunder, sedan sätta värdet i båda delayMicroseconds() funktion implementeringar. Om vi vill generera en arbetscykel än 50%, multiplicera din Periodvärdet plikt cykel procentsats du hög. Ange det nya värdet till funktionen delayMicroseconds() inne om() uttalande. Ange resten i delayMicroseconds() -funktionen i den annan sats.
Exempel: Du vill ha en effekt på 1kHz. 1/1000 Hz = 1 millisekund = 1000 mikrosekunder = period. 1000μs/2 = 500 μs ⇒ delayMicroseconds(). Om du vill ha 60% intermittens: 1000μs * 60% = 600 μs ⇒ om() uttalande delayMicroseconds() värde. 1000μs - 600μs = 400μs ⇒ annat uttalande delayMicroseconds() värde. Trevlig och lätt.
Här är tone generator koden:
Enkla tongeneratorn inte använder förinställda PWM
stiften men använder registret manipulation
bool state = sant;
void setup()
{
chipKIT endast
Ange register E, bit 0 som en utgång (0)
PIN-26 Uno32/uC32; stift 37 Max32
TRISE = TRISE & 0xFFFE; 0b1111 1111 1111 1110
Arduino endast
Ange register B, bit 0 som en utgång (1)
stift 8 UNO
DDRB = DDRB | 0x01; 0b0000 0001
}
void loop()
{
om (state)
{
chipKIT endast
SENT = 0X0001;
Arduino endast
PORTB = 0X01;
State = false;
delayMicroseconds(500);
}
annat
{
chipKIT endast
SENT = 0X0000;
Arduino endast
PORTB = 0X00;
State = sant;
delayMicroseconds(500);
}
}
Nedan hittar du o-scope bilder utdata, först från chipKIT Uno32...
.. .och sedan från Arduino UNO.
Galen nog, dessa bilder har genererats med hjälp av registret manipulation skissen som visas ovan, och när jag testade standardfunktion skissen, exakt samma bild dök upp. Konstigt, rätt? Så jag tänkte jag skulle bespara er att slösa tid ute på en dubblett. Jag har också ingen aning om varför den Arduino UNO är ganska instabil vid peak utgång, så om någon har någon legitim förklaring, förtydliga vänligen i kommentarerna.