Taula de continguts:

Bus I2C per ATtiny i ATmega: 8 passos
Bus I2C per ATtiny i ATmega: 8 passos

Vídeo: Bus I2C per ATtiny i ATmega: 8 passos

Vídeo: Bus I2C per ATtiny i ATmega: 8 passos
Vídeo: [Programming] I2C in AVR Assembly 2024, Juliol
Anonim
Bus I2C per ATtiny i ATmega
Bus I2C per ATtiny i ATmega

M'encanten els microcontroladors Atmel AVR. Des que vaig construir el sistema de desenvolupament del gueto descrit en aquest manual, no he tingut cap final de diversió experimentant amb l’AVR ATtiny2313 i l’ATmega168 en particular. Fins i tot vaig arribar a escriure una instrucció sobre l’ús d’interruptors com a entrades i vaig ampliar el concepte del sistema de desenvolupament de gueto a CPLD. Durant un projecte recent, necessitava diversos interruptors per establir els valors de control. Els AVR no tenien prou pins d'E / S, de manera que vaig haver de pensar en alguna cosa. Podria haver provat un sistema d’entrada complex amb teclat i pantalla, però l’ATtiny2313 hauria quedat sense recursos. Afortunadament, Atmel ha proporcionat una manera de solucionar aquest problema incloent una interfície que es pot enllaçar a xips addicionals (com ara memòria o ports d'E / S) amb una senzilla interfície de dos fils. És cert, en utilitzar només dos pins d'E / S en un AVR, podem accedir a molts pins d'E / S addicionals i altres recursos. Aquesta interfície de dos fils es coneix formalment com a bus de circuits integrats, o simplement bus I2C, i va ser inventada per NXP quan encara era Philips Semiconductors. Si esteu llegint aquest manual d’instruccions, probablement haureu sentit a parlar del bus I2C i fins i tot l’haureu utilitzat en un PIC o en un altre microcontrolador. Tot i que conceptualment és molt senzill i està recolzat pels recursos de maquinari dels AVR, els controladors de programari encara són necessaris per utilitzar el bus I2C. Atmel proporciona notes d’aplicació (consulteu els recursos més endavant en aquest document instructiu), però són incompletes i no mostren cap exemple més enllà de comunicar-se amb un altre dispositiu AVR. AVR. Més aviat, proporcionaré versions ampliades dels controladors Atmel per a dispositius ATtiny2313 i ATmega168, explicaré els requisits i les restriccions que s’apliquen en utilitzar-los i us mostraré exemples de treball de dispositius I2C. Després de treballar aquest Instructable, podreu utilitzar el bus I2C amb èxit en els vostres projectes AVR. Viouslybviament, podeu ignorar els controladors de minúsculs o MEGA si només us interessa un d’ells. Per a aquells que estiguin interessats a obtenir més informació sobre l’autobús I2C, proporcionaré enllaços al material adequat.

Pas 1: Què és tot això I2C?

Què és tot això I2C?
Què és tot això I2C?
Què és tot això I2C?
Què és tot això I2C?
Què és tot això I2C?
Què és tot això I2C?
Què és tot això I2C?
Què és tot això I2C?

El bus I2C és una connexió senzilla de dos fils que pot enllaçar diversos dispositius junts i permetre’ls intercanviar dades. En la seva forma més senzilla, hi ha un dispositiu mestre que es comunica a diversos dispositius esclaus. Tots els dispositius estan connectats en paral·lel als dos cables del bus I2C. Els dos cables es coneixen com a SCL i SDA. SCL és la línia del rellotge i està controlada pel dispositiu mestre. SDA és la línia de dades bidireccional. Per transferir dades, el mestre envia una adreça esclava combinada amb un indicador de lectura / escriptura d’un bit. Si es vol escriure, el mestre continuarà enviant dades a l'esclau adreçat. Si es demana una lectura, l'esclau respondrà amb dades. Per coordinar les transaccions, les línies SCL i SDA són manipulades pel mestre i l'esclau per assenyalar diverses condicions. Aquests inclouen START, STOP, ACK (reconèixer) i NAK (no reconèixer). Els conductors controlen els detalls d’aquestes condicions. Els autèntics frikis entre vosaltres poden aprendre tots els detalls als enllaços que es proporcionen al final d’aquest instructable. Els requisits elèctrics són bastant senzills. El mestre i els esclaus han d’utilitzar el mateix nivell per a Vcc, els terrenys han d’estar connectats i les línies SCL i SDA s’han d’arrossegar fins a Vcc. El valor de les resistències pull-up es determina amb precisió mitjançant un càlcul basat en la capacitat total del bus, però pràcticament pot ser pràcticament qualsevol valor entre 1,8K i 10K. Començo per 5.1K i faig servir valors més baixos fins que funcioni. Normalment, això no és un problema a menys que tingueu molts dispositius o fils llargs entre els dispositius. La velocitat de dades nominal al bus I2C és de 100 KB / segon. També són possibles taxes de 400 kbits / segon, 1 Mbits / segon i més, però els controladors no els admeten en aquest manual. Tots els dispositius I2C funcionaran a 100 Kbits / segon. L’ATtiny2313 i l’ATmega168 implementen cadascun el bus I2C de manera diferent. ATtiny2313 utilitza el maquinari Universal Serial Interface (USI), que també es pot utilitzar per al bus SPI. ATmega168 té maquinari dedicat per al bus I2C conegut com a interfície de dos cables (TWI). Un cop escrits els controladors, aquestes diferències són majoritàriament transparents per a l'usuari. Una diferència significativa es troba en el programari: el controlador ATmega168 I2C està controlat per interrupcions mentre que el de l'ATtiny2313 no ho és. Això significa que un programa ATmega168 no ha d’esperar a que es produeixin transferències de dades I2C, sinó que només ha d’esperar abans d’iniciar una altra transferència o fins que arribin les dades d’una operació de lectura. Els exemples i debats que cal seguir han de deixar-ho clar: les adreces I2C tenen una longitud de 7 bits, de manera que fins a 127 dispositius poden estar al bus si cadascuna té una adreça única. Com es mostra a la figura, aquesta adreça de 7 bits es desplaça cap a l'esquerra un bit i el bit menys significatiu s'utilitza per marcar una lectura o escriptura del dispositiu a l'adreça. Per tant, l'adreça esclava completa és un byte de 8 bits. L'adreça real es determina parcialment internament al dispositiu i no es pot canviar (4 bits més significatius), i parcialment es determina per bits que es poden connectar als pins del dispositiu (3 bits menys significatius) que es poden lligar alts o baixos per definir una adreça específica. Sembla confús, però un exemple ho deixarà clar. El full de dades del PCA8574A mostra que els quatre bits més significatius de l'adreça I2C sempre seran 0111. Els tres següents bits estan determinats per la configuració dels pins AD0, AD1 i AD2. Aquests pins es poden lligar a terra o a l'alimentació de tensió positiva (5 volts) per representar 0 o 1 respectivament. Per tant, el rang d’adreces possibles és de 38 a 3F hexadecimal, tal com es mostra a l’altra figura del full de dades PCA8574. Per tant, canviant la configuració del bit d’adreça, es poden trobar fins a 8 PCA8574A al bus I2C alhora. Cadascun respondrà només a la seva adreça esclava específica. Si calen encara més ports d'E / S, es pot utilitzar el PCA8574. L’única diferència entre el PCA8574 i el PCA8574A és que el rang d’adreces esclaus I2C del PCA8574 és de 20 a 27 hexadecimals. Determinar l’adreça d’un dispositiu determinat pot resultar confús ja que alguns fulls de dades consideren que el bit de lectura / escriptura forma part del adreça. Llegiu detingudament el full de dades i tingueu en compte que l'adreça esclava durarà 7 bits. El bit de lectura / escriptura s’ha de tractar per separat. De nou, un exemple us ajudarà. El full de dades de l'EEPROM 24C16 amb què experimentarem diu que els primers (més significatius) quatre bits de l'adreça esclava són 1010. Els següents tres bits es poden determinar per A0, A1 i A2; però tingueu en compte que el full de dades també inclou les 24C01 a les 24C08, que són EEPROM de mida més petita. La figura del full de dades mostra que la configuració d’aquests bits d’adreces s’ignora a mesura que augmenta la mida i s’ignoren completament per al 24C16. És a dir, els últims tres bits no importen i el 24C16 realment utilitza totes les adreces esclaus I2C de 50 a 57 hexadecimals. El rang d'adreces esclaves s'adreçarà a diferents seccions dins del 24C16. Els primers 256 bytes són a l'adreça 50h, els 256 següents a 51h, i així fins a l'últim 256 a les 57h, per a un total de 2K bytes. Com que l'adreça de la memòria RAM PCF8570 amb la qual també experimentem es troba en aquest rang, el 24C16 i el PCF8570 no es poden utilitzar junts.

Pas 2: demaneu alguns dispositius I2C

Ara que ja coneixeu una mica el bus I2C i voleu fer-lo servir, per què no demaneu a alguns dispositius I2C que experimentin ara perquè us puguin anar preparant el programari? Els dispositius adequats inclouen un I / O Interface Expander (el meu preferit), un RAM estàtic i una EEPROM. Hi ha molt més, però són un bon començament. Els processadors AVR que utilitzarem són ATtiny2313 i Atmega168 (que s’utilitzen a Arduino). Si no esteu al cas, feu una ullada a aquest fantàstic manual instructiu per obtenir més informació i construir el vostre sistema de desenvolupament de gueto. L'esquema de l'ATmega168 del present instructable mostra com implementar el sistema de desenvolupament Ghetto per a aquest processador. El cable de port paral·lel és el mateix que el de l'ATtiny2313. (No he provat la versió USB del Ghetto Development System, així que no estic segur de com s’hi accedeix al bus I2C. El mateix per a l’Arduino.) A continuació, es detallen els números de peça Digikey. Expandidor de port: I / O IC I2C EXPANDER 568-4236-5-NDRam: IC SRAM 256X8 W / I2C 568-1071-5-NDEEPROM: IC EEPROM SERIAL 16K CAT24C16LI-G-ND

Pas 3: controladors I2C

Aquí hi ha les descripcions de les funcions del controlador per al bus I2C. Aquests es van desenvolupar mitjançant els Notes d’Atmel Apps per a principiants. No ho hauria pogut fer sense ells com a base per construir. El desenvolupament es va fer amb WinAVR i el compilador gcc C. A continuació es descriuen les restriccions de freqüència de rellotge per a cada processador. Com que no sóc capaç de provar totes les combinacions de sabor del processador / velocitat de rellotge possibles, em limitaré a allò que realment puc provar i intentaré indicar les restriccions i limitacions. Aquí teniu les funcions del controlador i com utilitzar-les. Consulteu els exemples per obtenir més detalls i veure les funcions que s’utilitzen en programes complets. Per a l’ATtiny2313: requisit de rellotge: els controladors estan dissenyats per a una freqüència de rellotge d’1 MHz (la taxa per defecte) per a ATtiny2313. Si voleu córrer a altres velocitats, haureu d’ajustar les constants als controladors. Envieu-me un correu electrònic si necessiteu ajuda per fer-ho. També podeu obtenir algunes pistes de les notes de les aplicacions Atmel als enllaços del Pas de recursos. USI_TWI_Master_Initialise () Aquesta funció inicialitza el maquinari USI per al funcionament del mode I2C. Truqueu-lo una vegada al començament del programa. Torna nul i no hi ha arguments. USI_TWI_Get_State_Info () Aquesta funció retorna informació d'error I2C i s'utilitza si s'ha produït un error durant una transacció I2C. Com que aquesta funció només retorna un codi d'error, faig servir la funció TWI_Act_On_Failure_In_Last_Transmission (TWIerrorMsg) per fer parpellejar un LED d'error. Els codis d'error es defineixen a USI_TWI_Master.h. A continuació s’explica com anomenar-lo: TWI_Act_On_Failure_In_Last_Transmission (USI_TWI_Get_State_Info ()) USI_TWI_Start_Read_Write () Aquesta funció s’utilitza per llegir i escriure bytes individuals en dispositius I2C. També s’utilitza per escriure diversos bytes. Hi ha 6 passos per utilitzar aquesta funció. 1) Declareu un buffer de missatges al programa per contenir l'adreça esclava i el byte de dades que s'han d'enviar o rebre. unsigned char messageBuf (MESSAGEBUF_SIZE); 2) Col·loqueu l’adreça d’esclau com a primer byte al buffer. Canvieu-lo un bit cap a l'esquerra i OR al bit de lectura / escriptura. Tingueu en compte que el bit de lectura / escriptura serà 1 per a una lectura i 0 per a una escriptura. Aquest exemple és per a una lectura. messageBuf (0) = (TWI_targetSlaveAddress << TWI_ADR_BITS) | (TRUE << TWI_READ_BIT); 3) Quan feu una escriptura, col·loqueu el byte que cal escriure a la següent ubicació del buffer. es pot provar el valor retornat (temperatura en aquest cas) per veure si s’ha produït un error. Si és així, es gestiona tal com s'ha comentat anteriorment. Vegeu exemples als programes. 6) Si es va sol·licitar una lectura, la lectura de bytes es trobarà a la segona ubicació del buffer. Si s’han d’escriure diversos bytes (com ara en un dispositiu de memòria), es pot utilitzar aquesta mateixa rutina. La configuració del buffer i la trucada a la rutina són lleugerament diferents. El segon byte de la memòria intermèdia serà l'adreça de memòria inicial on escriure. Les dades que s’escriuran estaran en bytes posteriors. La mida del missatge serà la mida que inclou totes les dades vàlides. Per tant, si s’han d’escriure 6 bytes, la mida del missatge serà de 8 (adreça esclava + adreça de memòria + 6 bytes de dades). USI_TWI_Start_Random_Read () Aquesta funció s’utilitza per llegir diversos bytes d’un dispositiu I2C, normalment només un record d’alguna mena. L’ús d’aquesta rutina és molt similar a la rutina anterior, amb dues excepcions: la configuració del bit de lectura / escriptura no importa. La trucada a aquesta rutina sempre provocarà una operació de lectura. El missatge Size hauria de ser 2 més el nombre de bytes que s’ha de llegir. Si no es produeixen errors, les dades es trobaran a la memòria intermèdia a partir de la segona ubicació. els controladors estan dissenyats per a una freqüència de rellotge de 4 MHz per a ATmega168. L'exemple de codi mostra com establir aquesta freqüència de rellotge. Si voleu córrer a altres velocitats, haureu d’ajustar les constants als controladors. Envieu-me un missatge de correu electrònic si cal fer-ho. TWI_Master_Initialise () Aquesta funció inicialitza el maquinari TWI per al funcionament en mode I2C. Truqueu-lo una vegada al començament del programa. Torna nul i no hi ha arguments. Assegureu-vos d’activar les interrupcions trucant a swi () després de la inicialització. TWI_Get_State_Info () Aquesta funció retorna informació d'error I2C i s'utilitza si s'ha produït un error durant una transacció I2C. Atès que aquesta funció només retorna un codi d'error, faig servir la funció TWI_Act_On_Failure_In_Last_Transmission (TWIerrorMsg) per parpellejar un LED d'error. Els codis d'error es defineixen a TWI_Master.h, però es modifiquen per a la senyalització d'un LED d'error. Consulteu l'exemple de codi per obtenir més informació. A continuació s’explica com anomenar-lo: TWI_Act_On_Failure_In_Last_Transmission (TWI_Get_State_Info ()) Tingueu en compte que la comprovació d’errors es realitza comprovant que la transacció I2C està completa (funció que es descriu a continuació) i, a continuació, proveu un bit a la paraula d’estat global. TWI_Start_Read_Write () TWI_Read_Rand () dues funcions funcionen igual que les funcions corresponents descrites anteriorment, però amb algunes excepcions. No retornen cap valor d'error. La lectura de dades no es transfereix a la memòria intermèdia. Això es farà amb la funció que es descriu a continuació. Quan truqueu a TWI_Start_Random_Read, el missatge Size hauria de ser el nombre de bytes de dades sol·licitats més un, no dos. És a dir, les transaccions I2C s’inicien i després s’executen de forma independent mentre es continua executant la rutina principal. Quan la rutina principal vol que es comencin dades d'una transacció I2C, ha de comprovar si les dades estan disponibles. La situació és la mateixa per a la comprovació d'errors. La rutina principal ha d'assegurar-se que la transacció I2C s'ha completat abans de comprovar si hi ha errors. Les dues funcions següents s’utilitzen per a aquests propòsits. TWI_Transceiver_Busy () Truqueu a aquesta funció per veure si s’ha completat una transacció I2C abans de comprovar si hi ha errors. Els programes d'exemple mostren com s'utilitza això. TWI_Read_Data_From_Buffer () Truqueu a aquesta funció per transferir dades del buffer de recepció del controlador I2C al buffer de missatges. Aquesta funció assegurarà que la transacció I2C estigui completa abans de transferir les dades. Tot i que aquesta funció retorna un valor, trobo que la comprovació directa del bit d’error és més fiable. A continuació s’explica com es diu. La mida del missatge ha de ser superior al nombre de bits de dades desitjat. Les dades estaran a messageBuf a partir de la segona ubicació.temp = TWI_Read_Data_From_Buffer (messageBuf, messageSize);

Pas 4: Construïm

Construïm!
Construïm!
Construïm!
Construïm!
Construïm!
Construïm!
Construïm!
Construïm!

Comenceu descarregant el fitxer I2C Schematics.zip. És possible que vulgueu crear una carpeta I2C a la vostra àrea de treball per contenir els esquemes i els fitxers de programa d’exemple. Descomprimiu els esquemes en aquest directori. Trobareu una carpeta anomenada I2C Schematics. Obriu el fitxer anomenat tiny I2C.pdf. Aquest esquema mostra el sistema de desenvolupament de guets ATtiny2313 i l’expansor de ports E / S PCA8574A (té la gran caixa discontínua al voltant). El circuit Port Expander està construït sobre una taula de treball. Mireu les fotos per veure com són aquests circuits. Són molt senzills. La part ATtiny2313 de l’esquema és només el sistema de desenvolupament Ghetto amb tres llums intermitents (LED1, 2 i 3, més R4, 5 i 6) i un polsador (S1) enganxat a ell, més un detall addicional. Aquest detall és l’addició de ponts (JP4, 5 i 6) que es poden eliminar per permetre la connexió de les línies SCL i SDA del bus I2C. Els ponts han d'estar al seu lloc per a la programació, després s'han de treure perquè SCL i SDA es puguin connectar. Les fotos mostren els ponts al seu lloc i retirats. La ubicació d’aquests ponts depèn de vosaltres, només cal que els poseu al vostre sistema de desenvolupament Ghetto si voleu utilitzar el bus I2C. Cal desconnectar el bus I2C i posar els ponts per a la programació. Tingueu en compte que només cal que us preocupeu per JP4 i JP6 per al bus I2C. Introduïu JP5 si creieu que voldreu utilitzar el bus SPI. Fer una tauleta de pa amb l’expansor de ports E / S PCA8574A és molt senzill. Proporcioneu connexions Vcc (+5 volts) i Gnd (terra) i connecteu AD0, 1 i 2 a terra (fa que l'adreça esclava I2C sigui 38 hexadecimal). A continuació, connecteu 4 llums intermitents i 4 commutadors DIP. (Si no teniu commutadors DIP, només podeu utilitzar cables. Lligueu-lo a terra o deixeu-lo flotant per activar o desactivar el senyal respectivament.) Finalment, connecteu les resistències de tracció (R11 i 12) des de SDA i SCL a Vcc. Es mostren com a 3,3 K, però qualsevol valor des de 1,8 K fins a 5,1 K hauria de funcionar (potser fins a 10 K però no ho he provat). Un cop hàgiu programat l'ATtiny2313, podeu treure els ponts i connectar SDA i SCL per provar-los. Ara per a l'ATmega168. L'única arruga aquí és que potser no heu construït un sistema de desenvolupament Ghetto per a aquest processador. Si aquest és el cas, l'esquema que proporciono (MEGA I2C.pdf) us mostrarà com fer-ho. Això és només una permutació de la versió ATtiny2313. Si teniu previst assegurar-vos que el cable de programació s'adapti a tots dos sistemes. La principal diferència és l’addició de C2 i C3. Vegeu les imatges per situar-les, haurien d’estar molt a prop del xip; un d’ells es troba realment sota el xip. Aquests ajuden a evitar el soroll del convertidor analògic a digital en particular. No cal introduir els ponts tret que tingueu previst utilitzar el bus SPI, ja que no són necessaris per al bus I2C d’aquest xip. Tingueu en compte que la placa de suport PCA8754A no canviarà. Simplement connectareu SDA i SCL i ja no hi podreu. Fàcil, eh?

Pas 5: codifiquem i provem

Codifiquem i provem!
Codifiquem i provem!
Codifiquem i provem!
Codifiquem i provem!
Codifiquem i provem!
Codifiquem i provem!

És hora de construir els controladors i els programes d’exemple. Començarem per l'ATtiny2313 i la placa de suport PCA8574A que acabem de construir. Baixeu el fitxer I2C.zip al directori de treball I2C i descomprimiu-lo. Tindreu una nova carpeta anomenada I2C. Hi trobareu USI I2C (per a ATtiny2313) i TWI I2C (per a ATmega168). A USI I2C, trobareu la carpeta I_O Port. Aquesta carpeta conté el codi del nostre primer programa d’exemple i els controladors USI I2C. Utilitzant WinAVR, compileu i carregueu el codi a l’ATtiny2313. Respireu profundament i engegueu l’alimentació. Això és el que cal esperar: en encendre’s, el LED 1 del port PD6 de l’ATtiny2313 parpelleja dues vegades. No passarà res fins que no premeu el botó (S1). Cada vegada que es prem el botó, es llegeixen els commutadors i el seu paràmetre es mostrarà als LED connectats al PCA8574A. Canvieu el valor dels commutadors, premeu el botó i els LED haurien de canviar. Seguiu fent això fins que superi l'emoció de veure-ho funcionar. Si (Déu no ho permeti!), Les coses no funcionen com s’esperava, comproveu acuradament el cablejat. Els errors I2C seran assenyalats per parpelleigs del LED3 (PD4) i probablement signifiquin que haureu de comprovar que SDA i SCL estan connectats als pins correctes i que s’estrenen correctament. Si les coses encara no funcionen, llegiu la resta d'aquesta secció per obtenir informació sobre la depuració. Ara torneu enrere i fem una ullada al codi. Obriu el fitxer USI_I2C_Port.c. Aquest és el codi per al programa d'exemple. (USI_TWI_Master.c i USI_TWI_Master.h contenen els controladors; podeu ignorar-los tret que tingueu curiositat.) Feu servir l’exemple per guiar les vostres pròpies aplicacions I2C. pujar l'adreça esclava i la resta de memòria intermèdia de missatges i treure'n les dades. També veureu com rebutjo el botó i configuro el bucle while. Hi ha alguns detalls del programa que val la pena esmentar. Tingueu en compte que les dades dels commutadors s’inverteixen abans d’escriure-les als LED del Port Expander. Tingueu en compte també que els ports d’entrada del Port Expander s’han d’escriure com a Alts perquè funcionin correctament. Aquests detalls es descriuen al full de dades del PCA8574A. Llegiu sempre atentament els fulls de dades. L’interès és l’ús de la depuració condicional. Prop de l'inici del fitxer del programa hi ha la sentència // # define DEBUG i esquitxades per tot el codi hi ha sentències #ifdef DEBUG. Mentre no estigui definit DEBUG (les dues barres incloses fan que la línia sigui un comentari i eviti que es defineixi), no es compilarà el codi de les sentències #ifdef a #endif. Però si les coses no funcionen com esperàveu, torneu a compilar i torneu a carregar el codi amb #define DEBUG sense comentar. Rebreu molts parpelleigs als LED que podeu descodificar per seguir l'execució del programa i ajudar-vos a trobar exactament on les coses no funcionen correctament. De fet, us recomano que proveu això només per veure què passa. El que veureu és que el LED 2 (a PD5) parpellejarà a mesura que avanci l'execució a través del programa. El valor llegit dels commutadors parpellejarà al LED 1 (PD6) abans que es mostri als LED d'expansió de port. Hauríeu de ser capaç de fer un seguiment del programa mentre s’executa utilitzant aquests LED. A continuació, treballarem amb l’ATmega168; ometeu aquesta secció si només us interessa ATtiny2313. Encara amb mi? Bé. Aneu a la carpeta TWI_I2C, canvieu el directori de treball a IO_Port i compileu i carregueu TWI_I2C_Port.c a l’ATmega168. Desconnecteu les línies SDA i SCL de l'ATtiny2313 i connecteu-les a ATmega168. Connecteu el corrent elèctric i el terra, i enceneu-lo. L'operació hauria de ser la mateixa! Juga fins que l’emoció disminueix i, a continuació, mirem el codi. Obre TWI_I2C_Port.c. El codi és gairebé idèntic, excepte per a la manipulació d'errors i la adaptació als conductors impulsats per interrupcions. Aquí hi ha les diferències: tingueu en compte que el rellotge s’ha d’establir a 4 MHz perquè el bus I2C funcioni correctament. El sei (); La sentència activa les interrupcions després de la inicialització dels controladors I2C. Per comprovar si hi ha errors, es prova un bit d'estat específic. Durant una lectura, s’ha de cridar a la funció TWI_Read_Data_From_Buffer per transferir les dades llegides al buffer de missatges. Durant una escriptura, cal utilitzar {TWI_Transceiver_Busy ()) per assegurar-se que la transferència s'ha completat abans de comprovar si hi ha errors. Aquestes dues darreres funcions es descriuen anteriorment a la descripció dels controladors. A part d'això, el codi és pràcticament el mateix que per a l'ATtiny2313. DEBUG funciona igual si voleu experimentar amb això.

Pas 6: utilitzar la memòria I2C

Ús de memòria I2C
Ús de memòria I2C
Ús de memòria I2C
Ús de memòria I2C
Ús de memòria I2C
Ús de memòria I2C
Ús de memòria I2C
Ús de memòria I2C

Ara que hem après a utilitzar el bus I2C per llegir i escriure un expansor de port d'E / S, anem a utilitzar memòries I2C, tant RAM com EEPROM. La principal diferència és que es poden llegir o escriure múltiples bytes des de memòries amb una sola ordre I2C. Per preparar-nos per a aquests experiments, hem de modificar lleugerament el maquinari i construir un parell de circuits nous a la taula de treball. Mantingueu el circuit Port Expander, ja que l’utilitzarem per mostrar alguns valors de memòria. Traieu els interruptors DIP del PCA8574A i col·loqueu llums intermitents en aquests pins. Si no teniu prou parpelleig, moveu els de P4 a P7 a P0 a P3. (Els valors que es mostraran són prou petits.) Ara mireu l'esquema I2C Ram.pdf i connecteu el PCF8570 a la taula de treball. Mireu també la imatge. Assegureu-vos de lligar el pin 7 a Vcc. Executeu cables per a SDA i SCL des del PCA8574A. No calen resistències de tracció addicionals. Si també us interessa l'EEPROM, creeu aquest circuit també amb I2C EEPROM.pdf per al 24C16, però tingueu en compte que l'exemple utilitza l'ATmega168. Aquest circuit és realment senzill. Com s'ha comentat anteriorment, els bits d'adreça s'han d'ignorar. Només cal connectar el corrent elèctric i el sòl. No connecteu SDA i SCL encara, ja que no hem acabat d’experimentar amb el Ram. Començarem els nostres experiments de memòria amb l’ATtiny2313 connectat al PCA8574A Port Expander i al PCF8570 Ram. El programa escriurà alguns números a la memòria RAM, després els llegirà i els mostrarà al Port Expander. Canvieu el directori de treball a RAM sota USI I2C. Utilitzeu el fitxer make per compilar i descarregar USI_I2C_RAM.c. Tingueu en compte que els fitxers del controlador I2C són idèntics als que hem utilitzat anteriorment. Connecteu l’alimentació i hauríeu de veure un sol parpelleig al LED 1 (PD6). Les dades s’escriuran als primers 4 bytes de memòria. Premeu el botó i es llegiran i es mostraran dos bytes. Hauríeu de veure una llum LED al Port Expander (P0), una pausa de dos segons i després dos LED (P0 i P1). Una altra pausa de dos segons i els LED s’haurien d’apagar. Torneu a prémer el botó per tornar a iniciar la seqüència. La depuració és similar al mètode descrit anteriorment. Vegem el codi. Obriu USI_I2C_RAM.c. Ha de semblar força similar al codi anterior. Les principals diferències són els detalls de la lectura i l’escriptura de la memòria. Mireu com es carrega la memòria intermèdia de missatges abans de la trucada que realment escriu. El primer byte és l'adreça esclava amb el bit de lectura / escriptura establert adequadament. Però el següent byte és l’adreça de memòria on començar a escriure dades. Després vindran els bytes de dades reals que es carregaran seqüencialment a la memòria a partir de l’adreça que hem especificat. Especifiquem la mida del missatge com 6. Per tant, comencem a escriure a l’adreça 00 i escrivim els valors 01, 03, 02 i 06 a les ubicacions de memòria 00 a 03. Per llegir les dades de la memòria hem d’utilitzar la funció USI_TWI_Start_Random_Read. El buffer de missatges obté l'adreça esclava al primer byte i l'adreça inicial al segon byte. A continuació, truqueu a la funció amb la mida del missatge establerta al nombre de bytes a llegir més 2. Tingueu en compte que el bit de lectura / escriptura no importa, ja que es farà una lectura independentment. Les dades retornades començaran a la segona ubicació del buffer de missatges. Un cop llegides les dades, s’inverteixen per mostrar-les al Port Expander i s’hi escriuen un byte a la vegada amb una pausa entre els valors. Finalment, els LED d'expansió de port estan apagats. Les escriptures a Port Expander són idèntiques a les que es van fer en els exemples anteriors. Per diversió, podeu descomentar la sentència #define DEBUG tal com es mostra més amunt i veure un munt de LEDs parpellejants. Plens d’emoció després d’un altre experiment reeixit, anem a l’ATmega168 i a una EEPROM. Canvieu el directori de treball a EEPROM amb TWI I2C. Utilitzeu el fitxer make per compilar i descarregar TWI_I2C_EEPROM.c. Tingueu en compte que els fitxers del controlador I2C són idèntics als que hem utilitzat anteriorment per al PCA8574A. Per provar el programa, desconnecteu l'ATtiny2313 i connecteu l'ATmega168. Deixeu el bus I2C enganxat al Ram i enceneu-lo. Els resultats són diferents ja que ara escrivim i llegim més dades. El LED 1 del PD7 hauria de parpellejar a la inicialització. Premeu el botó i les dades es llegiran de la memòria i es mostraran. Els LED del PCA8574 haurien de parpellejar la següent seqüència: P1, P0 i P2, (tots apagats), P0 i P1, P1 i P2. Finalment, els LED del port haurien d’apagar-se. Torna a prémer el botó per repetir-ho. Oh, però espera, dius. No és aquest programa per a l'EEPROM? Com que accedim a un dispositiu de memòria amb la mateixa adreça I2C, el mateix programa funciona tant per a Ram com per a EEPROM. Apagueu i moveu SDA i SCL del RAM a l'EEPROM i torneu a executar el programa. Hauria de funcionar exactament igual. Tingueu en compte que l'EEPROM i el Ram no es poden connectar al bus I2C alhora, ja que comparteixen la mateixa adreça. (Els més intel·ligents de vosaltres poden considerar canviar els bits d’adreça programables al Ram, però això encara no funcionarà. El 24C16 utilitza tot el bloc d’adreces que es poden programar per al Ram.) D’acord, vegem aquest darrer programa. Obriu TWI_I2C_EEPROM.c. El primer que heu de tenir en compte és que he indicat com tractar la EEPROM 24C16 completa. Es pot accedir a trossos de 256 bytes a 8 adreces esclaus I2C diferents. Vegeu com MEMORY_ADDR es defineix com l’adreça inicial a 50 hexadecimals; per això, el Ram funcionava. Si voleu accedir a altres blocs del 24C16, feu servir les altres adreces tal com he indicat. Feu una ullada a com vaig configurar per escriure a la memòria. Primer es posa l'adreça esclava amb el conjunt de bits de lectura / escriptura al buffer, després l'adreça inicial de 00 i després 16 bytes de dades. La funció TWI_Start_Read_Write es diu per escriure les dades (com abans) amb la mida del missatge establerta a 18. Quan es prem el botó, fem servir TWI_Start_Random_Read i TWI_Read_Data_From_Buffer per llegir les dades. Cada tercer byte es mostra als LED d'expansió de port. Finalment, els LED s’apagaran per esperar el següent botó. Us podeu preguntar per què he escollit escriure 16 bytes. Si llegiu atentament el full de dades, veureu que el 24C16 fa un cicle d’escriptura cada vegada que rep 16 bytes, fins i tot si s’envien més bytes. Per tant, em va semblar un bon número d’utilitzar. Si decidiu augmentar-ho, haureu de canviar la mida de MESSAGEBUF_SIZE. També haureu de canviar el valor TWI_BUFFER_SIZE a TWI_Master.h. Això es deu al fet que el controlador copia les dades del buffer de missatges per utilitzar-les a la rutina del servei d'interrupcions. Enhorabona! Ja esteu a punt per utilitzar el bus I2C en els vostres propis projectes.

Pas 7: Recursos web

Aquí hi ha els enllaços als fulls de dades de les parts utilitzades per als experiments. Definitivament hauríeu d’aconseguir-los si no obteniu res més. Port ExpanderRamEEPROM Al ser el creador d’I2C, NXP (Philips) té un munt de coses fantàstiques. (Els agrada fer servir claudàtors als seus URL, de manera que no els puc incloure correctament aquí. Ho sentim.) Per accedir a l'àrea I2C, seleccioneu Interfície a la llista de productes. Podreu accedir al seu lloc I2C i accediu a tots els fulls de dades i notes d’aplicacions que ofereixen. La descripció i els detalls tècnics del bus I2C en concret es troben aquí. Obteniu els fulls de dades ATtiny2313 i ATmega168 (llibres de dades?) d’Atmel. Les notes de l’aplicació Atmel són aquí. Consulteu AVR310 i AVR315. Agafeu el codi també. Feu un cop d'ull aquí per veure més coses I2C.

Pas 8: notes per a frikis

Per al veritable friki que vulgui conèixer els detalls, aquí teniu algunes coses a tenir en compte si mireu les notes i el codi del controlador d'Atmel Apps: - El mètode d'adreçament i comandament d'un dispositiu I2C no forma part de les especificacions. A part de l'adreça esclava i el bit de lectura / escriptura, les ordres, els modes, etc. no s'especifiquen i són específics d'un dispositiu determinat. Per deixar-ho molt clar, tingueu en compte que l’esquema utilitzat a l’exemple d’Atmel només s’aplica a aquest exemple i és pràcticament no estàndard. La implementació USI difereix de la implementació TWI de maneres importants. + Amb USI, el rellotge el proporciona el programari; amb TWI el proporciona un generador de velocitat de bits. + El mètode USI no utilitza interrupcions; ho fa el TWI. Això té un cert sentit, ja que la família Mega (que utilitza TWI) podria fer moltes altres coses i no hauria d’estar embolicada per les transferències I2C. És cert que és possible una versió basada en interrupcions per a USI, simplement no està implementada en aquest instructiu. + El maquinari USI no està optimitzat per a I2C i només pot gestionar transferències de 8 bits. Això significa que es necessiten dues transferències per enviar el novè bit (ja sigui NACK o ACK). El maquinari TWI ho gestiona automàticament. Això fa que la implementació del controlador USI sigui una mica més complicada. + La detecció d'errors per al TWI es gestiona al maquinari. La USI requereix la manipulació de programari que complica una mica les coses. + El maquinari TWI controla directament la configuració del port. El maquinari USI requereix que els bits de port es configurin abans que es pugui utilitzar el port. Ho veureu a la rutina Master_Initialize per a la USI.- Atmel afirma que és possible utilitzar extraccions de port AVR per a les extraccions del bus I2C. No he descobert la manera de fer funcionar aquest enfocament. L’ús de dues resistències externes sembla un esquema força senzill, de manera que no hi vaig dedicar molt de temps.

Recomanat: