Indholdsfortegnelse:

I2C Bus til ATtiny og ATmega: 8 trin
I2C Bus til ATtiny og ATmega: 8 trin

Video: I2C Bus til ATtiny og ATmega: 8 trin

Video: I2C Bus til ATtiny og ATmega: 8 trin
Video: AVR microcontroller i2c 2024, Juli
Anonim
I2C Bus til ATtiny og ATmega
I2C Bus til ATtiny og ATmega

Jeg elsker Atmel AVR mikrokontrollere! Siden jeg byggede Ghetto Development System beskrevet i denne Instructable, har jeg ikke haft en ende på sjov at eksperimentere med AVR ATtiny2313 og især ATmega168. Jeg gik endda så langt som til at skrive en Instructable om brug af switches som input og udvidede Ghetto Development System -konceptet til CPLDs. I løbet af et nyligt projekt havde jeg brug for flere switches til indstilling af kontrolværdier. AVR'erne havde ikke nok I/O -ben, så jeg var nødt til at tænke på noget. Jeg kunne have prøvet et komplekst inputsystem med et tastatur og en skærm, men ATtiny2313 ville være løbet tør for ressourcer. Heldigvis har Atmel givet en løsning på dette problem ved at inkludere en grænseflade, der kan linke til yderligere chips (f.eks. Hukommelse eller I/O -porte) med en simpel to -tråds grænseflade. Det er rigtigt, ved kun at bruge to I/O -ben på en AVR kan vi også få adgang til mange ekstra I/O -ben og andre ressourcer. Denne totrådsgrænseflade er formelt kendt som den Inter-Integrated Circuit-bus eller bare I2C-bussen og blev opfundet af NXP, da den stadig var Philips Semiconductors. Hvis du læser denne Instructable, har du sikkert hørt om I2C -bussen og måske endda have brugt den på en PIC eller anden mikrokontroller. Selvom det konceptuelt er meget simpelt og understøttet af hardware -ressourcer på AVR'erne, er softwaredrivere stadig nødvendige for at bruge I2C -bussen. Atmel leverer applikationsnotater (se ressourcerne senere i denne instruktionsbog), men disse er ufuldstændige og viser ikke eksempler ud over at kommunikere med en anden AVR -enhed. Det er ikke formålet med denne instruktion at lære nogen at oprette I2C -drivere til AVR'er. Jeg vil snarere levere udvidede versioner af Atmel -driverne til ATtiny2313- og ATmega168 -enheder, jeg vil forklare de krav og begrænsninger, der gælder, når du bruger disse, og jeg vil vise dig eksempler på I2C -enheder. Når du har gennemgået denne Instructable, vil du kunne bruge I2C -bussen med succes i dine AVR -projekter. Det er klart, at du kan ignorere driverne til enten bittesmå eller MEGA, hvis du kun er interesseret i en af dem. For dem, der er interesseret i at lære mere om I2C -bussen, giver jeg links til passende materiale.

Trin 1: Hvad er alt dette I2C -ting alligevel?

Hvad er alt dette I2C -ting alligevel?
Hvad er alt dette I2C -ting alligevel?
Hvad er alt dette I2C -ting alligevel?
Hvad er alt dette I2C -ting alligevel?
Hvad er alt dette I2C -ting alligevel?
Hvad er alt dette I2C -ting alligevel?
Hvad er alt dette I2C -ting alligevel?
Hvad er alt dette I2C -ting alligevel?

I2C-bussen er en enkel totrådsforbindelse, der kan forbinde flere enheder sammen og give dem mulighed for at udveksle data. I sin enkleste form er der en master -enhed, der kommunikerer til flere slaveenheder. Alle enheder er forbundet parallelt med de to ledninger i I2C -bussen. De to ledninger er kendt som SCL og SDA. SCL er urlinjen og styres af master -enheden. SDA er den tovejs datalinje. For at overføre data sender masteren en slaveadresse kombineret med et en bit læse/skrive -flag. Hvis der ønskes en skrivning, vil masteren fortsat sende data til den adresserede slave. Hvis der anmodes om en læsning, svarer slaven med data. For at koordinere transaktioner manipuleres SCL- og SDA -linjer af masteren og slaven for at signalere flere forhold. Disse inkluderer START, STOP, ACK (bekræft) og NAK (ingen bekræftelse). Detaljerne i disse betingelser håndteres af chaufførerne. De sande nørder blandt jer kan lære alle detaljerne i linkene i slutningen af denne instruktionsbog. De elektriske krav er ret enkle. Mesteren og slaverne skal bruge samme niveau for Vcc, grundene skal forbindes, og SCL- og SDA -linjerne skal trækkes op til Vcc. Værdien af pull-up-modstandene bestemmes præcist ved en beregning baseret på den samlede kapacitans på bussen, men kan praktisk talt være stort set enhver værdi mellem 1,8K og 10K. Jeg starter med 5.1K og bruger lavere værdier, indtil det virker. Dette er normalt ikke et problem, medmindre du har mange enheder eller lange ledninger mellem enheder. Den nominelle datahastighed på I2C -bussen er 100Kbits/sekund. Priser på 400Kbits/sekund, 1Mbits/sekund og derover er også mulige, men understøttes ikke af driverne i denne Instructable. Alle I2C -enheder fungerer med 100Kbits/sekund. ATtiny2313 og ATmega168 implementerer hver I2C -bus forskelligt. ATtiny2313 anvender Universal Serial Interface (USI) hardware - som også kan bruges til SPI -bussen. ATmega168 har dedikeret hardware til I2C -bussen kendt som Two Wire Interface (TWI). Når driverne er skrevet, er disse forskelle for det meste gennemsigtige for brugeren. En væsentlig forskel er i softwaren: ATmega168 I2C -driveren er interruptdrevet, mens den for ATtiny2313 ikke er det. Det betyder, at et ATmega168 -program ikke behøver at vente på, at I2C -dataoverførsler finder sted, men kun skal vente, før der påbegyndes en anden overførsel, eller indtil der kommer data fra en læseoperation. Eksemplerne og diskussionen, der skal følges, bør gøre dette klart. I2C -adresser er 7 bits lange, så op til 127 enheder kan være på bussen, hvis hver har en unik adresse. Som vist i figuren flyttes denne 7 bit adresse en bit til venstre, og den mindst signifikante bit bruges til at markere en læsning eller skrivning af enheden på adressen. Således er den komplette slave -adresse en 8 bit byte. Den faktiske adresse bestemmes delvist internt til enheden og kan ikke ændres (4 mest betydningsfulde bits), og delvist bestemmes af bits, der kan forbindes til enhedsstifter (3 mindst signifikante bits), der kan bindes højt eller lavt for at indstille en bestemt adresse. Det lyder forvirrende, men et eksempel vil gøre dette klart. PCA8574A -databladet viser, at de fire mest betydningsfulde bits i I2C -adressen altid vil være 0111. De næste tre bits bestemmes af indstillingerne på ben AD0, AD1 og AD2. Disse ben kan bindes til jorden eller til den positive spændingsforsyning (5 volt) for at repræsentere henholdsvis 0 eller 1. Så rækkevidden af mulige adresser er 38 til 3F hexadecimal, som vist i den anden figur fra PCA8574 -databladet. Så ved at ændre adressebitindstillingerne kan op til 8 PCA8574A'er være på I2C -bussen på samme tid. Hver vil kun svare på sin specifikke slaveadresse. Hvis der er brug for endnu flere I/O -porte, kan PCA8574 bruges. Den eneste forskel mellem PCA8574 og PCA8574A er, at I2C -slaveadresseområdet for PCA8574 er 20 til 27 hexadecimal. Det kan være forvirrende at bestemme adressen på en given enhed, da nogle datablade anser læse/skrive -bit for at være en del af adresse. Læs databladet omhyggeligt, og husk, at slaveadressen bliver 7 bit lang. Læs/skriv -bit skal behandles separat. Igen vil et eksempel hjælpe. Dataarket for 24C16 EEPROM, vi vil eksperimentere med, siger, at de første (mest signifikante) fire bits i slaveadressen er 1010. De næste tre bits kan bestemmes af A0, A1 og A2; men bemærk databladet også dækker 24C01 til 24C08, som er mindre EEPROM'er. Figuren fra databladet viser, at indstillingerne for disse adressebit ignoreres, når størrelsen stiger og ignoreres fuldstændigt for 24C16. Det vil sige, de sidste tre bits er ligegyldige, og 24C16 bruger virkelig alle I2C -slaveadresser 50 til 57 hexadecimal. Udvalget af slaveadresser vil faktisk adressere forskellige sektioner inden for 24C16. De første 256 bytes er på adressen 50h, de næste 256 ved 51h og så videre op til de sidste 256 bytes på 57h - i alt 2K bytes. Da adressen på PCF8570 RAM, vi også eksperimenterer med, er i dette område, kan 24C16 og PCF8570 ikke bruges sammen.

Trin 2: Bestil nogle I2C -enheder

Nu hvor du ved lidt om I2C -bussen og vil bruge den, hvorfor ikke bestille nogle I2C -enheder til at eksperimentere med nu, så de kan være på vej til dig, mens du gør softwaren klar? Egnede enheder inkluderer en I/ O Interface Expander (min favorit), en statisk ram og en EEPROM. Der er meget mere, men disse er en god start. De AVR -processorer, vi vil bruge, er ATtiny2313 og Atmega168 (brugt i Arduino). Hvis du er ny inden for disse, så tag et kig på denne fantastiske Instructable for at lære om dem og bygge dit Ghetto Development System. Skematikken over ATmega168 i den foreliggende Instructable viser, hvordan man implementerer Ghetto Development System til denne processor. Kablet til parallelporten er det samme som for ATtiny2313. (Jeg har ikke prøvet USB -versionen af Ghetto Development System, så jeg er ikke sikker på, hvordan I2C -bussen får adgang til den. Samme for Arduino.) Her er Digikey -varenumre. Port Expander: IC I2C I/O EXPANDER 568-4236-5-NDRam: IC SRAM 256X8 W/I2C 568-1071-5-NDEEPROM: IC EEPROM SERIAL 16K CAT24C16LI-G-ND

Trin 3: I2C -drivere

Her er beskrivelserne af driverfunktionerne til I2C -bussen. Disse blev udviklet ved hjælp af Atmel Apps Notes til at begynde med. Jeg kunne ikke have gjort dette uden dem som en base at bygge på. Udviklingen blev udført ved hjælp af WinAVR og gcc C -kompilatoren. Begrænsninger i urfrekvens er beskrevet nedenfor for hver processor. Da jeg ikke er i stand til at teste alle kombinationer af processorsmag / urfrekvens, vil jeg bare holde mig til, hvad jeg faktisk kan teste og prøve at angive begrænsninger og begrænsninger. Her er driverfunktionerne og hvordan de bruges. Se eksemplerne for flere detaljer og for at se de funktioner, der er i brug i komplette programmer. Til ATtiny2313: Urkrav: Driverne er designet til en urfrekvens på 1MHz (standardhastigheden) for ATtiny2313. Hvis du vil køre med andre hastigheder, skal du justere konstanter i driverne. Send mig en e -mail, hvis du har brug for hjælp til dette. Du kan også få nogle tip fra noterne fra Atmel -apps i linkene i ressourcetrinnet. USI_TWI_Master_Initialise () Denne funktion initialiserer USI -hardware til drift i I2C -tilstand. Kald det en gang i starten af dit program. Det returnerer ugyldigt, og der er ingen argumenter. USI_TWI_Get_State_Info () Denne funktion returnerer I2C -fejloplysninger og bruges, hvis der opstod en fejl under en I2C -transaktion. Da denne funktion kun returnerer en fejlkode, bruger jeg funktionen TWI_Act_On_Failure_In_Last_Transmission (TWIerrorMsg) til at blinke en fejl -LED. Fejlkoderne er defineret i USI_TWI_Master.h. Sådan kaldes det: TWI_Act_On_Failure_In_Last_Transmission (USI_TWI_Get_State_Info ()) USI_TWI_Start_Read_Write () Denne funktion bruges til at læse og skrive enkeltbytes til I2C -enheder. Det bruges også til at skrive flere bytes. Der er 6 trin til at bruge denne funktion. 1) Angiv en meddelelsesbuffer i dit program for at holde slaveadressen og databyten, der skal sendes eller modtages. unsigned char messageBuf (MESSAGEBUF_SIZE); 2) Sæt Slave -adressen som den første byte i bufferen. Skift den en bit til venstre og ELLER i Læs/skriv -bit. Bemærk, at læs/skriv -bit vil være 1 for en læsning og 0 for en skrivning. Dette eksempel er til en Læs. messageBuf (0) = (TWI_targetSlaveAddress << TWI_ADR_BITS) | (SAND << TWI_READ_BIT); 3) Når du skriver, skal du sætte den byte, der skal skrives, til det næste sted i bufferen. 4) Ring til funktionen USI_TWI_Start_Read_Write med meddelelsesbufferen og meddelelsesstørrelsen som argument.temp = USI_TWI_Start_Read_Write (messageBuf, 2); 5) The returneret værdi (temp i dette tilfælde) kan testes for at se, om der opstod en fejl. I så fald håndteres det som diskuteret ovenfor. Se eksempler i programmerne. 6) Hvis der blev anmodet om en læsning, vil byte -læsningen være på det andet sted i bufferen. Hvis der skal skrives flere bytes (f.eks. Til en hukommelsesenhed), kan den samme rutine bruges. Opsætning af bufferen og opkald til rutinen er lidt anderledes. Den anden byte i bufferen vil være starthukommelsesadressen, der skal skrives til. De data, der skal skrives, vil være i efterfølgende bytes. Beskedstørrelsen er størrelsen inklusive alle gyldige data. Så hvis der skal skrives 6 bytes, vil meddelelsesstørrelsen være 8 (slaveadresse + hukommelsesadresse + 6 byte data). USI_TWI_Start_Random_Read () Denne funktion bruges til at læse flere bytes fra en I2C -enhed, typisk er det kun meningsfuldt for en slags hukommelse. Brug af denne rutine ligner meget den tidligere rutine, med to undtagelser. Indstillingen af Read/Write bit er ligegyldig. Hvis du kalder denne rutine, vil det altid medføre en Read -operation. Meddelelsen Størrelse skal være 2 plus antallet af bytes, der skal læses. Hvis der ikke er opstået fejl, vil dataene være i bufferen, der begynder på det andet sted. For ATmega168: Urkrav: drivere er designet til en urfrekvens på 4MHz for ATmega168. Eksempelkoden viser, hvordan du indstiller denne urfrekvens. Hvis du vil køre med andre hastigheder, skal du justere konstanter i driverne. Send mig en e -mail, hvis du skal gøre dette. TWI_Master_Initialise () Denne funktion initialiserer TWI -hardware til drift i I2C -tilstand. Kald det en gang i starten af dit program. Det returnerer ugyldigt, og der er ingen argumenter. Sørg for at aktivere afbrydelser ved at ringe til swi () efter initialisering. TWI_Get_State_Info () Denne funktion returnerer I2C -fejloplysninger og bruges, hvis der opstod en fejl under en I2C -transaktion. Da denne funktion kun returnerer en fejlkode, bruger jeg funktionen TWI_Act_On_Failure_In_Last_Transmission (TWIerrorMsg) til at blinke en fejl -LED. Fejlkoderne er defineret i TWI_Master.h, men er ændret til signalering på en fejl -LED. Se eksempelkoden for detaljer. Sådan kalder du det: TWI_Act_On_Failure_In_Last_Transmission (TWI_Get_State_Info ()) Bemærk, at fejlkontrol udføres ved at sikre, at I2C -transaktionen er fuldført (funktion beskrevet nedenfor) og derefter teste lidt i det globale statusord. TWI_Start_Read_Write () TWI_Start_R () to funktioner fungerer på samme måde som de tilsvarende funktioner beskrevet ovenfor, men med få undtagelser. De returnerer ingen fejlværdier. Læsede data overføres ikke til bufferen. Dette gøres med den funktion, der beskrives næste gang. Når der ringes til TWI_Start_Random_Read, skal meddelelsen Size være antallet af anmodede databyte plus en, ikke to. I2C -driveren til ATmega168 drives afbrudt. Det vil sige, at I2C -transaktionerne startes og derefter udføres uafhængigt, mens hovedrutinen fortsætter med at køre. Når hovedrutinen ønsker data fra en I2C -transaktion, som den startede, skal den kontrollere, om dataene er tilgængelige. Situationen er den samme for fejlkontrol. Hovedrutinen skal være sikker på, at I2C -transaktionen er gennemført, før der kontrolleres for fejl. De to næste funktioner bruges til disse formål. TWI_Transceiver_Busy () Ring til denne funktion for at se, om en I2C -transaktion er gennemført, før der kontrolleres for fejl. Eksempelprogrammerne viser, hvordan du bruger dette. TWI_Read_Data_From_Buffer () Kald denne funktion for at overføre data fra I2C -driverens modtagelsesbuffer til meddelelsesbufferen. Denne funktion sikrer, at I2C -transaktionen er gennemført, før dataene overføres. Selvom en værdi returneres af denne funktion, finder jeg det mere pålideligt at kontrollere fejlbitten direkte. Sådan kalder du det. Meddelelsen Størrelse skal være en større end antallet af ønskede databit. Dataene vil være i messageBuf fra den anden location.temp = TWI_Read_Data_From_Buffer (messageBuf, messageSize);

Trin 4: Lad os bygge

Lad os bygge!
Lad os bygge!
Lad os bygge!
Lad os bygge!
Lad os bygge!
Lad os bygge!
Lad os bygge!
Lad os bygge!

Start med at downloade filen I2C Schematics.zip. Du vil måske oprette en I2C -mappe i dit arbejdsområde for at indeholde skemaerne og eksemplerne på programfiler. Pak skemaerne ud i denne mappe. Du finder en mappe kaldet I2C Schematics. Åbn filen med navnet lille I2C.pdf. Denne skematisk viser ATtiny2313 Ghetto Development System og PCA8574A I/O Port Expander (har den store stiplede boks omkring sig). Port Expander kredsløbet er bygget på et brødbræt. Tag et kig på billederne for at se, hvordan disse kredsløb ser ud. De er virkelig temmelig enkle. ATtiny2313 -delen af skematikken er bare Ghetto Development System med tre blinkenlights (LED1, 2 og 3, plus R4, 5 og 6) og en trykknap (S1) tilsluttet det, plus en yderligere detaljer. Denne detalje er tilføjelsen af jumpere (JP4, 5 og 6), som kan fjernes for at muliggøre forbindelse af I2C -bus SCL- og SDA -linjer. Jumperne skal være på plads til programmering og derefter fjernes, så SCL og SDA kan tilsluttes. Billederne viser springerne på plads og fjernet. Placering af disse jumpere er op til dig, du skal bare sætte dem på dit Ghetto Development System, hvis du vil bruge I2C -bussen. I2C -bussen skal afbrydes, og springerne skal placeres til programmering. Bemærk, at du kun virkelig skal bekymre dig om JP4 og JP6 for I2C -bussen. Indsæt JP5, hvis du tror, du nogensinde vil bruge SPI -bussen. Det er meget enkelt at brede PCA8574A I/O Port Expander. Giv Vcc (+5 volt) og Gnd (jord) forbindelser og tilslut AD0, 1 og 2 til jord (gør I2C slave -adressen 38 hex). Tilslut derefter 4 blinkenlights og 4 DIP switches. (Hvis du ikke har DIP-switche, kan du bare bruge ledninger. Binde til jorden eller lade flyde til henholdsvis signal til eller fra.) Tilslut til sidst pull-up-modstandene (R11 og 12) fra SDA og SCL til Vcc. Disse er vist som 3,3K, men enhver værdi fra 1,8K til 5,1K burde fungere (måske op til 10K, men jeg har ikke prøvet det). Når du har programmeret ATtiny2313, kan du fjerne jumpere og tilslutte SDA og SCL til test. Nu til ATmega168. Den eneste rynke her er, at du muligvis ikke har bygget et Ghetto Development System til denne processor. Hvis det er tilfældet, viser skematikken jeg giver (MEGA I2C.pdf) dig hvordan. Dette er kun en permutation af ATtiny2313 -versionen. Hvis du planlægger fremad, kan du sikre dig, at dit programmeringskabel passer til begge systemer. Den største forskel er tilføjelsen af C2 og C3. Se billederne for placering af disse, de skal være meget tæt på chippen; en af dem er faktisk under chippen. Disse hjælper især med at holde støj ude af den analoge til digitale omformer. Du behøver ikke at sætte jumpere i, medmindre du planlægger at bruge SPI -bussen, da de ikke er nødvendige for I2C -bussen på denne chip. Bemærk, at PCA8754A brødbrættet vil være uændret. Du tilslutter bare SDA og SCL, og du er væk! Let, hva '?

Trin 5: Lad os kode og teste

Lad os kode og teste!
Lad os kode og teste!
Lad os kode og teste!
Lad os kode og teste!
Lad os kode og teste!
Lad os kode og teste!

Det er tid til at bygge driverne og eksempelprogrammerne. Vi starter med ATtiny2313 og PCA8574A brødbrættet, som vi lige har bygget. Download filen I2C.zip til dit I2C -arbejdskatalog, og pak den ud. Du får en ny mappe kaldet I2C. I den finder du USI I2C (til ATtiny2313) og TWI I2C (til ATmega168). I USI I2C finder du mappen I_O Port. Denne mappe indeholder koden til vores første eksempelprogram og USI I2C -driverne. Brug WinAVR til at kompilere og indlæse koden i ATtiny2313. Tag en dyb indånding, og tænd for strømmen. Her er hvad du kan forvente: Ved tænding blinker LED 1 på port PD6 på ATtiny2313 to gange. Intet andet vil ske, før du trykker på knappen (S1). Hver gang der trykkes på knappen, læses kontakterne, og deres indstilling vises på de lysdioder, der er tilsluttet PCA8574A. Skift værdien af kontakterne, tryk på knappen, og lysdioderne skal ændre sig. Bliv ved med at gøre dette, indtil du kommer over spændingen ved at se det virke. Hvis (gud forbyde!) Tingene ikke fungerer som forventet, skal du omhyggeligt kontrollere dine ledninger. I2C -fejl signaleres af blink på LED3 (PD4) og betyder sandsynligvis, at du skal kontrollere, at SDA og SCL er forbundet til de korrekte stifter og er trukket korrekt op. Hvis tingene stadig ikke virker, kan du læse resten af dette afsnit for at lære om fejlfinding. Gå nu tilbage, og lad os se på koden. Åbn filen USI_I2C_Port.c. Dette er koden til eksempelprogrammet. (USI_TWI_Master.c og USI_TWI_Master.h indeholder driverne - du kan ignorere dem, medmindre du er nysgerrig.) Brug eksemplet til at guide dine egne I2C -applikationer. For det meste viser programmet dig, hvordan du initialiserer og bruger I2C -drivere, herunder indstilling op slave -adressen og resten af meddelelsesbufferen, og få dataene ud af den. Du vil også se, hvordan jeg debounce knappen og konfigurere mens loop. Der er et par detaljer om programmet værd at nævne. Bemærk, at dataene fra switcherne er inverterede, før de skrives til lysdioderne på Port Expander. Bemærk også, at inputporte på Port Expander skal skrives som High for at få dem til at fungere korrekt. Disse detaljer er beskrevet i PCA8574A -databladet. Læs altid databladene omhyggeligt! Af mere interesse er brugen af betinget fejlfinding. Nær starten af programfilen er sætningen // #define DEBUG og sprøjtet i hele koden er #ifdef DEBUG -sætninger. Så længe DEBUG ikke er defineret (de to skråstreger gør linjen til en kommentar og forhindrer den i at blive defineret), vil koden i #ifdef til #endif -sætningerne ikke blive samlet. Men hvis tingene ikke fungerer, som du forventer, skal du kompilere og genindlæse koden med #define DEBUG uden kommentarer. Du får meget flere blink på lysdioderne, som du kan afkode for at følge udførelsen af dit program og hjælpe dig med at finde præcis, hvor tingene går galt. Faktisk anbefaler jeg dig at prøve dette bare for at se, hvad der sker. Det, du vil se, er, at LED 2 (på PD5) blinker, når udførelsen skrider frem gennem programmet. Den værdi, der læses fra kontakterne, blinker på LED 1 (PD6), før den vises på Port Expander LED'erne. Du bør være i stand til at spore programmet, mens det kører ved hjælp af disse lysdioder. Vi arbejder derefter med ATmega168; spring dette afsnit over, hvis du kun er interesseret i ATtiny2313. Stadig hos mig? Godt. Flyt til mappen TWI_I2C, skift dit arbejdskatalog til IO_Port, og kompilér og indlæs TWI_I2C_Port.c i ATmega168. Afbryd SDA- og SCL -linjer fra ATtiny2313, og slut dem til ATmega168. Tilslut strøm og jord, og tænd for strømmen. Operationen skal være den samme! Spil indtil spændingen aftager, så lad os se på koden. Åbn TWI_I2C_Port.c. Koden er næsten identisk bortset fra fejlhåndtering og imødekommende interruptdrevne drivere. Her er forskellene: Bemærk, at uret skal indstilles til 4MHz for, at I2C -bussen fungerer korrekt. Seien (); sætning tænder afbrydelser efter initialisering af I2C -driverne. For at kontrollere for fejl testes en bestemt statusbit. Under en læsning skal TWI_Read_Data_From_Buffer -funktionen kaldes for at overføre de læste data til meddelelsesbufferen. Under en skrivning, mens (TWI_Transceiver_Busy ()) skal bruges til at være sikker på, at overførslen er fuldført, før der kontrolleres for fejl. Disse to sidste funktioner er beskrevet ovenfor i beskrivelsen af driverne. Bortset fra det er koden stort set den samme som for ATtiny2313. DEBUG fungerer også det samme, hvis du vil eksperimentere med det.

Trin 6: Brug af I2C -hukommelse

Brug af I2C -hukommelse
Brug af I2C -hukommelse
Brug af I2C -hukommelse
Brug af I2C -hukommelse
Brug af I2C -hukommelse
Brug af I2C -hukommelse
Brug af I2C -hukommelse
Brug af I2C -hukommelse

Nu hvor vi har lært at bruge I2C -bussen til at læse og skrive en I/O -portudvidelse, lad os gå videre til at bruge I2C -hukommelser, både RAM og EEPROM. Hovedforskellen er, at flere bytes kan læses til eller skrives fra hukommelser med en enkelt I2C -kommando. For at blive klar til disse eksperimenter skal vi ændre hardware lidt og bygge et par nye kredsløb på brødbrættet. Behold Port Expander -kredsløbet, da vi vil bruge det til at vise nogle hukommelsesværdier. Fjern DIP -switchene fra PCA8574A, og sæt blinkenlights på disse ben. Hvis du ikke har nok blinklys, skal du flytte dem på P4 til og med P7 over til P0 gennem P3. (Værdierne, der skal vises, er små nok.) Se nu på den skematiske I2C Ram.pdf og tilslut PCF8570 på brødbrættet. Se også billedet. Sørg for at binde stift 7 til Vcc. Kør ledninger til SDA og SCL fra PCA8574A. Der kræves ingen ekstra pull-up-modstande. Hvis du også er interesseret i EEPROM, skal du bygge dette kredsløb også ved hjælp af I2C EEPROM.pdf til 24C16, men vær advaret om, at eksemplet bruger ATmega168. Dette kredsløb er virkelig simpelt. Som diskuteret ovenfor skal adressebits ignoreres. Tilslut bare strøm og jord. Tilslut ikke SDA og SCL endnu, da vi ikke er færdige med at eksperimentere med Ram. Vi starter vores hukommelseseksperimenter med ATtiny2313 forbundet til PCA8574A Port Expander og til PCF8570 Ram. Programmet vil skrive nogle numre til Ram'en, derefter læse dem tilbage og vise dem på Port Expander. Skift dit arbejdskatalog til RAM under USI I2C. Brug make -filen til at kompilere og downloade USI_I2C_RAM.c. Bemærk, at I2C -driverfilerne er identiske med dem, vi brugte tidligere. Tilslut strømmen, og du skal se et enkelt blink på LED 1 (PD6). Data skrives til de første 4 byte hukommelse. Tryk på knappen, og to bytes læses tilbage og vises. Du bør se et LED -lys på Port Expander (P0), en pause på to sekunder, derefter to LED'er (P0 og P1). Yderligere to sekunders pause, og lysdioderne skulle slukke. Tryk på knappen igen for at starte sekvensen forfra. Debugging ligner metoden beskrevet ovenfor. Lad os se på koden. Åbn USI_I2C_RAM.c. Det skal se nogenlunde ud som den tidligere kode. De største forskelle er detaljerne i læse- og skrivehukommelse. Se på den måde, meddelelsesbufferen indlæses før det opkald, der rent faktisk skriver. Den første byte er slave -adressen med læse/skrive -bit indstillet korrekt. Men den næste byte er hukommelsesadressen, hvor data skal startes. Derefter kommer de faktiske databyte, som vil blive indlæst sekventielt i hukommelsen fra den adresse, vi har angivet. Vi angiver meddelelsesstørrelsen som 6. Så vi begynder at skrive på adressen 00 og skriver værdierne 01, 03, 02 og 06 i hukommelsesstederne 00 til 03. For at læse dataene tilbage fra hukommelsen skal vi bruge funktionen USI_TWI_Start_Random_Read. Meddelelsesbufferen får slaveadressen i den første byte og startadressen i den anden byte. Ring derefter til funktionen med beskedstørrelsen indstillet til antallet af bytes, der skal læses plus 2. Bemærk, at læse/skrive -bit ikke er ligegyldigt, da en læsning vil blive foretaget uanset. De returnerede data starter på den anden placering i meddelelsesbufferen. Når dataene er læst ind, vendes de til visning på Port Expander og skrives en byte ad gangen til den med en pause mellem værdierne. Endelig er Port Expander -lysdioderne slukket. Skrifterne til Port Expander er identiske med, hvad der blev gjort i de foregående eksempler. For sjov kan du fjerne kommentaren fra #define DEBUG -sætningen som ovenfor og se masser af blinkende lysdioder. Skyllet af spænding efter endnu et vellykket eksperiment, lad os gå til ATmega168 og en EEPROM. Skift dit arbejdskatalog til EEPROM under TWI I2C. Brug make -filen til at kompilere og downloade TWI_I2C_EEPROM.c. Bemærk, at I2C -driverfilerne er identiske med dem, vi tidligere brugte til PCA8574A. For at teste programmet, skal du afbryde ATtiny2313 og tilslutte ATmega168. Lad I2C -bussen være tilsluttet Ram og tænd. Resultaterne er forskellige, da vi nu skriver og læser flere data. LED 1 på PD7 skulle blinke ved initialisering. Tryk på knappen, og data læses tilbage fra hukommelsen og vises. Lysdioderne på PCA8574 skal blinke i følgende rækkefølge: P1, P0 & P2, (alle slukket), P0 & P1, P1 & P2. Til sidst skulle port -lysdioderne alle slukke. Tryk på knappen igen for at gentage dette. Åh, men vent, siger du. Er dette program ikke til EEPROM? Da vi får adgang til en hukommelsesenhed på den samme I2C -adresse, fungerer det samme program for både Ram og EEPROM. Sluk, og flyt SDA og SCL fra ram til EEPROM, og kør programmet igen. Det skal fungere nøjagtig det samme. Bemærk, at EEPROM og Ram ikke kan forbindes til I2C -bussen på samme tid, da de deler den samme adresse. (De kloge blandt jer kan overveje at ændre de programmerbare adressebit på Ram'en, men det virker stadig ikke. 24C16 bruger hele adresseblokken, der kan programmeres til Ram.) OK, lad os se på dette sidste program. Åbn TWI_I2C_EEPROM.c. Den første ting at bemærke er, at jeg har angivet, hvordan jeg skal adressere hele 24C16 EEPROM. Det kan tilgås i 256 byte bidder på 8 forskellige I2C slave adresser. Se, hvordan MEMORY_ADDR defineres som startadressen ved 50 hexadecimale; derfor arbejdede vædderen. Hvis du vil have adgang til andre blokke af 24C16, skal du bruge de andre adresser som jeg har angivet. Se på, hvordan jeg konfigurerede mig til at skrive til hukommelsen. Først sættes slaveadressen med læse-/skrivebitsættet i bufferen, derefter startadressen på 00, derefter 16 bytes data. Funktionen TWI_Start_Read_Write kaldes til at skrive dataene (som før) med beskedstørrelsen indstillet til 18. Når der trykkes på knappen, bruger vi TWI_Start_Random_Read og TWI_Read_Data_From_Buffer til at læse dataene tilbage. Hver tredje byte vises på Port Expander -lysdioderne. Endelig slukkes lysdioderne for at afvente det næste tryk på knappen. Du undrer dig måske over, hvorfor jeg valgte at skrive 16 bytes. Hvis du læser databladet omhyggeligt, vil du se, at 24C16 laver en skrivecyklus, når den modtager 16 bytes, selvom der sendes flere bytes. Så det virkede som et godt nummer at bruge. Hvis du vælger at øge dette, skal du ændre størrelsen på MESSAGEBUF_SIZE. Du skal også ændre værdien TWI_BUFFER_SIZE i TWI_Master.h. Dette skyldes, at driveren kopierer dataene fra meddelelsesbufferen til brug i afbrydelsesrutinen. Tillykke! Du er nu klar til at bruge I2C -bussen i dine egne projekter!

Trin 7: Webressourcer

Her er linkene til databladene til de dele, der blev brugt til eksperimenterne. Du bør helt sikkert få disse, hvis du ikke får noget andet. Port ExpanderRamEEPROM Ved at være skaberen af I2C har NXP (Philips) masser af gode ting. (De kan lide at bruge firkantede parenteser i deres webadresser, så jeg kan ikke korrekt inkludere dem her. Beklager.] For at komme til I2C -området skal du vælge Interface fra listen over produkter. Du kan komme til deres I2C -websted og adgang til alle de datablade og apps noter, de tilbyder. I2C -busbeskrivelsen og især tekniske detaljer er her. Hent ATtiny2313 og ATmega168 databladene (databøger?) fra Atmel. Atmel applikationsnotaterne er her. Se AVR310 og AVR315. Tag også koden. Se her for mange flere I2C -ting.

Trin 8: Noter til nørder

For den sande nørd, der ønsker at kende detaljerne, er her nogle ting at huske på, hvis du ser på Atmel Apps Notes og driverkode:- Metoden til adressering og kommando af en I2C-enhed er ikke en del af specifikationen! Andre end slaveadressen og læse/skrive -bit er kommandoer, tilstande osv. Ikke specificeret og er specifikke for en given enhed. For at gøre dette meget klart, skal du bemærke, at den ordning, der bruges i Atmel-eksemplet, kun gælder for dette eksempel og stort set er ikke-standard.- USI-implementeringen adskiller sig fra TWI-implementeringen på et par vigtige måder. + Med USI leveres uret af software; med TWI leveres den af en Bit Rate Generator. + USI -metoden bruger ikke afbrydelser; TWI gør. Dette giver en vis mening, da Mega -familien (ved hjælp af TWI) kunne lave mange andre ting og ikke burde blive svinet til af I2C -overførsler. En interrupt -drevet version til USI er bestemt mulig, den er bare ikke implementeret i denne Instructable. + USI -hardwaren er ikke optimeret til I2C og kan kun håndtere 8 bit overførsler. Det betyder, at to overførsler er nødvendige for at sende den niende bit (enten NACK eller ACK). TWI -hardware håndterer dette automatisk. Dette gør implementeringen af USI -driveren lidt mere kompliceret. + Fejlsøgning for TWI håndteres i hardware. USI kræver håndtering i software, som komplicerer tingene noget. + TWI -hardwaren styrer konfigurationen af porten direkte. USI -hardware kræver, at portbitene konfigureres, før porten kan bruges. Du vil se dette i Master_Initialize-rutinen for USI.-Atmel hævder, at det er muligt at bruge AVR-port pull-ups til I2C bus pull-ups. Jeg har ikke fundet ud af en måde at få den tilgang til at fungere. Brug af to eksterne modstande virker som en temmelig simpel ordning, så jeg brugte ikke meget tid på dette.

Anbefalede: