- Wat is het I2C-communicatieprotocol?
- Hoe I2C-communicatie werkt?
- Waar gebruik ik I2C-communicatie?
- I2C met PIC16F877a met XC8 Compiler
- Programmeren met behulp van de I2C-headerbestanden:
- Proteus Simulatie:
PIC-microcontrollers zijn een krachtig platform dat wordt geleverd door microchip voor ingebedde projecten. Door zijn veelzijdige karakter heeft het manieren gevonden om in veel toepassingen te komen en de fase is nog niet afgerond. Als je onze PIC-tutorials hebt gevolgd, zou je hebben gemerkt dat we al vanaf de basis een breed scala aan tutorials over PIC-microcontrollers hebben behandeld. Sinds nu hebben we de basis besproken waarmee we op interessantere dingen kunnen komen, zoals het communicatieportaal.
In het enorme systeem van embedded applicaties kan geen enkele microcontroller alle activiteiten zelf uitvoeren. Op een bepaald moment moet het communiceren met andere apparaten om informatie te delen, er zijn veel verschillende soorten communicatieprotocollen om deze informatie te delen, maar de meest gebruikte zijn USART, IIC, SPI en CAN. Elk communicatieprotocol heeft zijn eigen voor- en nadeel. Laten we ons voorlopig concentreren op het IIC-gedeelte, want dat is wat we in deze tutorial gaan leren.
Wat is het I2C-communicatieprotocol?
De term IIC staat voor " Inter Integrated Circuits ". Het wordt normaal gesproken aangeduid als I2C of I squared C of zelfs als 2-draads interfaceprotocol (TWI) op sommige plaatsen, maar het betekent allemaal hetzelfde. I2C is een synchroon communicatieprotocol, wat betekent dat beide apparaten die de informatie delen een gemeenschappelijk kloksignaal moeten delen. Het heeft slechts twee draden om informatie te delen, waarvan de ene wordt gebruikt voor het cocksignaal en de andere wordt gebruikt voor het verzenden en ontvangen van gegevens.
Hoe I2C-communicatie werkt?
I2C-communicatie werd voor het eerst geïntroduceerd door Phillips. Zoals eerder gezegd heeft het twee draden, deze twee draden worden over twee apparaten verbonden. Hier wordt het ene apparaat een master genoemd en het andere apparaat als slaaf. Communicatie moet en zal altijd plaatsvinden tussen twee een Master en een Slave. Het voordeel van I2C-communicatie is dat er meer dan één slaaf op een master kan worden aangesloten.
De volledige communicatie vindt plaats via deze twee draden, namelijk Serial Clock (SCL) en Serial Data (SDA).
Seriële klok (SCL): deelt het kloksignaal dat door de master wordt gegenereerd met de slave
Seriële gegevens (SDA): verzendt de gegevens van en naar tussen de master en slave.
Op elk moment kan alleen de master de communicatie starten. Omdat er meer dan één slave in de bus is, moet de master naar elke slave verwijzen met een ander adres. Als alleen de zalf met dat specifieke adres wordt geadresseerd, zal hij antwoorden met de informatie, terwijl de anderen stoppen. Op deze manier kunnen we dezelfde bus gebruiken om met meerdere apparaten te communiceren.
Waar gebruik ik I2C-communicatie?
I2C-communicatie wordt alleen gebruikt voor communicatie op korte afstand. Het is zeker tot op zekere hoogte betrouwbaar omdat het een gesynchroniseerde klokpuls heeft om het slim te maken. Dit protocol wordt voornamelijk gebruikt om te communiceren met sensoren of andere apparaten die informatie naar een master moeten sturen. Het is erg handig wanneer een microcontroller moet communiceren met veel andere slavemodules met een minimum aan alleen draden. Als u op zoek bent naar langeafstandscommunicatie, moet u RS232 proberen en als u op zoek bent naar betrouwbaardere communicatie, moet u het SPI-protocol proberen.
I2C met PIC16F877a met XC8 Compiler
Genoeg introducties, laten we erop ingaan en leren hoe we een microcontroller kunnen gebruiken voor het uitvoeren van I2C-communicatie. Voordat we beginnen, moet duidelijk worden gemaakt dat deze tutorial alleen spreekt over I2C in PIC16F877a met behulp van de XC8-compiler. Het proces zal hetzelfde zijn voor andere microcontrollers, maar er kunnen kleine wijzigingen nodig zijn. Onthoud ook dat voor geavanceerde microcontrollers zoals de PIC18F-serie de compiler zelf misschien een ingebouwde bibliotheek heeft om de I2C-functies te gebruiken, maar voor PIC16F877A bestaat zoiets niet, dus laten we er zelf een bouwen. De bibliotheek die hier wordt uitgelegd, wordt onderaan als een header-bestand gegeven om te downloaden, dat kan worden gebruikt voor PIC16F877A om te communiceren met andere I2C-apparaten.
Zoals altijd is de beste plaats om iets te beginnen onze datasheet. Kijk voor details over I2C in datasheet en controleer welke registers geconfigureerd moeten worden. Ik ga het niet in details uitleggen, aangezien de datasheet dat al voor je heeft gedaan. Hieronder ga ik de verschillende functies die aanwezig zijn in het headerbestand en hun verantwoordelijkheid in het programma uitleggen.
leegte I2C_Initialize ()
De initialisatiefunctie wordt gebruikt om de microcontroller te vertellen dat we het I2C-protocol gaan gebruiken. Dit kan worden gedaan door de vereiste bits in het SSPCON- en SSPCON2-register in te stellen. De eerste stap zou zijn om de IIC-pinnen als invoerpinnen te declareren, hier zouden de pinnen RC3 en RC4 moeten worden gebruikt voor I2C-communicatie, dus we declareren ze als invoerpinnen. Vervolgens moeten we de SSPCON en SSPCON2 instellen, wat een MSSP-besturingsregistratie is. We gebruiken de PIC in IIC-mastermodus met een klokfrequentie van FOSC / (4 * (SSPADD + 1)). Raadpleeg de paginanummers van het gegevensblad in de commentaarregels hieronder om te begrijpen waarom dat specifieke register zo is ingesteld.
Dus vervolgens moeten we de klokfrequentie instellen, de klokfrequentie voor verschillende toepassingen kan variëren, daarom krijgen we de keuze van de gebruiker via de variabele feq_k en gebruiken we deze in onze formules om het SSPADD-register in te stellen.
void I2C_Initialize (const unsigned long feq_K) // Begin IIC als master { TRISC3 = 1; TRISC4 = 1; // Stel SDA- en SCL-pinnen in als invoerpinnen SSPCON = 0b00101000; // pg84 / 234 SSPCON2 = 0b00000000; // pg85 / 234 SSPADD = (_XTAL_FREQ / (4 * feq_K * 100)) - 1; // Kloksnelheid instellen pg99 / 234 SSPSTAT = 0b00000000; // pg83 / 234 }
Ongeldig I2C_Hold ()
De volgende belangrijke functie is de I2C_hold- functie die wordt gebruikt om de uitvoering van het apparaat vast te houden totdat de huidige I2C-bewerking is voltooid. We zouden moeten controleren of de I2C-operaties moeten worden vastgehouden voordat we een nieuwe operatie starten. Dit kan gedaan worden door het register SSPSTAT en SSPCON2 te controleren. De SSPSTAT bevat de informatie over de status van de I2C-bus.
Het programma lijkt misschien een beetje ingewikkeld, aangezien het een "en" en een "of" -operator omvat. Wanneer je het breekt als
SSPSTAT & 0b00000100 SSPCON2 & 0b00011111
Het is een feit dat u zich geen zorgen hoeft te maken.
Het betekent dat we ervoor zorgen dat de 2 e bit op SSPSTAT nul is en evenzo bits van 0 tot 4 zijn nul op SSPCON2. Vervolgens combineren we al deze om te controleren of het resultaat nul is. Als het resultaat nul is, gaat het programma verder, zo niet, dan blijft het daar totdat het nul wordt, omdat het in een while- lus wordt gebruikt.
ongeldig I2C_Hold () { while ((SSPCON2 & 0b00011111) - (SSPSTAT & 0b00000100)); // controleer dit op registers om er zeker van te zijn dat de IIC niet bezig is }
Void I2C_Begin () en ongeldig I2C_End ()
Elke keer dat we gegevens schrijven of lezen met behulp van de I2C-bus , moeten we de I2C-verbinding beginnen en beëindigen. Om een I2C-communicatie te beginnen, moeten we de SEN-bit instellen en om de communicatie te beëindigen, moeten we de PEN-statusbit instellen. Voordat we een van deze bits omschakelen, moeten we ook controleren of de I2C-bus bezet is door de functie I2C_Hold te gebruiken zoals hierboven besproken.
leegte I2C_Begin () { I2C_Hold (); // Houd het programma vast, I2C is bezet SEN = 1; // Begin IIC pg85 / 234 } leegte I2C_End () { I2C_Hold (); // Houd het programma vast, I2C is bezig PEN = 1; // Einde IIC pg85 / 234 }
Ongeldig I2C_Write ()
De schrijffunctie wordt gebruikt om alle gegevens van de mastermodule naar de salve-module te sturen. Deze functie wordt normaal gesproken gebruikt na een I2C-beginfunctie en wordt gevolgd door een I2C-eindfunctie. De gegevens die naar de IIC-bus moeten worden geschreven, worden door de variabele gegevens geleid. Deze gegevens worden vervolgens in het SSPBUF-bufferregister geladen om ze via de I2C-bus te verzenden.
Normaal gesproken wordt voordat er gegevens worden geschreven een adres geschreven, dus u zou de schrijffunctie twee keer moeten gebruiken, één keer om het adres in te stellen en de andere keer om de feitelijke gegevens te verzenden.
ongeldig I2C_Write (niet-ondertekende gegevens) { I2C_Hold (); // Houd het programma vast, I2C is bezig SSPBUF = data; // pg82 / 234 }
ongetekende korte I2C_Read ()
De laatste functie die we moeten kennen, is de functie I2C_Read . Deze functie wordt gebruikt om de gegevens te lezen die momenteel op de I2C-bus staan. Het wordt gebruikt na het vragen van een slaaf om een waarde naar de bus te schrijven. De waarde die wordt ontvangen, staat in de SSPBUF, we kunnen die waarde overbrengen naar elke variabele voor onze bewerking.
Tijdens een I2C-communicatie zal de slaaf na het verzenden van de door de master gevraagde gegevens een andere bit verzenden die de bevestigingsbit is, deze bit moet ook door de master worden gecontroleerd om er zeker van te zijn dat de communicatie succesvol was. Na het controleren van de ACKDT-bit voor bevestiging, moet deze worden ingeschakeld door de ACKEN-bit in te stellen.
unsigned short I2C_Read (unsigned short ack) { unsigned short incoming; I2C_Hold (); RCEN = 1; I2C_Hold (); inkomend = SSPBUF; // haal de gegevens op die zijn opgeslagen in SSPBUF I2C_Hold (); ACKDT = (ack)? 0: 1; // controleer of ack-bit ACKEN = 1 heeft ontvangen; // pg 85/234 retour inkomend; }
Dat is het, deze functies zouden voldoende moeten zijn om een I2C-communicatie op te zetten en gegevens van een apparaat te schrijven of te lezen. Merk ook op dat er veel andere functionaliteiten zijn die de I2C-communicatie kan uitvoeren, maar voor de eenvoud bespreken we ze hier niet. U kunt altijd de datasheet raadplegen om de volledige werking van het
De volledige code met header-bestand voor PIC16F877A I2C-communicatie kan worden gedownload via de link.
Programmeren met behulp van de I2C-headerbestanden:
Nu we hebben geleerd hoe een I2C-communicatie werkt en hoe we het daarvoor gemaakte header-bestand kunnen gebruiken, gaan we een eenvoudig programma maken waarin we het header-bestand gebruiken en enkele waarden naar de I2C-regels schrijven. We zullen dit programma dan simuleren en controleren of deze waarden op de bus worden geschreven.
Zoals altijd begint het programma met het instellen van de configuratiebits en het instellen van de klokfrequentie op 20 MHz, zoals hieronder weergegeven
#pragma config FOSC = HS // Oscillator Selectie bits (HS oscillator) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT uitgeschakeld) #pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT ingeschakeld) # pragma config BOREN = ON // Brown-out Reset Enable bit (BOR ingeschakeld) #pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digitale I / O, HV aan MCLR moet worden gebruikt voor het programmeren) #pragma config CPD = OFF // Data EEPROM-geheugencodebeschermingsbit (Data EEPROM- codebescherming uit) #pragma config WRT = OFF // Flash Programmageheugen Write Enable bits (schrijfbeveiliging uit; alle programmageheugen kan worden geschreven door EECON controle) #pragma config CP = OFF // Flash-programmageheugencodebescherming bit ( codebescherming uit) #define _XTAL_FREQ 20000000
De volgende stap zou zijn om het header-bestand toe te voegen waarover we zojuist hebben gesproken. Het header-bestand heet PIC16F877a_I2C.h en kan worden gedownload via de link die we hierboven hebben besproken. Zorg ervoor dat het header-bestand is toegevoegd aan het header-bestand van uw projectlijst, de structuur van uw projectbestand zou er als volgt uit moeten zien
Nadat u ervoor heeft gezorgd dat het header-bestand aan uw projectbestand is toegevoegd, neemt u het header-bestand op in het C-hoofdbestand
# omvatten
Binnen de while- lus beginnen we met de I2C-communicatie, schrijven enkele willekeurige waarden naar de I2C-bus en beëindigen vervolgens de I2C-communicatie. De willekeurige waarden die ik heb gekozen zijn D0, 88 en FF. U kunt elke gewenste waarde invoeren. Maar onthoud die waarden, want we zullen ze verifiëren in onze simulatie.
while (1) { I2C_Begin (); I2C_Write (0xD0); I2C_Write (0x88); I2C_Write (0xFF); I2C_End (); __delay_ms (1000); }
Het complete programma vindt u onderaan de pagina, u kunt dat gebruiken of het complete zip-bestand van het programma van hieruit downloaden. Nadat u het programma hebt opgehaald, compileert u het en maakt u zich klaar voor simulatie.
Proteus Simulatie:
Proteus heeft een mooi instrument genaamd I2C debugger dat gebruikt kan worden om de data op een I2C bus te lezen, dus laten we er een circuit mee bouwen en controleren of de data succesvol geschreven wordt. Het volledige schakelschema wordt hieronder weergegeven
Laad het hex-bestand dat door ons programma is gegenereerd door te dubbelklikken op de Microcontroller. Simuleer vervolgens het programma. U ziet een pop-upvenster waarin alle informatie over de I2C-bus wordt weergegeven. Het venster voor ons programma wordt hieronder weergegeven.
Als je de gegevens die worden geschreven goed bekijkt, kun je zien dat ze dezelfde zijn als die we in ons programma hebben geschreven. De waarden zijn D0, 88 en FF. De waarden worden voor elke seconde geschreven, dus de tijd wordt ook bijgewerkt zoals hieronder weergegeven. De blauwe pijl geeft aan dat het van master naar slave is geschreven, anders zou het in tegengestelde richting wijzen. Hieronder ziet u een nadere blik op de verzonden gegevens.
Dit is slechts een glimp van wat I2C kan doen, het kan ook gegevens lezen en schrijven naar meerdere apparaten. We zullen meer over I2C behandelen in onze komende tutorials door verschillende modules te koppelen die werken met het I2C-protocol.
Ik hoop dat je het project hebt begrepen en er iets nuttigs van hebt geleerd. Als je twijfels hebt, plaats ze dan in de commentaarsectie hieronder of gebruik de forums voor technische hulp.
De volledige code is hieronder gegeven; u kunt hier header-bestanden met alle code downloaden.