Designa med diskret SPI Flash minne (5 / 7 steg)
Steg 5: Kod kod kod!
Jag skrev en skiss som tillåter mig att kommunicera med Uno via seriell TTY kommunikation via seriell bildskärmen (eller ens en Unix-prompt som du väl se). Detta är en bra metod för felsökning av ny maskinvara, som jag kan utfärda kommandon interaktivt.
Funktionen "serialEvent()" är en inbyggd motringning, anropas när något händer på Standard Serial objektet. Jag använder denna callback att konstruera en kommandosträng och ange en boolesk flagga (byte av byte byggandet av strängen är klar när callback läser som semikolon ";" från strömmen; Jag använder denna i stället för en ny rad eftersom det finns inget sätt att utfärda en newline från seriella monitor). När callback konstruerar strängen och flaggan, utför funktionen "loop()" en avkodare. Dekodern avgör vilken funktion som ska ringa baserat på kommandosträngen, analyserar eventuella ytterligare parametrar från kommandosträngen och anropar funktionen.
Varje funktion är i huvudsak en wrapper runt en lägsta-nivå-genomförande av ett WinBond SPI funktionella timing diagram. Jag använde en wrapper så att lågnivåfunktionerna förbli generiska: Jag kan använda dem igen i andra skisser med en enkel klipp-och-klistra. Plus, omslaget skrivs ut lite feedback till användaren, vilket är mycket användbart för debug.
Skärmbilden ovan visar en interaktiv session med seriell bildskärmen. Jag har utfärdat fyra kommandon, "get_jedec_id;", "read_page 0;", "write_byte 0 2 8.", och "read_page 0;" Du förstår faktiskt inte kommandona (serial bildskärmen har inte ett eko, och jag inte ut den exakta kommandot... Jag förmodligen borde ha), men du ser svaret. Det bör vara mest tydlig när jag läsa/skriva/läsa sida 0. "Read_page," kommando bara dumpar den angivna sidan (i decimalform). "write_byte;" funktionen är lite konstigt, eftersom parametrarna ange ett sidnummer, en förskjutning i den sidan, och sedan byten. Eftersom det finns ingen native 32-bitars register i 16-bitars Atmega, jag brydde mig inte göra logiska fysiska översättning, men du måste du överväga denna översättning någon gång. Hur som helst, märka att den tredje byten av sida noll nu "08h".
Jag kunde har också utfärdat "chip_erase;" och sedan "read_page 0;" att illustrera en radera-cykel, men förhoppningsvis du får bild.
Låg nivå funktioner börjar med "_", och heter "_read_page" eller "_write_page" eller "_erase_chip". Dessa funktioner sekvens uttryckligen alla SPI kommandon finns i databladet timing diagram. Varje funktion slutar med en uppmaning att "not_busy()" förhindrar körning från förfarandet innan chip har avslutat sin interna verksamhet.
Redigera (11-MAR-2014): det fanns ett problem med funktionen _read_page låg nivå, jag hade glömt att dra CS hög innan du drar det låg i början av funktionen, så övriga funktioner. Detta innebär att om _read_page är den första funktionen som du kallar, CS kan inte redan vara hög, så utan en giltig /CS 1 -> 0 övergången _read_page fungerar inte korrekt, första gången det kallas. Andra gången det skulle fungera bra eftersom det lämnar /CS som 1. Litet men irriterande bugg.