Innehållsförteckning:

AVRSH: a Command Interpreter Shell för Arduino/AVR .: 6 steg (med bilder)
AVRSH: a Command Interpreter Shell för Arduino/AVR .: 6 steg (med bilder)

Video: AVRSH: a Command Interpreter Shell för Arduino/AVR .: 6 steg (med bilder)

Video: AVRSH: a Command Interpreter Shell för Arduino/AVR .: 6 steg (med bilder)
Video: AVR Shell Command Interpreter 2024, Juli
Anonim
AVRSH: a Command Interpreter Shell för Arduino/AVR
AVRSH: a Command Interpreter Shell för Arduino/AVR

Har du någonsin velat bli "inloggad" på din AVR -mikrokontroller? Har du någonsin trott att det skulle vara coolt att "katta" ett register för att se dess innehåll? Har du alltid velat ett sätt att slå på och stänga av enskilda perifera undersystem på din AVR eller Arduino i * realtid *? Jag också, så jag skrev AVR-skalet, ett UNIX-liknande skal. Det är UNIX-liknande eftersom det påminner om skalkontot som du gick ut och köpte för att köra dina irc nick kollisionsbots på, liksom att ha ett eller två kommandon gemensamt. Det har också ett filsystem som liknar UNIX extfs, med hjälp av en extern EEPROM, men det har blivit ett projekt för sig själv så jag kommer att släppa den modulen separat under en annan instruerbar när den är produktionsklar. Här är en lista över de saker du för närvarande kan göra med AVR -skalet:

  • Läs alla dina Data Direction Registers (DDRn), portar och stift i realtid
  • Skriv till alla dina DDRn, portar och stift för att slå på motorer, lysdioder eller läsa sensorer i realtid
  • Lista alla kända register på systemet
  • Skapa och lagra värden i användardefinierade variabler som säkerhetskopieras av EEPROM.
  • Skapa ett rotlösenord och verifiera mot det (används för telnetåtkomst)
  • Läs den konfigurerade CPU -klockhastigheten
  • Ändra din CPU -klockhastighet genom att ställa in en förkalkning
  • Starta och stoppa 16-bitars timers för timing av olika saker
  • Starta och/eller stänga av perifera undersystem: Analog till digitala omvandlare (ADC), Seriellt perifert gränssnitt (SPI), Tvåtrådigt gränssnitt (TWI/I2C), UART/USART. Användbart för när du vill minska mikroförbrukningens strömförbrukning eller för att aktivera vissa funktioner.
  • Skrivet i C ++ med återanvändbara objekt.

Denna instruerbara kommer att gå igenom installationen, användningen och anpassningen av avrsh.

Steg 1: Vad du behöver

Vad du behöver
Vad du behöver

Denna instruerbara kräver inte mycket förutom att du:

  • Ha en Arduino eller ATmega328P. Andra AVR kan fungera, men du kan behöva ändra koden för att lista alla register som är unika för din MCU. Namnen behöver bara matcha det som anges i rubrikfilen som är unik för din MCU. Många av registernamnen är desamma mellan AVR: er, så din körsträcka kan variera vid portning.
  • Har ett sätt att ansluta till den seriella USART på din Arduino/AVR. Systemet har testats mest utförligt med AVR -terminalen, en Windows -app som gör en seriell anslutning via din USB- eller COM -port. Fungerar med Arduinos med USB-anslutningen och alla AVR som använder USB-BUB från Moderndevice.com. Andra terminalalternativ inkluderar: Kitt, minicom (Linux och FreeBSD), skärm (Linux/FreeBSD), Hyperterminal, Teraterm. Jag har hittat kitt och teraterm skicka lite skräp när du ansluter så att ditt första kommando kan vara förvrängt.
  • Har AVR Shell -firmware installerad och igång, som du kan ladda ner från dessa sidor, eller alltid få den senaste versionen på BattleDroids.net.

För att installera AVR -terminalen, packa upp den och kör den. För att installera AVR Shell -firmware, ladda ner den och antingen direkt ladda upp hex -filen och anslut din seriella terminal på 9600 baud, eller kompilera den själv med "make" och sedan "make program" för att ladda upp hexen. Observera att du kan behöva ändra AVRDUDE -inställningarna för att återspegla din COM -port. Obs! PROGMEM -attributet är trasigt i den nuvarande AVR GCC -implementeringen för C ++ och detta är en känd bugg. Om du kompilerar det, räkna med att få många varningsmeddelanden som säger "varning: endast initialiserade variabler kan placeras i programmets minnesområde." Förutom att det är irriterande att se, är den här varningen ofarlig. Eftersom C ++ på den inbäddade plattformen inte är högt på AVR GCC: s prioriteringslista är det okänt när detta kommer att åtgärdas. Om du checkar ut koden kommer du att se var jag har arbetat runt för att minska denna varning genom att implementera mina egna attribututtalanden. Ganska enkelt. Ladda ner och installera allt som du kan behöva för att sedan vända på sidan och låt oss få spricka.

Steg 2: Läsa och skriva register

Läsa och skriva register
Läsa och skriva register

AVR -skalet skrevs främst för att komma åt vissa sensorer som jag hade anslutit till min AVR. Det började med en enkel LED och flyttade sedan till ljussensorer, temperatursensorer och slutligen till två ultraljudsgivare. avrsh kan ställa in de digitala komponenterna i dessa sensorer genom att skriva till registren som styr dem. Hantera AVR -register medan du kör För att få en lista över alla kända register på din Arduino skriver du:

skriva ut register och du får en utskrift som ser ut så här

Jag känner till följande register:

TIFR0 PORTC TIFR1 PORTD TIFR2 DDRD PCIFR DDRB EIFR DDRC EIMSK PINB EECR PINC EEDR PIND SREG EEARL GPIOR0 EEARH GPIOR1 GTCCR GPIOR2 TCCR0A TCCR0B TCNT0 OCR0A OCR0B SPCR SPDR ACSR SMCR MCUSR MCUCR SPMCSR WDTCSR CLKPR PRR OSCCAL PCICR EICRA PCMSK0 PCMSK1 TIMSK0 TIMSK1 TIMSK2 ADCL ADCH ADCSRA ADCSRB ADMUX DIDR0 DIDR1 TCCR1A TCCR1B TCCR1C TCNT1L TCNT1H ICR1L ICR1H OCR1AL OCR1AH OCR1BL OCR1BH TCCR2A TCCR2B TCNT2 OCR2A OCR2B ASSR TWBR TWSR TWR0 UR0 UR0 UR0 UR0 UR0 UCR För att se hur de enskilda bitarna ställs in i ett register använder du kommandot cat eller echo

katt %GPIOR0 Här ber jag kommandotolkaren att visa, eller eko, innehållet i I/O -registret för allmänt ändamål #0. Notera procenttecknet (%) framför registernamnet. Du behöver detta för att indikera för skalet att detta är ett reserverat nyckelord som identifierar ett register. Den typiska utsignalen från ett ekokommando ser ut så här

GPIOR0 (0x0) inställd på [00000000] Utdata visar namnet på registret, det hexadecimala värdet som finns i registret och den binära representationen av registret (visar varje bit som en 1 eller 0). För att ställa in en viss bit i vilket register som helst, använd "index för" -operatorn . Låt oss till exempel säga att jag vill ha den tredje biten till en 1

%GPIOR0 [3] = 1 och skalet ger dig ett svar som indikerar dess handling och resultatet

GPIOR0 (0x0) inställd på [00000000] (0x8) inställd på [00001000] Glöm inte procenttecknet för att berätta för skalet att du arbetar med ett register. Observera också att genom att ställa in den tredje biten är det 4 bitar in eftersom våra AVR använder ett nollbaserat index. Med andra ord, räknar du till den tredje biten räknar du 0, 1, 2, 3, vilket är den fjärde platsen, men den tredje biten. Du kan rensa lite på samma sätt genom att sätta lite till noll. Genom att ställa in bitar så här kan du ändra din AVR: s funktion direkt. Till exempel genom att ändra matchningsvärdet för CTC -timer som finns i OCR1A. Det låter dig också kika in på specifika inställningar som du skulle behöva programmera in i din kod, till exempel UBBR -värdet för din överföringshastighet. Arbeta med DDRn, PORTn och PINn I/O -stiften är också tilldelade register och kan ställas in på exakt samma sätt, men en speciell syntax har skapats för att arbeta med dessa typer av register. I koden finns det en normal process för att tända en LED eller annan enhet som kräver en digital hög eller låg. Det kräver att du ställer in datariktningsregistret för att indikera att stiftet är för utmatning och sedan skriver ett 1 eller 0 till den specifika biten i rätt port. Förutsatt att vi har en lysdiod ansluten till digital pin 13 (PB5) och vi vill slå på den, så här gör du det medan din AVR körs

set pin pb5 outputwrite pin pb5 high Utgången, förutom att kunna se din LED tändas, skulle se ut så här

root@ATmega328p> set pin pb5 output Ställ in pb5 för outputroot@ATmega328p> skriv pin pb5 high Skriv logik hög till pin pb5 "Root@ATmega328p>" är skalets prompt som indikerar att den är redo att acceptera kommandon från dig. För att stänga av lysdioden skulle du helt enkelt skriva ett lågt till stiftet. Om du vill läsa den digitala ingången från en pin, använd kommandot read. Med vårt exempel ovan

root@ATmega328p> läs pin pb5Pin: pb5 är HÖG Alternativt är det bara att eka stiftregistret som styr den stiftporten. Om vi till exempel har dip switchar anslutna till digital pin 7 och 8 (PD7 och PD8), kan du skicka kommandot

eko %PIND och skalet skulle då visa innehållet i det registret och visa dig alla in-/utgångstillstånd för anslutna enheter och om omkopplarens tillstånd var på eller av.

Steg 3: Läsa och skriva säkringar

Läser och skriver säkringar
Läser och skriver säkringar

Säkringar är speciella typer av register. De styr allt från klockhastigheten på din mikrokontroller till vilka programmeringsmetoder som finns tillgängliga för skrivskyddande EEPROM. Ibland måste du ändra dessa inställningar, särskilt om du skapar ett fristående AVR-system. Jag är inte säker på att du ska ändra dina säkringsinställningar på Arduino. Var försiktig med dina säkringar; du kan låsa dig själv om du ställer in dem felaktigt. I en tidigare instruerbar visade jag hur du kan läsa och ställa in dina säkringar med din programmerare och avrdude. Här visar jag dig hur du läser tillbaka dina säkringar vid körning för att se hur din MCU faktiskt har ställt in dem. Observera att detta inte är inställningen för kompileringstid som du får från definitionerna i utan de faktiska säkringarna när MCU läser dem vid körning. Från tabell 27-9 i ATmega328P-databladet (databok, mer liknande det) är bitarna i Fuse Low Byte följande:

CKDIV8 CKOUT SUT1 SUT0 CKSEL3 CKSEL2 CKSEL1 CKSEL0En intressant sak att notera är att med säkringar betyder 0 programmerad och 1 betyder att just den biten är oprogrammerad. Något kontraintuitivt, men när du väl vet det vet du det.

  • CKDIV8 ställer in din CPU -klocka att delas med 8. ATmega328P kommer från fabriken programmerad för att använda sin interna oscillator vid 8MHz med CKDIV8 programmerad (dvs inställd på 0) vilket ger dig en slutlig F_CPU eller CPU -frekvens på 1MHz. På Arduino's ändras detta eftersom de är konfigurerade för att använda en extern oscillator vid 16MHz.
  • CKOUT när den är programmerad kommer att mata ut din CPU -klocka på PB0, som är digital pin 8 på Arduinos.
  • SUT [1..0] anger starttiden för din AVR.
  • CKSEL [3..0] ställer in klockan, till exempel den interna RC -oscillatorn, den externa oscillatorn, etc.

När du läser dina säkringar returneras den till dig i hexadecimal. Detta är det format du behöver om du vill skriva säkringar via avrdude. På min arduino, här är vad jag får när jag läser den lägre säkringsbyte:

root@ATmega328p> läs lfuseLower Säkring: 0xffSå, alla bitar är inställda på 1. Jag gjorde samma procedur på en Arduino -klon och fick samma värde. När jag kontrollerade ett av mina fristående AVR-system fick jag 0xDA vilket är det värde jag hade ställt in för en tid tillbaka när jag konfigurerade chipet. Samma procedur används för att kontrollera High Fuse Byte, Extended Fuse Byte och Lock säkringar. Kalibrerings- och signatur säkringsbyte har inaktiverats i koden med ett #if 0 förbehandlingsdirektiv, som du kan ändra om du känner dig skrapig.

Steg 4: Andra kommandon

Andra kommandon
Andra kommandon

Det finns flera andra kommandon som standardkommandotolkar förstår att du kan tycka är användbara. Du kan se alla implementerade kommandon och kommande kommandon genom att utfärda hjälp eller meny vid prompten. Jag kommer snabbt att täcka dem här eftersom de mestadels är självförklarande. CPU -klockfrekvensinställningar Du kan ta reda på vad din firmware har konfigurerats för att använda som CPU -klockinställningar med fcpu -kommandot:

root@ATmega328p> fcpuCPU Freq: 16000000Det är 16 miljoner, eller 16 miljoner herz, mer allmänt känt som 16 MHz. Du kan ändra detta direkt, oavsett anledning, med klockkommandot. Det här kommandot tar ett argument: förkalkningen som ska användas när du delar din klockhastighet. Klockkommandot förstår dessa förkalkningsvärden:

  • ckdiv2
  • ckdiv4
  • ckdiv8
  • ckdiv16
  • ckdiv32
  • ckdiv64
  • ckdiv128
  • ckdiv256

Använda kommandot:

klocka ckdiv2 när din CPU -hastighet är 16MHz skulle resultera i att din klockhastighet ändras till 8MHz. Att använda en förkalkning av ckdiv64 med en initial klockhastighet på 16MHz resulterar i en slutlig klockhastighet på 250 KHz. Varför i helvete skulle du vilja göra din MCU långsammare? Tja, för en, en lägre klockhastighet förbrukar mindre ström och om du har din MCU igång från ett batteri i ett projekthölje kanske du inte behöver det för att köra med högsta hastighet, och kan därför sänka hastigheten och minska dess strömförbrukning, vilket ökar batteriets livslängd. Om du också använder klockan för någon form av tidpunktsproblem med en annan MCU, säg att implementera en programvaru -UART eller något sådant, kanske du vill ställa in den till ett visst värde som är lätt att få en bra jämn överföringshastighet med lägre felprocent. Slå på och stänga av kringutrustningssystem På samma sätt som att minska energiförbrukningen som nämnts tidigare kanske du vill minska strömmen ytterligare genom att stänga av några av de inbyggda kringutrustningar som du inte använder. Kommandotolk och skal kan för närvarande slå på och stänga av följande kringutrustning:

  • Analog-till-digital-omvandlare (ADC). Denna kringutrustning används när du har en analog sensor som tillhandahåller data (som temperatur, ljus, acceleration, etc.) och behöver konvertera den till ett digitalt värde.
  • Seriellt perifert gränssnitt (SPI). SPI-bussen används för att kommunicera med andra SPI-aktiverade enheter, som externa minnen, LED-drivrutiner, externa ADC, etc. Delar av SPI används för ISP-programmering, eller åtminstone stiften är, så var försiktig när du stänger av detta om du programmerar via ISP.
  • Tvåtrådigt gränssnitt. Vissa externa enheter använder I2C-bussen för att kommunicera, även om dessa snabbt ersätts av SPI-aktiverade enheter eftersom SPI har en större genomströmning.
  • USART. Detta är ditt seriella gränssnitt. Du vill förmodligen inte stänga av detta om du är ansluten till AVR via den seriella anslutningen! Men jag lade till detta här som ett skelett för portning till enheter som har flera USART -enheter som ATmega162 eller ATmega644P.
  • Allt. Detta argument till kommandot powerup eller powerdown aktiverar alla nämnda kringutrustning eller stänger av dem alla med ett kommando. Återigen, använd detta kommando klokt.

root@ATmega328p> powerdown twiPowerdown of twi complete.root@ATmega328p> powerup twi Powerup of twi complete.

Starta och stoppa timers Skalet har en inbyggd 16-bitars timer som är tillgänglig för användning. Du startar timern med timer -kommandot:

timer startoch stoppa timern med stoppargumentet

timerstoppDenna timer kommer inte att stå i konflikt med den interna USART -timern. Se koden för implementeringsdetaljer för USART -timern, om den typen av tråkiga detaljer intresserar dig

root@ATmega328p> timer startStarted timer.root@ATmega328p> timer stop Förfluten tid: ~ 157 sekunder Autentisering Skalet kan lagra ett lösenord med 8 tecken i EEPROM. Denna lösenordsmekanism skapades för att stödja telnet -inloggningsfunktionerna, men kan utökas för att skydda andra saker. Till exempel kan du kräva vissa kommandon, som att ändra registervärden, via autentiseringsmekanismen. Ställ in lösenordet med lösenordskommandot

root@ATmega328p> passwd blah Skriv root -lösenord till EEPROMAuktorisera mot lösenordet (eller kräva auktorisation programmatiskt genom koden) med kommandot auth. Observera att om du försöker ändra rotlösenordet och det redan finns ett rotlösenord måste du godkänna dig själv mot det gamla lösenordet innan du kan ändra det till ett nytt lösenord

root@ATmega328p> passwd blinkyDu måste auktorisera dig själv först. root@ATmega328p> auth blahAuthorized.root@ATmega328p> passwd blinky Skriver NYTT root -lösenord till EEPROMNaturligtvis måste du ladda avrsh.eep -filen om du raderar firmware för att dina gamla värden och variabler ska återställas. Makefile skapar EEPROM -filen åt dig. Variabler Skalet förstår begreppet användardefinierade variabler. Koden begränsar detta till 20, men du kan ändra det om du vill genom att ändra definiera MAX_VARIABLES i script.h. Du kan spara valfritt 16-bitars värde (det vill säga vilket nummer som helst upp till 65, 536) till en variabel som ska återkallas senare. Syntaxen liknar register förutom att ett dollarstecken ($) används för att beteckna variabler till skalet. Lista alla dina variabler med kommandot print variables

skrivvariabler Användardefinierade variabler: Indexnamn -> Värde (01): $ FREE $ -> 0 (02): $ FREE $ -> 0 (03): $ FREE $ -> 0 (04): $ FREE $ -> 0 (05): $ FREE $ -> 0 (06): $ FREE $ -> 0 (07): $ FREE $ -> 0 (08): $ FREE $ -> 0 (09): $ FREE $ -> 0 (10): $ FREE $ -> 0 (11): $ FREE $ -> 0 (12): $ FREE $ -> 0 (13): $ FREE $ -> 0 (14): $ FREE $ -> 0 (15): $ FREE $ -> 0 (16): $ FREE $ -> 0 (17): $ FREE $ -> 0 (18): $ FREE $ -> 0 (19): $ FREE $ -> 0 (20): $ FREE $ -> 0Complete. Ange en variabel

$ newvar = 25 $ timeout = 23245Få värdet på en given variabel

root@ATmega328p> eko $ newvar $ newvar 25Du kan se vad alla variabler du för närvarande har instanserat med utskriftskommandot som du redan känner till

Användardefinierade variabler: Indexnamn -> Värde (01): newvar -> 25 (02): timeout -> 23245 (03): $ FREE $ -> 0 (04): $ FREE $ -> 0 (05): $ FREE $ -> 0 (06): $ FREE $ -> 0 (07): $ FREE $ -> 0 (08): $ FREE $ -> 0 (09): $ FREE $ -> 0 (10): $ FREE $ -> 0 (11): $ FREE $ -> 0 (12): $ FREE $ -> 0 (13): $ FREE $ -> 0 (14): $ FREE $ -> 0 (15): $ FREE $ -> 0 (16): $ FREE $ -> 0 (17): $ FREE $ -> 0 (18): $ FREE $ -> 0 (19): $ FREE $ -> 0 (20): $ FREE $ -> 0 Komplett.$ FREE $ -namnet indikerar bara att den variabla platsen är ledig och inte har tilldelats ett variabelnamn ännu.

Steg 5: Anpassa skalet

Anpassa skalet
Anpassa skalet

Du är fri att hacka på koden och anpassa den till dina egna behov, om du vill. Om jag hade vetat att jag skulle släppa den här koden, skulle jag ha gjort en separat kommandotolkarklass och kommandostruktur och helt enkelt itererat genom att kalla en funktionspekare. Det skulle minska mängden kod, men som det ser ut analyserar skalet kommandoraden och anropar lämplig skalmetod. För att lägga till dina egna anpassade kommandon, gör följande: 1. Lägg till ditt kommando i analyslistan Kommandotolken kommer analysera kommandoraden och ge dig kommandot och eventuella argument separat. Argumenten överförs som pekare till pekare, eller en rad pekare, men du gillar att arbeta med dem. Detta finns i shell.cpp. Öppna shell.cpp och hitta ExecCmd -metoden i AVRShell -klassen. Du kanske vill lägga till kommandot i programminnet. Om du gör det lägger du till kommandot i progmem.h och progmem.cpp. Du kan lägga till kommandot direkt i programminnet med PSTR () -makrot, men du kommer att generera en annan varning för den typ som nämnts tidigare. Återigen, detta är en känd bugg som arbetar med C ++, men du kan komma runt detta genom att lägga till kommandot direkt i programmets.* -Filer, som jag har gjort. Om du inte har något emot att lägga till din SRAM -användning kan du lägga till kommandot som jag har illustrerat med kommandot "klocka". Säg att du ville lägga till ett nytt kommando som heter "newcmd." Gå till AVRShell:: ExecCmd och hitta en lämplig plats att infoga följande kod:

annars om (! strcmp (c, "newcmd")) cmdNewCmd (args);Detta kommer att lägga till ditt kommando och anropa cmdNewCmd -metoden som du kommer att skriva i nästa steg. 2. Skriv din anpassade kommandokod Lägg till din anpassade kommandokod i samma fil. Detta är metoddefinitionen. Du kommer fortfarande att vilja lägga till deklarationen till shell.h. Lägg det bara till de andra kommandona. I föregående exempel kan koden se ut ungefär så här

voidAVRShell:: cmdNewCmd (char ** args) {sprintf_P (buff, PSTR ("Ditt kommando är %s / r / n", args [0]); WriteRAM (buff);}Det finns flera saker här. För det första är "buff" en buffert med 40 tecken som finns i koden för din användning. Vi använder programminnesversionen av sprintf eftersom vi skickar den en PSTR. Du kan använda den vanliga versionen om du vill, men se till att du inte klarar formatet i en PSTR. Argumenten finns också i args -arrayen. Om du skrev "newcmd arg1 arg2" kan du komma till dessa argument med argumenten [0] och args [1]. Du kan skicka maximalt MAX_ARGS -argument enligt definitionen i koden. Ändra gärna det värdet när du kompilerar om du behöver många fler argument som ska skickas på en gång. WriteLine och WriteRAM är globala funktioner som returnerar UART: s metoder med samma namn. Det andra argumentet till denna funktion är implicit. Om du inte klarar något kommer en kommandotolk att skrivas efteråt. Om du skickar ett 0 som det andra argumentet kommer en prompt inte att skrivas. Detta är användbart när du vill skriva flera separata strängar för att mata ut innan kommandotolken returneras till användaren. 3. Låt skalet köra kommandokoden Du har redan sagt till skalexekutören att köra metoden cmdNewCmd när du konfigurerar det nya kommandot, men lägger till det i filen shell.h för att få det att förstås av skalobjektet. Lägg bara till det under det sista kommandot eller framför det första kommandot, eller var som helst där inne. Och det är det. Omkompilera och ladda upp firmware till din Arduino och ditt nya kommando är tillgängligt från skalet vid prompten.

Steg 6: Sammanfattning

Du bör veta hur du installerar och ansluter till din AVR/Arduino och får en live -prompt på din mikrokontroller som körs. Du känner till flera kommandon som drar körtidsdata från MCU: n eller ställer in värden i MCU: n direkt. Du har också visat hur du lägger till din egen anpassade kod för att skapa dina egna unika kommandon i skalet för att ytterligare anpassa den efter dina egna behov. Du kan till och med tömma kommandotolkaren så att den bara innehåller dina egna kommandon om det passar dina behov. som en inlärningsprocess för att implementera din egen. Som alltid ser jag fram emot kommentarer eller förslag på hur denna instruerbara kan förbättras! Ha kul med din AVR!

Rekommenderad: