- Vad är I2C-kommunikationsprotokoll?
- Hur fungerar I2C-kommunikation?
- Var ska jag använda I2C-kommunikation?
- I2C med PIC16F877a med XC8 Compiler
- Programmering med I2C-huvudfiler:
- Proteus-simulering:
PIC Microcontrollers är en kraftfull plattform som tillhandahålls av mikrochip för inbäddade projekt, dess mångsidiga natur har gjort det möjligt att hitta vägar till många applikationer och fasen pågår fortfarande. Om du har följt våra PIC-självstudier skulle du ha lagt märke till att vi redan har täckt ett brett utbud av självstudier om PIC-mikrokontroller med utgångspunkt från de grundläggande. Sedan nu har vi täckt grunderna vi kan komma in på mer intressanta saker som kommunikationsportalen.
I det stora systemet med inbäddade applikationer kan ingen mikrokontroller utföra alla aktiviteter på egen hand. Vid någon tidpunkt måste den kommunicera med andra enheter för att dela information, det finns många olika typer av kommunikationsprotokoll för att dela informationen, men de mest använda är USART, IIC, SPI och CAN. Varje kommunikationsprotokoll har sina egna fördelar och nackdelar. Låt oss fokusera på IIC-delen för nu eftersom det är vad vi ska lära oss i denna handledning.
Vad är I2C-kommunikationsprotokoll?
Termen IIC står för " Inter Integrated Circuits ". Det betecknas normalt som I2C eller I kvadrat C eller till och med som 2-tråds gränssnittsprotokoll (TWI) på vissa ställen men allt betyder detsamma. I2C är ett synkron kommunikationsprotokoll som betyder att båda enheterna som delar informationen måste dela en gemensam klocksignal. Den har bara två ledningar för att dela information varav den ena används för kocksignalen och den andra används för att skicka och ta emot data.
Hur fungerar I2C-kommunikation?
I2C-kommunikation introducerades först av Phillips. Som sagt tidigare har den två ledningar, dessa två ledningar kommer att anslutas över två enheter. Här kallas en enhet en master och den andra enheten kallas slav. Kommunikation bör och kommer alltid att ske mellan två en mästare och en slav. Fördelen med I2C-kommunikation är att mer än en slav kan anslutas till en mästare.
Den fullständiga kommunikationen sker via dessa två ledningar, nämligen Serial Clock (SCL) och Serial Data (SDA).
Serial Clock (SCL): Delar klocksignalen som genereras av mastern med slaven
Serial Data (SDA): Skickar data till och från mellan Master och slav.
Vid varje given tidpunkt är det bara befälhavaren som kan initiera kommunikationen. Eftersom det finns mer än en slav i bussen måste befälhavaren hänvisa till varje slav med en annan adress. När den adresseras kommer endast salven med den specifika adressen att svara tillbaka med informationen medan de andra slutar. På så sätt kan vi använda samma buss för att kommunicera med flera enheter.
Var ska jag använda I2C-kommunikation?
I2C-kommunikation används endast för kortdistanskommunikation. Det är verkligen tillförlitligt i viss utsträckning eftersom det har en synkroniserad klockpuls för att göra det smart. Detta protokoll används främst för att kommunicera med sensorer eller andra enheter som måste skicka information till en master. Det är mycket praktiskt när en mikrokontroller måste kommunicera med många andra slavmoduler med ett minimum av endast ledningar. Om du letar efter en långväga kommunikation bör du prova RS232 och om du letar efter mer tillförlitlig kommunikation bör du prova SPI-protokollet.
I2C med PIC16F877a med XC8 Compiler
Tillräckligt med introduktioner, kan komma in i det och lära oss hur vi kan använda en mikrokontroller för att utföra I2C-kommunikation. Innan vi börjar göra det klart att denna handledning bara talar om I2C i PIC16F877a med hjälp av XC8-kompilator, kommer processen att vara densamma för andra mikrokontroller men små förändringar kan krävas. Kom också ihåg att för avancerade mikrokontroller som PIC18F-serien kan kompilatorn själv ha något inbyggt bibliotek för att använda I2C-funktionerna, men för PIC16F877A finns inget sådant så låt oss bygga ett på egen hand. Biblioteket som förklaras här kommer att ges som en rubrikfil för nedladdning längst ner som kan användas för PIC16F877A för att kommunicera med andra I2C-enheter.
Som alltid är det bästa stället att börja någonting vårt datablad. Leta efter detaljer om I2C i databladet och kontrollera vilka register som måste konfigureras. Jag kommer inte att förklara i detalj eftersom databladet redan har gjort det åt dig. Längre ner kommer jag att förklara de olika funktionerna i rubrikfilen och deras ansvar i programmet.
ogiltig I2C_Initialize ()
Initieringsfunktionen används för att berätta för mikrokontrollern att vi ska använda I2C-protokollet. Detta kan göras genom att ställa in nödvändiga bitar i SSPCON- och SSPCON2-registret. Det första steget skulle vara att deklarera IIC-stiften som ingångsstift, här ska stiften RC3 och RC4 användas för I2C-kommunikation så vi deklarerar dem som ingångsstift. Därefter ska vi ställa in SSPCON och SSPCON2 som är ett MSSP-kontrollregister. Vi använder PIC i IIC-masterläge med en klockfrekvens på FOSC / (4 * (SSPADD + 1)). Se sidnumren för databladet som nämns i kommentarraderna nedan för att förstå varför just det registret är inställt på det sättet.
Så nu måste vi ställa in klockfrekvensen, klockfrekvensen för olika applikationer kan variera, därför får vi valet från användaren genom variabeln feq_k och använder den i våra formler för att ställa in SSPADD-registret.
ogiltig I2C_Initialize (const osignerad lång feq_K) // Börja IIC som master { TRISC3 = 1; TRISC4 = 1; // Ställ in SDA- och SCL-stift som ingångsstift SSPCON = 0b00101000; // pg84 / 234 SSPCON2 = 0b00000000; // pg85 / 234 SSPADD = (_XTAL_FREQ / (4 * feq_K * 100)) - 1; // Ställa in klockhastighet pg99 / 234 SSPSTAT = 0b00000000; // pg83 / 234 }
Ogiltig I2C_Hold ()
Nästa viktiga funktion är I2C_hold- funktionen som används för att hålla exekveringen av enheten tills den aktuella I2C-operationen är klar. Vi måste kontrollera om I2C-operationerna måste hållas innan någon ny operation startas. Detta kan göras genom att kontrollera registret SSPSTAT och SSPCON2. SSPSTAT innehåller information om status för I2C-bussen.
Programmet kan tyckas vara lite komplicerat eftersom det involverar en "och" och en "eller" operatör. När du bryter det som
SSPSTAT & 0b00000100 SSPCON2 & 0b00011111
</s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s>
Det betyder att vi ser till att andra bitar på SSPSTAT är noll och på liknande sätt bitar från 0 till 4 är noll på SSPCON2. Sedan kombinerar vi alla dessa för att kontrollera att resultatet är noll. Om resultatet är noll kommer programmet att fortsätta om det inte kommer att hålla det tills det blir noll eftersom den används i ett tag loop.
ogiltigt I2C_Hold () { medan ((SSPCON2 & 0b00011111) - (SSPSTAT & 0b00000100)); // kontrollera detta i register för att se till att IIC inte pågår }
Ogiltig I2C_Begin () och ogiltig I2C_End ()
Varje gång vi skriver eller läser data med hjälp av I2C-bussen bör vi börja och avsluta I2C-anslutningen. För att starta en I2C-kommunikation måste vi ställa in SEN-bit och för att avsluta kommunikationen måste vi ställa in PEN-statusbit. Innan vi byter till någon av dessa bitar bör vi också kontrollera om I2C-bussen är upptagen med funktionen I2C_Hold som diskuterats ovan.
ogiltig I2C_Begin () { I2C_Hold (); // Håll programmet är I2C är upptagen SEN = 1; // Börja IIC pg85 / 234 } ogiltig I2C_End () { I2C_Hold (); // Håll programmet är I2C är upptagen PEN = 1; // Avsluta IIC pg85 / 234 }
Ogiltig I2C_Write ()
Skrivfunktionen används för att skicka data från mastermodulen till salvmodulen. Denna funktion används normalt efter en I2C-startfunktion och följs av en I2C-slutfunktion. Data som måste skrivas till IIC-bussen skickas genom variabeldata. Dessa data laddas sedan in i SSPBUF-buffertregistret för att skicka dem över I2C-bussen.
Normalt skrivs en adress innan du skriver data så att du måste använda skrivfunktionen två gånger, en gång för att ställa in adressen och den andra gången för att skicka den faktiska informationen.
ogiltigt I2C_Write (osignerade data) { I2C_Hold (); // Håll programmet är I2C är upptagen SSPBUF = data; // pg82 / 234 }
osignerad kort I2C_Read ()
Den sista funktionen som vi måste veta är I2C_Read- funktionen. Denna funktion används för att läsa de data som för närvarande finns på I2C-bussen. Den används efter att ha bett om en slav att skriva något värde till bussen. Värdet som tas emot kommer att finnas i SSPBUF. Vi kan överföra det värdet till vilken variabel som helst för vår verksamhet.
Under en I2C-kommunikation skickar slaven efter att ha skickat data som begärts av mastern en annan bit som är bekräftelsebiten. Denna bit ska också kontrolleras av mastern för att säkerställa att kommunikationen lyckades. Efter att ha kontrollerat ACKDT-biten för bekräftelse bör den aktiveras genom att ställa in ACKEN-biten.
osignerad kort I2C_Read (osignerad kort ack) { osignerad kort inkommande; I2C_Hold (); RCEN = 1; I2C_Hold (); inkommande = SSPBUF; // få data sparade i SSPBUF I2C_Hold (); ACKDT = (ack) 0 0: 1; // kontrollera om ack-bit mottagen ACKEN = 1; // sid 85/234 återkommande; }
Det är det, dessa funktioner borde vara tillräckliga för att skapa en I2C-kommunikation och skriva eller läsa data från en enhet. Observera också att det finns många andra funktioner som I2C-kommunikationen kan utföra men för enkelhets skull diskuterar vi inte dem här. Du kan alltid hänvisa databladet för att få veta hur funktionen fungerar
Den kompletta koden med rubrikfil för PIC16F877A I2C-kommunikation kan laddas ner från länken.
Programmering med I2C-huvudfiler:
Nu när vi har lärt oss hur en I2C-kommunikation fungerar och hur vi kan använda rubrikfilen som skapats för den, låt oss göra ett enkelt program där vi kommer att använda huvudfilen och skriva några värden till I2C-raderna. Vi simulerar sedan detta program och kontrollerar om dessa värden skrivs på bussen.
Som alltid börjar programmet med att ställa in konfigurationsbitarna och ställa in klockfrekvensen till 20 MHz enligt nedan
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled) # pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled ) #pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 är digital I / O, HV på MCLR måste användas för programmering) #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off) #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all programm memory) kan skrivas till av EECON-kontroll) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) #define _XTAL_FREQ 20000000
Nästa steg skulle vara att lägga till rubrikfilen som vi just diskuterade om. Rubrikfilen heter PIC16F877a_I2C.h och kan laddas ner från länken som vi diskuterade ovan. Se till att rubrikfilen läggs till i huvudfilen i din projektlista, din projektfilstruktur ska se ut så här
Efter att ha sett till att huvudfilen läggs till i din projektfil inkluderar du huvudfilen i huvud-C-filen
#omfatta
Inuti while- slingan börjar vi I2C-kommunikationen skriva några slumpmässiga värden till I2C-bussen och sedan avsluta I2C-kommunikationen. De slumpmässiga värdena som jag har valt är D0, 88 och FF. Du kan mata in önskade värden. Men kom ihåg dessa värden eftersom vi kommer att verifiera dem i vår simulering.
medan (1) { I2C_Begin (); I2C_Write (0xD0); I2C_Write (0x88); I2C_Write (0xFF); I2C_End (); __fördröja_ms (1000); }
Det fullständiga programmet finns längst ner på sidan kan du använda det eller ladda ned hela zip-filen i programmet härifrån. Efter att programmet har sammanställts och gör dig redo för simulering.
Proteus-simulering:
Proteus har ett trevligt instrument som heter I2C debugger som kan användas för att läsa data på en I2C-buss, så låt oss bygga en krets med den och kontrollera om data skrivs framgångsrikt. Det fullständiga kretsschemat visas nedan
Ladda hexfilen som genererades av vårt program genom att dubbelklicka på Microcontroller. Simulera sedan programmet. Du kommer att märka att ett fönster dyker upp som visar all information om I2C-bussen. Fönstret för vårt program visas nedan.
Om du tittar noga på de data som skrivs kan du märka att de är desamma som vi skrev i vårt program. Värdena är D0, 88 och FF. Värdena skrivs var 1: e sekund så tiden uppdateras också enligt nedan. Den blå pilen indikerar att den är skriven från master till slav, den skulle peka i motsatt riktning om annars. En närmare titt på de data som skickas visas nedan.
Detta är bara en glimt av vad I2C kan göra, det kan också läsa och skriva data till flera enheter. Vi kommer att täcka mer om I2C i våra kommande handledning genom att koppla ihop olika moduler som fungerar med I2C-protokollet.
Hoppas att du förstod projektet och lärde dig något användbart av det. Om du är osäker kan du lägga upp dem i kommentarfältet nedan eller använda forumen för teknisk hjälp.
Komplett kod har angivits nedan; du kan hämta headerfiler med all kod härifrån.