- Какво е I2C протокол за комуникация?
- Как работи I2C Комуникацията?
- Къде да използвам I2C комуникация?
- I2C с PIC16F877a с помощта на компилатор XC8
- Програмиране с помощта на заглавните файлове на I2C:
- Симулация на протея:
Микроконтролерите PIC са мощна платформа, предоставена от микрочип за вградени проекти, неговата гъвкава природа го е накарала да намира пътища в много приложения и фазата все още продължава. Ако сте следвали нашите уроци за PIC, тогава бихте забелязали, че вече сме обхванали широк набор от уроци за PIC микроконтролер, започвайки от самите основи. От сега обхващаме основите, по които можем да влезем в по-интересни неща като комуникационния портал.
В обширната система от вградени приложения никой микроконтролер не може да изпълнява всички дейности сам. На даден етап от времето той трябва да комуникира с други устройства, за да споделя информация, има много различни видове комуникационни протоколи за споделяне на тази информация, но най-използваните са USART, IIC, SPI и CAN. Всеки комуникационен протокол има своите предимства и недостатъци. Нека се съсредоточим върху IIC частта засега, тъй като това ще научим в този урок.
Какво е I2C протокол за комуникация?
Терминът IIC означава „ Интер интегрални схеми “. Обикновено се обозначава като I2C или I на квадрат C или дори като двупроводен интерфейсен протокол (TWI) на някои места, но всичко означава едно и също. I2C е синхронен комуникационен протокол, което означава, че и двете устройства, които споделят информацията, трябва да споделят общ тактов сигнал. Той има само два проводника за споделяне на информация, от които единият се използва за сигнала на крана, а другият се използва за изпращане и получаване на данни.
Как работи I2C Комуникацията?
I2C комуникацията е представена за първи път от Филипс. Както беше казано по-рано, той има два проводника, тези два проводника ще бъдат свързани през две устройства. Тук едното устройство се нарича master, а другото устройство се нарича slave. Комуникацията трябва и винаги ще се осъществява между двама Господар и Роб. Предимството на I2C комуникацията е, че повече от един slave може да бъде свързан към Master.
Пълната комуникация се осъществява чрез тези два проводника, а именно, сериен часовник (SCL) и сериен данни (SDA).
Сериен часовник (SCL): Споделя сигнала на часовника, генериран от главното устройство, с подчинения
Серийни данни (SDA): Изпраща данните към и между главния и подчинения.
Във всеки един момент само майсторът ще може да инициира комуникацията. Тъй като в шината има повече от един slave, капитанът трябва да се обърне към всеки slave, използвайки различен адрес. Когато бъде адресиран, само магистърът с този адрес ще отговори с информацията, докато останалите продължават да се отказват. По този начин можем да използваме една и съща шина за комуникация с множество устройства.
Къде да използвам I2C комуникация?
I2C комуникацията се използва само за комуникация на къси разстояния. Със сигурност е надежден до известна степен, тъй като има синхронизиран импулс на часовника, за да го направи умен. Този протокол се използва главно за комуникация със сензор или други устройства, които трябва да изпращат информация до главен. Много е удобно, когато микроконтролерът трябва да комуникира с много други подчинени модули, използвайки минимум само проводници. Ако търсите комуникация на дълги разстояния, трябва да опитате RS232, а ако търсите по-надеждна комуникация, трябва да опитате протокола SPI.
I2C с PIC16F877a с помощта на компилатор XC8
Достатъчно представяне, нека влезем в него и да научим как можем да използваме микроконтролер за извършване на I2C комуникация. Преди да започнем да изясним, че този урок говори само за I2C в PIC16F877a, използвайки компилатор XC8, процесът ще бъде същият и за други микроконтролери, но може да са необходими леки промени. Също така не забравяйте, че за усъвършенствани микроконтролери като серията PIC18F, самият компилатор може да има вградена библиотека, която да използва функциите I2C, но за PIC16F877A нищо подобно не съществува, така че нека създадем такъв сами. Обясняваната тук библиотека ще бъде дадена като заглавен файл за изтегляне отдолу, който може да се използва за PIC16F877A за комуникация с други I2C устройства.
Както винаги най-доброто място да започнете каквото и да е е нашият лист с данни. Потърсете подробности за I2C в таблицата с данни и проверете кои регистри трябва да бъдат конфигурирани. Няма да обяснявам подробно, тъй като таблицата с данни вече е направила това за вас. По-нататък ще обясня различните функции в заглавния файл и тяхната отговорност в програмата.
void I2C_Initialize ()
Функцията за инициализиране се използва, за да каже на микроконтролера, че ще използваме протокола I2C. Това може да стане чрез задаване на необходимите битове в регистъра SSPCON и SSPCON2. Първата стъпка би била да се декларират IIC щифтовете като входни щифтове, тук пиновете RC3 и RC4 трябва да се използват за I2C комуникация, така че ние ги декларираме като входни щифтове. След това трябва да зададем SSPCON и SSPCON2, който е MSSP контролни регистри. Работим с PIC в главен режим IIC с тактова честота FOSC / (4 * (SSPADD + 1)). Вижте номерата на страниците на листа с данни, споменати в редовете за коментари по-долу, за да разберете защо точно този регистър е настроен по този начин.
След това трябва да зададем тактовата честота, тактовата честота за различните приложения може да варира, поради което получаваме избора от потребителя чрез променливата feq_k и го използваме в нашите формули, за да зададем SSPADD регистъра.
void I2C_Initialize (const unsigned long feq_K) // Започнете IIC като master { TRISC3 = 1; TRISC4 = 1; // Задаване на SDA и SCL щифтове като входни щифтове SSPCON = 0b00101000; // pg84 / 234 SSPCON2 = 0b00000000; // pg85 / 234 SSPADD = (_XTAL_FREQ / (4 * feq_K * 100)) - 1; // Задаване на тактова скорост pg99 / 234 SSPSTAT = 0b00000000; // pg83 / 234 }
Празно I2C_Hold ()
Следващата важна функция е функцията I2C_hold, която се използва за задържане на изпълнението на устройството до завършване на текущата операция I2C. Трябва да проверим дали операциите I2C трябва да се проведат, преди да започнем нова операция. Това може да стане чрез проверка на регистъра SSPSTAT и SSPCON2. SSPSTAT съдържа информация за състоянието на I2C шината.
Програмата може да изглежда малко сложна, тъй като включва оператори „и“ и „или“. Когато го разбиете като
SSPSTAT & 0b00000100 SSPCON2 & 0b00011111
U
Това означава, че се уверяваме, че 2- ри бит на SSPSTAT е нула и по същия начин битовете от 0 до 4 са нула на SSPCON2. След това комбинираме всичко това, за да проверим дали резултатът е нула. Ако резултатът е нулев, програмата ще продължи, ако не, ще се задържи там, докато не получи нула, тъй като се използва в цикъл while .
void I2C_Hold () { while ((SSPCON2 & 0b00011111) - (SSPSTAT & 0b00000100)); // проверете това в регистрите, за да се уверите, че IIC не е в ход }
Void I2C_Begin () и void I2C_End ()
Всеки път, докато пишем или четем каквито и да е данни, използвайки I2C шината, трябва да започнем и да прекратим връзката I2C. За да започнем I2C комуникация, трябва да зададем бита SEN, а за да прекратим комуникацията трябва да зададем бита за статус PEN. Преди да превключите някой от тези битове, трябва също да проверим дали I2C шината е заета, като използваме функцията I2C_Hold, както е обсъдено по-горе.
void I2C_Begin () { I2C_Hold (); // Задръжте програмата е I2C е зает SEN = 1; // Започваме IIC pg85 / 234 } void I2C_End () { I2C_Hold (); // Задръжте програмата е I2C е зает PEN = 1; // Край на IIC pg85 / 234 }
Void I2C_Write ()
Функцията за запис се използва за изпращане на всякакви данни от главния модул към модула за помощ. Тази функция обикновено се използва след I2C начална функция и е последвана от I2C End функция. Данните, които трябва да бъдат записани в IIC шината, се предават през променливите данни. След това тези данни се зареждат в буферния регистър SSPBUF, за да се изпратят през I2C шината.
Обикновено, преди да напишете данни, ще бъде написан адрес, така че ще трябва да използвате функцията за запис два пъти, веднъж за задаване на адреса и другия път за изпращане на действителните данни.
void I2C_Write (неподписани данни) { I2C_Hold (); // Задръжте програмата е I2C е зает SSPBUF = данни; // pg82 / 234 }
неподписано кратко I2C_Read ()
Последната функция, за която трябва да знаем, е функцията I2C_Read . Тази функция се използва за четене на данните, които в момента са на I2C шината. Използва се след искане на роб да запише някаква стойност в шината. Получената стойност ще бъде в SSPBUF, можем да прехвърлим тази стойност към всяка променлива за нашата операция.
По време на I2C комуникация, подчиненият след изпращане на данните, изискани от Главния, ще изпрати друг бит, който е битът за потвърждение, този бит също трябва да бъде проверен от главния, за да се увери, че комуникацията е била успешна. След проверка на бита ACKDT за потвърждение, той трябва да бъде активиран чрез задаване на бита ACKEN.
неподписан кратък I2C_Read (неподписан къс ack) { неподписан кратък входящ; I2C_Hold (); RCEN = 1; I2C_Hold (); входящи = SSPBUF; // получаваме данните, запазени в SSPBUF I2C_Hold (); ACKDT = (ack)? 0: 1; // проверяваме дали ack bit е получил ACKEN = 1; // pg 85/234 връщане на входящи; }
Това е всичко, тези функции трябва да са достатъчни за настройка на I2C комуникация и запис или четене на данни от устройство. Също така имайте предвид, че има много други функционалности, които комуникацията I2C може да изпълнява, но за по-голяма простота не ги обсъждаме тук. Винаги можете да се обърнете към листа с данни, за да знаете пълната работа на
Пълният код с заглавен файл за комуникация PIC16F877A I2C може да бъде изтеглен от връзката.
Програмиране с помощта на заглавните файлове на I2C:
Сега, след като научихме как работи I2C комуникацията и как можем да използваме заглавния файл, създаден за нея, нека направим проста програма, в която ще използваме заглавния файл и ще запишем някои стойности в I2C редовете. След това ще симулираме тази програма и ще проверим дали тези стойности се записват в шината.
Както винаги програмата започва с настройка на битовете за конфигуриране и настройка на тактовата честота на 20 MHz, както е показано по-долу
#pragma config FOSC = HS // Осцилатор битове за избор (HS осцилатор) #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 // Нисковолтово (Едно захранване) Вътрешно верижно програмиране Бит за разрешаване (RB3 е цифров I / O, HV включен MCLR трябва да се използва за програмиране) #pragma config CPD = OFF // бит за защита на EEPROM данни за данни (защита на EEPROM код за данни изключена) #pragma config WRT = OFF // Flash Program Memory Активиране на битове (Защита срещу запис; цялата програмна памет може да се запише от контрола на EECON) #pragma config CP = OFF // Бит за защита на кода на паметта на Flash програма (защита на кода изключена) #define _XTAL_FREQ 20000000
Следващата стъпка ще бъде добавяне на заглавния файл, за който току-що обсъждахме. Заглавният файл е наречен PIC16F877a_I2C.h и може да бъде изтеглен от връзката, която обсъдихме по-горе. Уверете се, че заглавният файл е добавен в заглавния файл на вашия списък с проекти, вашата файлова структура на проекта трябва да изглежда така
След като се уверите, че заглавният файл е добавен към вашия файл на проекта, включете заглавния файл в основния C файл
#include
Вътре в цикъла while ще започнем I2C комуникацията да напишем няколко произволни стойности в I2C шината и след това да прекратим I2C комуникацията. Случайните стойности, които съм избрал, са D0, 88 и FF. Можете да въведете всякакви стойности, които искате. Но запомнете тези стойности, тъй като ние ще ги проверяваме в нашата симулация.
докато (1) { I2C_Begin (); I2C_Write (0xD0); I2C_Write (0x88); I2C_Write (0xFF); I2C_End (); __delay_ms (1000); }
Най- пълната програма може да се намери в долната част на страницата, можете да използвате, че или изтеглите пълното архивен файл на програмата от тук. След като получите програмата, компилирайте я и се пригответе за симулация.
Симулация на протея:
Proteus има хубав инструмент, наречен I2C дебъгер, който може да се използва за четене на данните на I2C шина, така че нека да изградим схема, използвайки я и да проверим дали данните се записват успешно. Пълната електрическа схема е показана по-долу
Заредете шестнадесетичния файл, генериран от нашата програма, като щракнете двукратно върху микроконтролера. След това симулирайте програмата. Ще забележите изскачащ прозорец, който ще покаже цялата информация за I2C шината. Прозорецът за нашата програма е показан по-долу.
Ако погледнете отблизо записваните данни, можете да забележите, че те са същите като тези, които сме написали в нашата програма. Стойностите са D0, 88 и FF. Стойностите се записват на всеки 1 сек, така че времето също се актуализира, както е показано по-долу. Синята стрелка показва, че е написана от главен на подчинен, че би била насочена в обратна посока, ако е друго. По-подробен поглед на изпращаните данни е показан по-долу.
Това е само поглед върху това, което I2C може да направи, може също да чете и записва данни на множество устройства. Ще разгледаме повече за I2C в предстоящите ни уроци, като свързваме различни модули, които работят с I2C протокол.
Надявам се, че сте разбрали проекта и сте научили нещо полезно от него. Ако имате някакви съмнения, публикувайте ги в раздела за коментари по-долу или използвайте форумите за техническа помощ.
Пълният код е даден по-долу; можете да изтеглите заглавни файлове с целия код от тук.