- Какво представлява протоколът за комуникация SPI?
- Как работи SPI протоколът?
- Разлика между I2C и SPI комуникация
- SPI с PIC16F877A с помощта на компилатор XC8:
- Обяснение на заглавния файл на SPI:
- Основна програма Обяснение:
- Симулиране на PIC с SPI дебъгер:
Микроконтролерите PIC са мощна платформа, предоставена от микрочип за вградени проекти; неговата универсална природа му е позволила да намери пътища в много приложения и тепърва ще расте много. Ако сте следвали нашите уроци за PIC, тогава бихте забелязали, че вече сме обхванали широка гама от уроци за PIC микроконтролер, започвайки от самите основи. В същия поток пристъпваме към изучаването на комуникационните протоколи, налични с PIC, и как да ги използваме. Вече покрихме I2C с PIC Microcontroller.
В обширната система от вградени приложения никой микроконтролер не може да изпълнява всички дейности сам. На даден етап от времето той трябва да комуникира с други устройства, за да споделя информация, има много различни видове комуникационни протоколи за споделяне на тази информация, но най-използваните са USART, IIC, SPI и CAN. Всеки комуникационен протокол има своите предимства и недостатъци. Нека се съсредоточим върху протокола SPI засега, тъй като това ще научим в този урок.
Какво представлява протоколът за комуникация SPI?
Терминът SPI означава „ сериен периферен интерфейс “. Това е общ комуникационен протокол, който се използва за изпращане на данни между два микроконтролера или за четене / запис на данни от датчик към микроконтролер. Използва се и за комуникация със SD карти, регистри за смяна, контролери за дисплей и много други.
Как работи SPI протоколът?
SPI комуникацията е синхронна комуникация, което означава, че работи с помощта на тактов сигнал, който се споделя между двете устройства, които обменят данните. Също така това е пълна дуплексна комуникация, защото може да изпраща и получава данни с помощта на отделна шина. В съобщението SPI изисква 5 жици, за да работят. По-долу е показана проста SPI комуникационна схема между главен и подчинен
Петте проводника, необходими за комуникацията, са SCK (сериен часовник), MOSI (Master Out Slave In), MISO (Master In Slave Out) и SS (Slave Select). SPI комуникацията винаги се осъществява само между главен и подчинен. Капитанът може да има няколко роби, свързани с него. Капитанът е отговорен за генерирането на тактовия импулс и същото се споделя с всички роби. Също така всички комуникации могат да бъдат инициирани само от капитана.
SCK щифтът (известен още като SCL-сериен часовник) споделя сигнала на часовника, генериран от главния модул, с подчинените. ПИН MOSI (известен още като SDA - изход за серийни данни) се използва за изпращане на данните от главния модул към матрицата. ПИНът MISO (известен още като SDI - Serial Data In) се използва за получаване на данните от salve до главния. Можете също да следвате стрелката на горната фигура, за да разберете движението на данни / сигнал. И накрая, SS щифтът (известен още като CS –Chip select) се използва, когато има повече от един подчинени модула, свързани към главния. Това може да се използва за избор на необходимия роб. В схемата по-долу е показана примерна верига, при която повече от един slave е свързан с главен за SPI комуникация.
Разлика между I2C и SPI комуникация
Вече научихме I2C комуникацията с PIC и затова трябва да сме запознати с това как работи I2C и къде можем да ги използваме, както I2C може да се използва за интерфейс на RTC модул. Но сега, защо ни е необходим протокол SPI, след като вече имаме I2C. Причината е, че комуникациите I2C и SPI са предимства по свой начин и следователно са специфични за приложението.
До известна степен може да се счита, че I2C комуникацията има някои предимства пред SPI комуникацията, тъй като I2C използва по-малък брой пинове и става много удобен, когато има голям брой подчинени устройства, свързани към шината. Но недостатъкът на I2C е, че той има една и съща шина за изпращане и получаване на данни и следователно е сравнително бавен. Така че изцяло въз основа на приложението можете да решите между SPI и I2C протокола за вашия проект.
SPI с PIC16F877A с помощта на компилатор XC8:
Достатъчно от основите, сега нека научим как можем да използваме SPI комуникация на микроконтролера PIC16F877A, използвайки MPLABX IDE и XC8 компилатор. Преди да започнем да изясним, че този урок говори само за SPI в PIC16F877a, използвайки компилатор XC8, процесът ще бъде същият и за други микроконтролери, но може да са необходими леки промени. Също така не забравяйте, че за усъвършенствани микроконтролери като серията PIC18F, самият компилатор може да има вградена библиотека за използване на функциите SPI, но за PIC16F877A нищо подобно не съществува, така че нека да го изградим сами. Обясняваната тук библиотека ще бъде дадена като заглавен файл за изтегляне отдолу, който може да се използва за PIC16F877A за комуникация с други SPI устройства.
В този урок ще напишем малка програма, която използва SPI комуникация за запис и четене на данни от SPI шината. След това ще проверим същото, като използваме симулация на Proteus. Целият код, свързан с SPI регистрите, ще бъде направен в заглавния файл, наречен PIC16f877a_SPI.h. По този начин можем да използваме този заглавен файл във всички наши предстоящи проекти, в които се изисква SPI комуникация. А вътре в основната програма просто ще използваме функциите от заглавния файл. Пълният код заедно със заглавния файл можете да изтеглите от тук.
Обяснение на заглавния файл на SPI:
Вътре в заглавния файл трябва да инициализираме SPI комуникацията за PIC16F877a. Както винаги най-доброто място за започване е таблицата с данни PIC16F877A. Регистрите, които контролират SPI комуникацията за PIC16F8777a, са SSPSTAT и SSPCON регистърът. Можете да научите за тях на стр. 74 и 75 от листа с данни.
Има много опции за параметри, които трябва да бъдат избрани при инициализиране на SPI комуникацията. Най-често използваната опция е тактовата честота ще бъде настроена на Fosc / 4 и ще бъде направена в средата, а часовникът ще бъде настроен като нисък в идеално състояние. Така че ние също използваме същата конфигурация за нашия заглавен файл, можете лесно да ги промените, като промените съответните битове.
SPI_Initialize_Master ()
Функцията за инициализиране на SPI Master се използва за стартиране на комуникацията SPI като главен. Вътре в тази функция задаваме съответните щифтове RC5 и RC3 като изходни щифтове. След това конфигурираме SSPTAT и SSPCON регистъра, за да включим SPI комуникациите
void SPI_Initialize_Master () { TRISC5 = 0; // SSPSTAT = 0b00000000; // стр. 74/234 SSPCON = 0b00100000; // стр. 75/234 TRISC3 = 0; // Комплект като изход за режим роб }
SPI_Initialize_Slave ()
Тази функция се използва, за да настрои микроконтролера да работи в подчинен режим за SPI комуникация. По време на подчинен режим щифтът RC5 трябва да бъде зададен като изход, а щифтът RC3 трябва да бъде зададен като вход. SSPSTAT и SSPCON са настроени по един и същ начин както за подчинения, така и за главния.
void SPI_Initialize_Slave () { TRISC5 = 0; // SDO щифтът трябва да бъде деклариран като изход SSPSTAT = 0b00000000; // стр. 74/234 SSPCON = 0b00100000; // стр. 75/234 TRISC3 = 1; // Задайте като изходящ за главен режим }
SPI_Write (входящ знак)
Функцията SPI Write се използва за записване на данни в SPI шината. Той получава информацията от потребителя чрез входящата променлива и след това я използва, за да премине към буферния регистър. SSPBUF ще бъде изчистен в последователния импулс на часовника и данните ще се изпращат в шината бит по бит.
void SPI_Write (char входящ) { SSPBUF = входящ; // Записване на дадените от потребителя данни в буфер }
SPI_Ready2Read ()
Функцията SPI Ready to Read се използва за проверка дали данните в SPI шината са получени изцяло и дали могат да бъдат прочетени. Регистърът SSPSTAT има бит, наречен BF, който ще се зададе, след като данните бъдат получени изцяло, така че проверяваме дали този бит е зададен, ако не е зададен, тогава трябва да изчакаме, докато не бъде настроен да чете нещо от SPI шината.
неподписан SPI_Ready2Read () { if (SSPSTAT & 0b00000001) връща 1; иначе връща 0; }
SPI_Read ()
SPI Read се използва за четене на данните от SPI шината в микроконтролера. Данните, присъстващи в шината SPI, ще се съхраняват в SSPBUF, трябва да изчакаме, докато пълните данни се съхраняват в буфера и след това можем да ги прочетем в променлива. Проверяваме BF бита на SSPSTAT регистъра, преди да прочетем буфера, за да сме сигурни, че приемането на данни е завършено.
char SPI_Read () // Прочетете получените данни { while (! SSPSTATbits.BF); // Задръжте, докато се зададе бит BF, за да сте сигурни, че пълните данни са прочетени return (SSPBUF); // връщане на прочетените данни }
Основна програма Обяснение:
Функциите, обяснени в горния раздел, ще бъдат в заглавния файл и могат да бъдат извикани в основния c файл. Така че нека напишем малка програма, за да проверим дали SPI комуникацията работи. Просто ще напишем малко данни в SPI шината и ще използваме симулацията на proteus, за да проверим дали същите данни се получават в SPI дебъгера.
Както винаги стартирайте програмата, като зададете конфигурационни битове и след това е много важно да добавите заглавния файл, който току-що обяснихме в програмата, както е показано по-долу
#include
Ако сте отворили програмата от zip файла, изтеглен по-горе, тогава по подразбиране заглавният файл ще присъства в директорията на заглавния файл на вашия проект. В противен случай трябва да добавите заглавния файл ръчно във вашия проект, след като добавите вашите проектни файлове, ще изглежда по-долу
Вътре в основния файл трябва да инициализираме PIC като Master за SPI комуникация и след това в безкраен цикъл while ще напишем произволни три шестнадесетични стойности в SPI шината, за да проверим дали получаваме същото по време на симулация.
void main () { SPI_Initialize_Master (); докато (1) { SPI_Write (0X0A); __забавяне_ms (100); SPI_Write (0X0F); __забавяне_ms (100); SPI_Write (0X15); __забавяне_ms (100); } }
Забележете, че случайните стойности, използвани в програмата, са 0A, 0F и 15 и те са шестнадесетични стойности, така че трябва да видим същото по време на симулация. Това е, че кодът е свършен, това е само пример, но можем да използваме същата методология за комуникация с други MCU или с други сензорни модули, работещи по протокол SPI.
Симулиране на PIC с SPI дебъгер:
Сега, когато нашата програма е готова, можем да я компилираме и след това да продължим със симулацията. Proteus има хубава удобна функция, наречена SPI дебъгер , която може да се използва за наблюдение на данните през SPI шина. Затова използваме същото и изграждаме верига, както е показано по-долу.
Тъй като в симулацията има само едно SPI устройство, ние не използваме SS щифта и когато не се използва, той трябва да бъде заземен, както е показано по-горе. Просто заредете шестнадесетичния файл в микроконтролера PIC16F877A и кликнете върху бутона за възпроизвеждане, за да симулирате нашата програма. След като стартира симулацията, ще получите изскачащ прозорец, който показва данните в SPI шината, както е показано по-долу
Нека да разгледаме по-отблизо постъпващите данни и да проверим дали те са същите като тези, които сме написали в нашата програма.
Данните се получават в същия ред, който сме написали в нашата програма и същите са подчертани за вас. Можете също така да опитате да симулирате програма за комуникация с два PIC микроконтролера, използвайки протокол SPI. Трябва да програмирате единия PIC като главен, а другия като slave. Всички необходими заглавни файлове за тази цел са вече дадени в заглавния файл.
Това е само поглед върху това, което SPI може да направи, може също да чете и записва данни на множество устройства. Ще разгледаме повече за SPI в предстоящите ни уроци, като свързваме различни модули, които работят с протокол SPI.
Надявам се, че сте разбрали проекта и сте научили нещо полезно от него. Ако имате някакви съмнения, публикувайте ги в раздела за коментари по-долу или използвайте форумите за техническа помощ.
Пълният основен код е даден по-долу; можете да изтеглите заглавни файлове с целия код от тук