Gränsyta för elektroniska kretsar till Arduinos (3 / 6 steg)
Steg 3: Omvandla vågformer till koden
Steg 3: konvertera Timing diagram in kodenArduino utvecklingsmiljön skyddar användaren från mycket rörig koden detaljer. Detta är bra när du just har börjat och vill att blinka en LED. När vi vill samverka med andra elektroniska kretsar, dock måste vi samverka mer direkt med mikroprocessor.
Första låt oss diskutera hur man effektivt läser i 16 stiften på databussen. Eftersom jag använder Arduino Mega eftersom det har en hel del IO pinnar, kan jag använda Port A och Port C vara min 16-bitars databuss. Port A och Port C är stiften 22-37 på Arduino Mega. Databussen är dubbelriktad, vilket innebär ibland stiften att används som utgångar och andra gånger som insatsvaror så vi måste ställa in pin lägen snabbt samt läsa/skriva till stiften själva. Det LÅNGSAMMA sättet att använda dessa stift skulle vara följande:
pinMode(22,INPUT);
pinMode(23,INPUT);
pinMode(24,INPUT);
…
pinMode(37,INPUT);
bit1 = digitalRead(22);
bit2 = digitalRead(23);
bit3 = digitalRead(24);
…
Bit16 = digitalRead(37);
I denna takt skulle vi förlora data som vi skulle läsa data långsammare än data tas emot. Vi måste påskynda detta genom direkt samverkar med Arduino mikroprocessorn.
Arduino mikroprocessorn är som motorn inuti Porschen. De flesta gånger en förare av en bil verkligen bara måste förstå hur man gör bilen sluta och gå och behöver inte till fullo förstå det interna arbetet av bilens motor. En racerförare, men måste förstå de begränsningar och möjligheter för motorn att driva det att vinna loppet. Likaså behöver vi förstå detaljerna för ATMEL AVR som den Arduino motor att samverka med andra elektroniska kretsar.
För att förstå den Arduino microcontroller läser vi AVR databladet. Arduino Mega använder ATMEGA1280 som kan hittas här: www.atmel.com/dyn/resources/prod_documents/doc2549.pdf
Ja, detta är 444 sidor med detaljerad information som kan vara skrämmande vid första titt. Hittar du på sidorna 100 och 101 som du kan ange alla stiften på port A för C med en enda skriva till PORTA adress och PORTC adress. Vi kan också läsa från dessa portar men vi gör det inte med att läsa från PORTA och PORTC adresser men från PINA och PINC adresser. Likaså vi kan ange pin lägen för alla stift i hamnen på en gång genom att skriva till DDRA och DDRC adresser, en '1' anger PIN-koden för utdata och '0' till ingång.
Nu kan vi ställa in stiften till ingångarna och läsa dem mycket mer snabbt med hjälp av dessa kommandon:
DDRA = 0X00;
DDRC = 0X00;
Byte1 = PINA;
Byte2 = PINC;
Och att skriva till port stiften:
DDRA = 0XFF;
DDRC = 0XFF;
PORTA = Byte1;
PORTC = Byte2;
Nu när vi kan effektivt läsa och skriva buss stiften, måste vi titta på hur man effektivt läsa och skriva andra normala stiften. I mitt exempel projekt använde jag Arduino stift 2 – 12 för att styra de 11 icke-bus styrsignaler mellan DEI1016 och Arduino. Om vi vill skriva effektiva kod för dessa stift också (och vi gör) måste vi undvika de digitalWrite och digitalRead rutiner som är långsamma eftersom de gör saker som kontroll av att se att stiften är inställd i rätt lägen, etc. För att skriva mycket snabbt kan igen vi skriva direkt till hårdvara stift att undvika Arduino overhead. Inkludera filen avrio.h innehåller funktionerna avrio_WritePin och avrio_ReadPin som utför snabb skrivning och läsning. Jag tog en aning från glcd bibliotek och definierat min egen fastWrite rutin som är #defined att avrio_WritePin att göra koden mer läsbar. Om du vill kan du granska hur glcd biblioteket löser deras snabba skriver, även om du måste korsa några lager falskhet.
En sista bit av svårigheter vi måste översätta timing diagram kod – bara hur dröj vi för det angivna antalet nanosekunder? Hur lång är en nanosekund? Fråga: Hur lång tid det tar för dig att halka på en peeling och falla? Svar: En bananosecond. Ledsen för den dåliga ordvitsen. Arduinoen har en delay(milliseconds) och delayMicroseconds() men har inte en delayNanoseconds() funktion. När du arbetar på en hög nivå språk som C, har vi mindre kunskap om hur mycket tid en mikrokontroller tar för att köra våra kommandon. Detta blir riktigt knepigt som processorerna blir mer komplexa och har undervisning rörledningar med L1 och L2 minne gömställen, etc. I vårt Arduino fall är det inte alltför svårt som vi kan använda språket C förmåga för att inkludera inline-kod. Med hjälp av församlingen kan vi räkna instruktionerna och vet hur många klocka cykler (vanligtvis 1/16000000 av en sekund) en operation tar. Genom att använda "inline" församling, våra instruktioner inte får genomföras som subrutiner och därför tar inte längre till med hoppningen subrutin och trycka och poppar data från stacken. Nackdelen med inline församling är att kompilerade objektkod blir längre, men detta är acceptabelt eftersom vi inte gör en massa förseningarna nanosekund.
Igen stjäla jag lösningen i glcd bibliotek. Det innehåller de filen delay.h som innehåller funktionen _delay_cycles. Jag definierar sedan denna funktion som den mer lättläst DelayNanoseconds enligt följande:
Hans Heinrichs dröjsmål cykel rutin:
#define DelayNanoseconds(__ns) _delay_cycles ((dubbel) (F_CPU) * ((dubbel) __ns) / 1.0e9 + 0,5)
Du kommer att märka att det finns dubbla flytande punkt math pågår här som är oftast undvikas eftersom det är mycket tidskrävande och vi vill ha mycket små förseningar. Denna rutin använder flytande punkt math rutiner att automatiskt anpassa sig till den microcontroller klockfrekvens Infoga rätt mängd av församlingen koden inline med C-kod och det bästa är att den flyttal beräkningar utförs när du kompilerar och utförs inte av Arduino vid körning! Denna metod kan resultera i en singel-instruktion 'NOP' infogas som en upptagen fördröjning.