Innholdsfortegnelse:

AVRSH: a Command Interpreter Shell for Arduino/AVR .: 6 trinn (med bilder)
AVRSH: a Command Interpreter Shell for Arduino/AVR .: 6 trinn (med bilder)

Video: AVRSH: a Command Interpreter Shell for Arduino/AVR .: 6 trinn (med bilder)

Video: AVRSH: a Command Interpreter Shell for Arduino/AVR .: 6 trinn (med bilder)
Video: AVR Shell Command Interpreter 2024, November
Anonim
AVRSH: a Command Interpreter Shell for Arduino/AVR
AVRSH: a Command Interpreter Shell for Arduino/AVR

Har du noen gang ønsket å være "logget inn" på AVR -mikrokontrolleren din? Har du noen gang tenkt at det ville være kult å "katte" et register for å se innholdet? Har du alltid ønsket en måte å slå på og slå av individuelle perifere undersystemer til AVR eller Arduino i * sanntid *? Jeg også, så jeg skrev AVR-skallet, et UNIX-lignende skall. Det er UNIX-aktig fordi det minner om skallkontoen du gikk ut og kjøpte for å kjøre irc nick kollisjonsroboter på, i tillegg til å ha en kommando eller to til felles. Det har også et filsystem som ligner UNIX-extfs, ved hjelp av en ekstern EEPROM, men det har blitt et prosjekt for seg selv, så jeg skal slippe den modulen separat under en annen instruerbar når den er produksjonsklar. Her er en liste over tingene du kan gjøre med AVR -skallet:

  • Les alle dine data direction registre (DDRn), porter og pins i sanntid
  • Skriv til alle dine DDRn-er, porter og pins for å slå på motorer, LED-er eller lese sensorer i sanntid
  • Liste over alle kjente registre på systemet
  • Lag og lagre verdier i brukerdefinerte variabler sikkerhetskopiert av EEPROM.
  • Opprett et rotpassord og godkjenn det (brukes for telnet -tilgang)
  • Les den konfigurerte CPU -klokkehastigheten
  • Endre CPU -klokkehastigheten ved å stille inn en forkalkning
  • Start og stopp 16-biters timere for timing av forskjellige ting
  • Slå på og/eller slå av perifere undersystemer: Analog til digitale omformere (ADC), Serielt perifert grensesnitt (SPI), To-leder grensesnitt (TWI/I2C), UART/USART. Nyttig for når du vil redusere strømforbruket til mikrokontrolleren eller for å aktivere visse funksjoner.
  • Skrevet i C ++ med gjenbrukbare objekter.

Denne instruksen vil gå gjennom installasjon, bruk og tilpasning av avrsh.

Trinn 1: Hva du trenger

Hva du trenger
Hva du trenger

Dette instruerbare krever ikke mye bortsett fra at du:

  • Ha en Arduino eller ATmega328P. Andre AVR -er kan fungere, men du må kanskje endre koden for å vise alle registre som er unike for MCU -en din. Navnene trenger bare å samsvare med det som er oppført i toppfilen som er unik for MCU -en din. Mange av registernavnene er de samme mellom AVR -er, så kjørelengden din kan variere ved porting.
  • Har en måte å koble til den serielle USART på Arduino/AVR. Systemet har blitt testet mest omfattende med AVR -terminalen, en Windows -app som gjør en seriell tilkobling via USB- eller COM -porten. Fungerer med Arduinos ved hjelp av USB-tilkoblingen og enhver AVR som bruker USB-BUB fra Moderndevice.com. Andre terminalalternativer inkluderer: Putty, minicom (Linux og FreeBSD), skjerm (Linux/FreeBSD), Hyperterminal, Teraterm. Jeg har funnet kitt og teraterm sende litt søppel når du kobler til, så din første kommando kan bli forvrengt.
  • Har fastvaren for AVR Shell installert og kjørende, som du kan laste ned fra disse sidene, eller alltid få den siste versjonen på BattleDroids.net.

For å installere AVR -terminalen, bare pakk den ut og kjør den. For å installere AVR Shell -fastvaren, last ned den og enten last opp hex -filen direkte og koble til den serielle terminalen på 9600 baud, eller kompiler den selv med "make" og deretter "make program" for å laste opp hex. Vær oppmerksom på at du kanskje må endre AVRDUDE -innstillingene for å gjenspeile COM -porten. Merk: PROGMEM -attributtet er ødelagt i den nåværende AVR GCC -implementeringen for C ++, og dette er en kjent feil. Hvis du kompilerer det, kan du forvente å få mange advarselsmeldinger som sier "advarsel: bare initialiserte variabler kan plasseres i programminneområdet." I tillegg til å være irriterende å se, er denne advarselen ufarlig. Siden C ++ på den innebygde plattformen ikke er høyt på AVR GCCs prioriteringsliste, er det ukjent når dette vil bli løst. Hvis du sjekker ut koden, vil du se hvor jeg har jobbet for å redusere denne advarselen ved å implementere mine egne attributtuttalelser. Ganske enkelt. Last ned og installer alt du måtte trenge for å snu siden, og la oss knekke.

Trinn 2: Lese og skrive registre

Lese og skrive registre
Lese og skrive registre

AVR -skallet ble først og fremst skrevet for å få tilgang til noen sensorer som jeg hadde koblet til min AVR. Det startet med en enkel LED og flyttet deretter til lyssensorer, temperatursensorer og til slutt til to ultralydstransdusere. avrsh kan sette de digitale komponentene i disse sensorene ved å skrive til registrene som kontrollerer dem. Manipulering av AVR -registre mens du kjører For å få en liste over alle kjente registre på Arduino, skriver du inn:

skrive ut registre og du får en utskrift som ser slik ut

Jeg vet om følgende registre:

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 URG UR For å se hvordan de enkelte bitene er satt i et hvilket som helst register, bruker du katten eller ekkokommandoen

katt %GPIOR0 Her ber jeg kommandotolk om å vise, eller ekko, innholdet i I/O -registeret for generell bruk #0. Legg merke til prosenttegnet (%) foran registernavnet. Du trenger dette for å indikere for skallet at dette er et reservert nøkkelord som identifiserer et register. Den typiske utgangen fra en ekkokommando ser slik ut

GPIOR0 (0x0) satt til [00000000] Utgangen viser navnet på registret, den heksadesimale verdien som finnes i registret og den binære representasjonen av registret (viser hver bit som en 1 eller 0). For å sette en bestemt bit i et hvilket som helst register, bruk "indeksen til" -operatoren . La oss for eksempel si at jeg vil ha den tredje biten til en 1

%GPIOR0 [3] = 1 og skallet vil gi deg et svar som indikerer at det er handling og resultatet

GPIOR0 (0x0) satt til [00000000] (0x8) satt til [00001000] Ikke glem prosenttegnet for å fortelle skallet at du jobber med et register. Vær også oppmerksom på at ved å sette den tredje biten, er det 4 biter inn fordi AVR-ene våre bruker en nullbasert indeks. Med andre ord, teller du til 3. bit teller du 0, 1, 2, 3, som er 4. plass, men 3. bit. Du kan fjerne litt på samme måte ved å sette litt til null. Ved å sette biter som dette kan du endre funksjonen til AVR -en din i farten. For eksempel, ved å endre CTC -tidsmatchingsverdien som finnes i OCR1A. Den lar deg også kikke inn på bestemte innstillinger som du må programmere inn i koden din, for eksempel UBBR -verdien for baudhastigheten din. Arbeide med DDRn, PORTn og PINn I/O -pinnene er også tilordnet registre og kan settes på nøyaktig samme måte, men det er laget en spesiell syntaks for å arbeide med denne typen registre. I kode er det en normal prosess for for eksempel å slå på en LED eller annen enhet som krever digital høy eller lav. Det krever at Data Direction Register angis for å indikere at pinnen er for utdata, og deretter skrive en 1 eller 0 til den bestemte biten i riktig port. Forutsatt at vi har en LED koblet til digital pin 13 (PB5) og vi vil slå den på, så gjør du dette mens AVR -en din kjører

sett pin pb5 outputwrite pin pb5 high Utgangen, i tillegg til å kunne se LED -en din, ville se slik ut

root@ATmega328p> sett pin pb5 output Sett pb5 for outputroot@ATmega328p> skriv pin pb5 høy Skriv logikk høy til pin pb5 "Root@ATmega328p>" er beskjeden fra skallet som indikerer at den er klar til å godta kommandoer fra deg. For å slå av LED -en, ville du ganske enkelt skrive en lav til pinnen. Hvis du vil lese den digitale inngangen fra en pin, bruker du kommandoen read. Ved å bruke vårt eksempel ovenfor

root@ATmega328p> les pin pb5Pin: pb5 er HØY Alternativt er det bare å ekko pin -registeret som styrer pin -porten. For eksempel, hvis vi har dip switcher koblet til digital pin 7 og 8 (PD7 og PD8), kan du sende kommandoen

ekko %PIND og skallet vil da vise innholdet i det registeret, og vise deg alle inngangs-/utgangstilstandene for tilkoblede enheter og om tilstanden til bryteren var på eller av.

Trinn 3: Lese og skrive sikringer

Lese og skrive sikringer
Lese og skrive sikringer

Sikringer er spesielle typer registre. De styrer alt fra klokkehastigheten til mikrokontrolleren din til hvilke programmeringsmetoder som er tilgjengelige til skrivebeskyttende EEPROM. Noen ganger må du endre disse innstillingene, spesielt hvis du lager et frittstående AVR-system. Jeg er ikke sikker på at du bør endre sikringsinnstillingene på Arduino. Vær forsiktig med sikringene dine; Du kan låse deg selv ute hvis du setter dem feil. I en tidligere instruks viste jeg hvordan du kan lese og sette sikringene dine ved hjelp av programmereren og avrdude. Her vil jeg vise deg hvordan du leser tilbake sikringene dine under kjøretid for å se hvordan MCU -en din faktisk har konfigurert dem. Vær oppmerksom på at dette ikke er kompileringstid-innstillingen du får fra definisjonene, men de faktiske sikringene mens MCU leser dem ved kjøretid. Fra tabell 27-9 i ATmega328P-databladet (databok, mer lik den) er bitene i Fuse Low Byte som følger:

CKDIV8 CKOUT SUT1 SUT0 CKSEL3 CKSEL2 CKSEL1 CKSEL0En interessant ting å merke seg er at med sikringer betyr 0 programmert og 1 betyr at den aktuelle biten er uprogrammert. Noe mot-intuitivt, men når du vet det, vet du det.

  • CKDIV8 setter CPU -klokken din til å bli delt med 8. ATmega328P kommer fra fabrikken som er programmert til å bruke den interne oscillatoren på 8MHz med CKDIV8 programmert (dvs. satt til 0) og gir deg en endelig F_CPU eller CPU -frekvens på 1MHz. På Arduino er dette endret siden de er konfigurert til å bruke en ekstern oscillator ved 16MHz.
  • CKOUT når den er programmert, sender CPU -klokken din ut på PB0, som er digital pin 8 på Arduinos.
  • SUT [1..0] angir oppstartstiden for AVR -en.
  • CKSEL [3..0] angir klokkekilden, for eksempel den interne RC -oscillatoren, den eksterne oscillatoren, etc.

Når du leser sikringene dine, blir den returnert til deg i heksadesimal. Dette er formatet du trenger hvis du vil skrive sikringene via avrdude. På min arduino, her er hva jeg får når jeg leser den nedre sikringsbyten:

root@ATmega328p> les lfuseLowere sikring: 0xffSå alle biter er satt til 1. Jeg gjorde samme prosedyre på en Arduino -klon og fikk samme verdi. Når jeg sjekket et av mine frittstående AVR-systemer, fikk jeg 0xDA, som er verdien jeg hadde satt et stykke tilbake da jeg konfigurerte brikken. Den samme prosedyren brukes for å kontrollere High Fuse Byte, Extended Fuse Byte og Lock sikringer. Kalibrerings- og signatur sikringsbyte er deaktivert i koden med et #if 0 forhåndsbehandlingsdirektiv, som du kan endre hvis du føler deg skrap.

Trinn 4: Andre kommandoer

Andre kommandoer
Andre kommandoer

Det er flere andre kommandoer som standard kommandotolker forstår at du kan finne nyttige. Du kan se alle de implementerte og fremtidige kommandoene ved å sende ut hjelp eller meny når du blir bedt om det. Jeg vil raskt dekke dem her, da de stort sett er selvforklarende. CPU -klokkefrekvensinnstillinger Du kan finne ut hva fastvaren din er konfigurert til å bruke som CPU -klokkeinnstillinger med fcpu -kommandoen:

root@ATmega328p> fcpuCPU Freq: 16000000Det er 16 millioner, eller 16 millioner herz, mer kjent som 16 MHz. Du kan endre dette i farten, uansett grunn, med klokkekommandoen. Denne kommandoen tar ett argument: prescaler som skal brukes når du deler klokkehastigheten. Klokkekommandoen forstår disse forhåndskalkulatorverdiene:

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

Bruke kommandoen:

klokke ckdiv2 når CPU -hastigheten din er 16MHz vil resultere i at klokkehastigheten blir endret til 8MHz. Hvis du bruker en forkalkning av ckdiv64 med en innledende klokkehastighet på 16MHz, vil det resultere i en siste klokkehastighet på 250 KHz. Hvorfor i all verden vil du gjøre MCU -en tregere? Vel, for det første, bruker en lavere klokkehastighet mindre strøm, og hvis du har MCU -en som går tom for et batteri i et prosjektkapsling, trenger du kanskje ikke at den skal kjøre i toppfart, og kan derfor redusere hastigheten og redusere strømforbruket, øker batterilevetiden. Hvis du også bruker klokken til noen form for timingproblemer med en annen MCU, for eksempel å implementere en UART -programvare eller noe slikt, kan det være lurt å sette den til en bestemt verdi som er lett å få en fin jevn baudhastighet med lavere feilrater. Slå på og slå av perifere undersystemer På samme måte som å redusere strømforbruket nevnt tidligere, kan det være lurt å redusere strømmen ytterligere ved å slå av noen av de innebygde eksterne enhetene du ikke bruker. Kommandotolken og skallet kan for øyeblikket slå på og slå av følgende eksterne enheter:

  • Analog-til-digital omformer (ADC). Denne eksterne enheten brukes når du har en analog sensor som gir data (som temperatur, lys, akselerasjon, osv.) Og må konvertere den til en digital verdi.
  • Serielt perifert grensesnitt (SPI). SPI-bussen brukes til å kommunisere med andre SPI-aktiverte enheter, for eksempel eksterne minner, LED-drivere, eksterne ADC-er, etc. Deler av SPI-en brukes til ISP-programmering, eller i det minste er pinnene, så vær forsiktig når du slår den av. hvis du programmerer via ISP.
  • To-leder grensesnitt. Noen eksterne enheter bruker I2C-bussen til å kommunisere, selv om disse raskt blir erstattet av SPI-aktiverte enheter ettersom SPI har en større gjennomstrømning.
  • USART. Dette er ditt serielle grensesnitt. Du vil sannsynligvis ikke slå av dette hvis du er koblet til AVR via den serielle tilkoblingen! Imidlertid la jeg dette til her som et skjelett for overføring til enheter som har flere USART -er som ATmega162 eller ATmega644P.
  • alle. Dette argumentet til kommandoen powerup eller powerdown slår på alle nevnte eksterne enheter eller slår dem av med én kommando. Igjen, bruk denne kommandoen klokt.

root@ATmega328p> powerdown twi Powerdown av twi complete.root@ATmega328p> powerup twi Powerup av twi fullført.

Start og stopp timere Skallet har en innebygd 16-bit timer som er tilgjengelig for bruk. Du starter timeren med timer -kommandoen:

timer startog stopp timeren med stoppargumentet

timer stoppDenne timeren vil ikke komme i konflikt med den interne USART -timeren. Se koden for implementeringsdetaljer for USART -timeren, hvis den typen dristige detaljer interesserer deg

root@ATmega328p> timer start Started timer.root@ATmega328p> timer stop Forløpt tid: ~ 157 sekunder Autentisering Skallet kan lagre et passord på 8 tegn i EEPROM. Denne passordmekanismen ble opprettet for å støtte telnet -påloggingsfunksjonene, men kan utvides for å beskytte andre ting. For eksempel kan du kreve visse kommandoer, for eksempel å endre registerverdier, gjennom autentiseringsmekanismen. Sett passordet med passordkommandoen

root@ATmega328p> passwd blah Skriv rotpassordet til EEPROMAutoriser mot passordet (eller kreve autorisasjon programatisk gjennom koden) med auth -kommandoen. Vær oppmerksom på at hvis du prøver å endre rotpassordet og det allerede er et rotpassord, må du autorisere deg selv mot det gamle passordet før du kan endre det til et nytt passord

root@ATmega328p> passwd blinkyDu må autorisere deg selv først. root@ATmega328p> auth blahAuthorized.root@ATmega328p> passwd blinkySkriv nytt rotpassord til EEPROMSelvfølgelig må du laste avrsh.eep -filen hvis du sletter fastvaren for å få de gamle verdiene og variablene gjenopprettet. Makefile vil opprette EEPROM -filen for deg. Variabler Skallet forstår begrepet brukerdefinerte variabler. Koden begrenser dette til 20, men du kan endre det hvis du vil ved å endre definere MAX_VARIABLES i script.h. Du kan lagre hvilken som helst 16-biters verdi (det vil si et hvilket som helst tall opptil 65, 536) til en variabel som skal hentes tilbake senere. Syntaksen ligner på registre bortsett fra et dollartegn ($) brukes til å betegne variabler til skallet. List opp alle variablene dine med kommandoen print variables

Skriv ut variabler Brukerdefinerte variabler: Indeksnavn -> Verdi (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. Sett en variabel

$ newvar = 25 $ timeout = 23245Få verdien av en gitt variabel

root@ATmega328p> ekko $ newvar $ newvar 25Du kan se alle variablene du for øyeblikket har opprettet med utskriftskommandoen du allerede kjenner

Brukerdefinerte variabler: Indeksnavn -> Verdi (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): $ GRATIS $ -> 0 Fullfør.$ FREE $ -navnet indikerer bare at variabelplasseringen er gratis og ikke har blitt tildelt et variabelnavn ennå.

Trinn 5: Tilpasse skallet

Tilpasse skallet
Tilpasse skallet

Du står fritt til å hacke på koden og tilpasse den til dine egne behov, hvis du vil. Hvis jeg hadde visst at jeg skulle gi ut denne koden, ville jeg ha laget en egen kommandotolkeklasse og kommandostruktur og ganske enkelt iterert gjennom dette kallet en funksjonspeker. Det ville redusere mengden kode, men som det ser ut, analyserer skallet kommandolinjen og kaller den riktige skallmetoden. For å legge til dine egne egendefinerte kommandoer, gjør du følgende: 1. Legg til kommandoen din i analyselisten Kommandoparseren vil analyser kommandolinjen og gir deg kommandoen og eventuelle argumenter separat. Argumentene sendes som pekere til pekere, eller en rekke pekere, men du liker å jobbe med dem. Dette finnes i shell.cpp. Åpne shell.cpp og finn ExecCmd -metoden i AVRShell -klassen. Det kan være lurt å legge til kommandoen i programminnet. Hvis du gjør det, legger du til kommandoen i progmem.h og progmem.cpp. Du kan legge kommandoen til å programmere minne direkte ved hjelp av PSTR () -makroen, men du vil generere en annen advarsel om typen nevnt tidligere. Igjen, dette er en kjent feil som arbeider med C ++, men du kan omgå dette ved å legge til kommandoen direkte i progmem.* -Filene, slik jeg har gjort. Hvis du ikke har noe imot å legge til SRAM -bruken din, kan du legge til kommandoen som jeg har illustrert med kommandoen "klokke". Si at du ønsket å legge til en ny kommando som heter "newcmd." Gå til AVRShell:: ExecCmd og finn et praktisk sted å sette inn følgende kode:

ellers hvis (! strcmp (c, "newcmd")) cmdNewCmd (args);Dette vil legge til kommandoen din og kalle cmdNewCmd -metoden som du vil skrive i neste trinn. 2. Skriv din egendefinerte kommandokode I den samme filen legger du til den egendefinerte kommandokoden. Dette er metodedefinisjonen. Du vil fortsatt legge til erklæringen på shell.h. Bare legg den til de andre kommandoene. I forrige eksempel kan koden se omtrent slik ut

voidAVRShell:: cmdNewCmd (char ** args) {sprintf_P (buff, PSTR ("Kommandoen din er %s / r / n", args [0]); WriteRAM (buff);}Det er flere ting her. For det første er "buff" en matrisebuffer på 40 tegn i koden for din bruk. Vi bruker programminneversjonen av sprintf siden vi sender den en PSTR. Du kan bruke den vanlige versjonen hvis du vil, men sørg for at du ikke består formatet i en PSTR. Argumentene er også i args -arrayet. Hvis du skrev "newcmd arg1 arg2" kan du komme til disse argumentene med args [0] og args [1] abonnementene. Du kan passere maksimalt MAX_ARGS argumenter, som definert i koden. Du kan gjerne endre denne verdien når du kompilerer på nytt hvis du trenger mange flere argumenter for å bli sendt på en gang. WriteLine og WriteRAM er globale funksjoner som returnerer UARTs metoder med samme navn. Det andre argumentet til denne funksjonen er implisitt. Hvis du ikke sender noe, blir det skrevet en ledetekst etterpå. Hvis du sender en 0 som det andre argumentet, blir det ikke skrevet en melding. Dette er nyttig når du vil skrive flere separate strenger som skal sendes ut før ledeteksten blir returnert til brukeren. 3. La skallet utføre kommandokoden Du har allerede fortalt skallutføreren å utføre metoden cmdNewCmd når du konfigurerer den nye kommandoen, men legg den til i shell.h -filen for å få den forstått av skallobjektet. Bare legg den til under den siste kommandoen eller foran den første kommandoen, eller hvor som helst der inne. Og det er det. Kompil og last opp fastvaren til Arduino igjen, og din nye kommando er tilgjengelig fra skallet når du blir bedt om det.

Trinn 6: Oppsummering

Du bør vite hvordan du installerer og kobler til AVR/Arduino og får en direkte melding på din mikrokontroller som kjører. Du kjenner flere kommandoer som vil trekke kjøretidsdata fra MCU eller sette verdier inn i MCU i farten. Du har også blitt vist hvordan du legger til din egen tilpassede kode for å lage dine egne unike kommandoer til skallet for å tilpasse den til dine egne behov. Du kan til og med tømme kommandotolken slik at den bare inneholder de egendefinerte kommandoene dine, hvis det passer dine behov. Som en læringsprosess for å implementere din egen. Som alltid ser jeg frem til kommentarer eller forslag til hvordan dette kan forbedres! Ha det gøy med AVR!

Anbefalt: