Съдържание:

I2C автобус за ATtiny и ATmega: 8 стъпки
I2C автобус за ATtiny и ATmega: 8 стъпки

Видео: I2C автобус за ATtiny и ATmega: 8 стъпки

Видео: I2C автобус за ATtiny и ATmega: 8 стъпки
Видео: AVR 48# Аппаратный I2C 2024, Юли
Anonim
I2C автобус за ATtiny и ATmega
I2C автобус за ATtiny и ATmega

Обичам микроконтролерите Atmel AVR! От създаването на системата за развитие на гето, описана в тази инструкция, нямах край на забавлението да експериментирам с AVR ATtiny2313 и по -специално с ATmega168. Дори стигнах дотам, че написах инструкция за използване на превключватели като входове и разширих концепцията на системата за развитие на гето до CPLD. По време на скорошен проект имах нужда от няколко превключвателя за настройка на контролни стойности. AVR не разполагаха с достатъчно I/O пинове, така че трябваше да мисля за нещо. Можех да опитам сложна система за въвеждане с клавиатура и дисплей, но ATtiny2313 щеше да свърши ресурсите. За щастие Atmel осигури начин за заобикаляне на този проблем, като включи интерфейс, който може да се свързва с допълнителни чипове (като памет или I/O портове) с прост двупроводен интерфейс. Точно така, като използваме само два I/O пина на AVR, можем да получим достъп до много допълнителни I/O пинове, както и до други ресурси. Този двупроводен интерфейс е официално известен като шина с интегрирана схема или просто I2C шина и е изобретен от NXP, когато все още е Philips Semiconductors. Ако четете този Instructable, вероятно сте чували за I2C шината и може би дори сте го използвали на PIC или друг микроконтролер. Въпреки че концептуално са много прости и поддържани от хардуерни ресурси на AVR, софтуерните драйвери все още са необходими за използване на I2C шината. Atmel предоставя бележки за приложението (вижте ресурсите по -късно в тази инструкция), но те са непълни и не показват никакви примери, освен комуникацията с друго AVR устройство. AVR. По -скоро ще предоставя разширени версии на драйверите на Atmel за устройства ATtiny2313 и ATmega168, ще обясня изискванията и ограниченията, които се прилагат при използването им, и ще ви покажа работещи примери за I2C устройства. След като работите с този Instructable, ще можете успешно да използвате I2C шината във вашите AVR проекти. Очевидно можете да пренебрегнете драйверите за миниатюрни или за MEGA, ако се интересувате само от един от тях. За тези, които се интересуват да научат повече за I2C шината, ще дам връзки към подходящ материал.

Стъпка 1: Какви са всички тези I2C неща?

Какви са всички тези I2C неща?
Какви са всички тези I2C неща?
Какви са всички тези I2C неща?
Какви са всички тези I2C неща?
Какви са всички тези I2C неща?
Какви са всички тези I2C неща?
Какво все пак са тези I2C неща?
Какво все пак са тези I2C неща?

I2C шината е проста двужична връзка, която може да свързва множество устройства заедно и да им позволява да обменят данни. В най -простата си форма има едно главно устройство, което комуникира с множество подчинени устройства. Всички устройства са свързани паралелно към двата проводника на I2C шината. Двата проводника са известни като SCL и SDA. SCL е тактовата линия и се управлява от главното устройство. SDA е двупосочна линия за данни. За да прехвърли данни, капитанът изпраща подчинен адрес, комбиниран с еднобитов флаг за четене/запис. Ако желаете запис, капитанът ще продължи да изпраща данни до адресирания подчинен. Ако се поиска четене, подчиненият ще отговори с данни. За да координират транзакциите, линиите SCL и SDA се манипулират от главния и подчинения, за да сигнализират няколко условия. Те включват START, STOP, ACK (потвърждение) и NAK (без потвърждение). Подробностите за тези условия се обработват от шофьорите. Истинските отрепки сред вас могат да научат всички подробности в връзките, предоставени в края на тази инструкция. Електрическите изисквания са доста прости. Капитанът и подчинените устройства трябва да използват едно и също ниво за Vcc, основанията трябва да бъдат свързани и линиите SCL и SDA трябва да бъдат изтеглени до Vcc. Стойността на издърпващите се резистори се определя точно чрез изчисление въз основа на общия капацитет на шината, но на практика може да бъде почти всяка стойност между 1,8K и 10K. Започвам с 5.1K и използвам по -ниски стойности, докато не работи. Това обикновено не е проблем, освен ако нямате много устройства или дълги кабели между устройствата. Номиналната скорост на данни на I2C шината е 100Kbits/секунда. Скорости от 400Kbits/секунда, 1Mbits/секунда и след това също са възможни, но не се поддържат от драйверите в тази инструкция. Всички I2C устройства ще работят със 100Kbits/секунда. Всеки ATtiny2313 и ATmega168 реализират I2C шината по различен начин. ATtiny2313 използва хардуер за универсален сериен интерфейс (USI) - който може да се използва и за SPI шината. ATmega168 има специален хардуер за I2C шината, известен като двужичен интерфейс (TWI). След като драйверите бъдат написани, тези разлики са най -вече прозрачни за потребителя. Една съществена разлика е в софтуера: ATmega168 I2C драйверът се управлява чрез прекъсване, докато този за ATtiny2313 не. Това означава, че програмата ATmega168 не трябва да чака излъчването на I2C данни, а трябва само да изчака, преди да започне друго прехвърляне, или докато данните пристигнат от операция за четене. Примерите и дискусията, които следва да направят това ясни. I2C адресите са дълги 7 бита, така че до 127 устройства могат да бъдат в шината, ако всяко има уникален адрес. Както е показано на фигурата, този 7 -битов адрес се измества наляво един бит и най -малко значимият бит се използва за отбелязване на четене или запис на устройството на адреса. По този начин пълният подчинен адрес е 8 -битов байт. Действителният адрес е частично определен вътрешно към устройството и не може да бъде променен (4 най -значими бита) и частично се определя от битове, които могат да бъдат свързани към щифтове на устройството (3 най -малко значими бита), които могат да бъдат обвързани високо или ниско, за да се зададе конкретен адрес. Звучи объркващо, но един пример ще направи това ясно. Информационният лист PCA8574A показва, че четирите най -значими бита на I2C адреса винаги ще бъдат 0111. Следващите три бита се определят от настройките на пинове AD0, AD1 и AD2. Тези щифтове могат да бъдат свързани към земята или към захранването с положително напрежение (5 волта), за да представляват съответно 0 или 1. Така че диапазонът от възможни адреси е 38 до 3F шестнадесетичен, както е показано на другата фигура от информационния лист PCA8574. Така че чрез промяна на настройките на битовете на адреса, до 8 PCA8574A могат да бъдат на I2C шината едновременно. Всеки ще отговори само на своя специфичен подчинен адрес. Ако са необходими още повече I/O портове, може да се използва PCA8574. Единствената разлика между PCA8574 и PCA8574A е, че обхватът на адрес на I2C подчинен адрес на PCA8574 е шестнадесетичен номер от 20 до 27. Определянето на адреса на дадено устройство може да бъде объркващо, тъй като някои информационни листове смятат, че битът за четене/запис е част от адрес. Прочетете внимателно информационния лист и имайте предвид, че подчиненият адрес ще бъде дълъг 7 бита. Битът за четене/запис трябва да се третира отделно. Отново един пример ще помогне. Информационният лист за 24C16 EEPROM, с който ще експериментираме, казва, че първите (най -значимите) четири бита на подчинения адрес са 1010. Следващите три бита могат да бъдат определени чрез A0, A1 и A2; но имайте предвид, че листът с данни също обхваща 24C01 до 24C08, които са по -малки размери EEPROM. Фигурата от информационния лист показва, че настройките на тези адресни битове се игнорират с увеличаване на размера и са напълно игнорирани за 24C16. Тоест последните три бита нямат значение и 24C16 наистина използва всички I2C подчинени адреси от 50 до 57 шестнадесетични. Диапазонът от подчинени адреси всъщност ще адресира различни секции в рамките на 24C16. Първите 256 байта са на адрес 50h, следващите 256 на 51h и така нататък до последните 256 в 57h - за общо 2K байта. Тъй като адресът на RAM PCF8570, с който също експериментираме, е в този диапазон, 24C16 и PCF8570 не могат да се използват заедно.

Стъпка 2: Поръчайте някои I2C устройства

Сега, когато знаете малко за I2C Bus и искате да го използвате, защо не поръчате някои I2C устройства да експериментират сега, за да могат да са на път към вас, докато подготвяте софтуера? Подходящите устройства включват I/ O Interface Expander (любимият ми), Static Ram и EEPROM. Има още много, но това е чудесно начало. AVR процесорите, които ще използваме, са ATtiny2313 и Atmega168 (използвани в Arduino). Ако сте нови в тези, тогава разгледайте този страхотен Instructable, за да научите за тях и да изградите вашата система за развитие на гето. Схемата на ATmega168 в настоящата инструкция показва как да се внедри системата за развитие на гето за този процесор. Кабелът за паралелен порт е същият като този за ATtiny2313. (Не съм пробвал USB версията на системата за развитие на Ghetto, така че не съм сигурен как се осъществява достъп до I2C шината на нея. Същото и за Arduino.) Ето номера на частите на Digikey. РАЗШИРИТЕЛ 568-4236-5-NDRam: IC SRAM 256X8 W/I2C 568-1071-5-NDEEPROM: IC EEPROM SERIAL 16K CAT24C16LI-G-ND

Стъпка 3: I2C драйвери

Ето описанията на функциите на драйвера за I2C шината. Те са разработени с помощта на Atmel Apps Notes за начало. Не бих могъл да направя това без тях като основа за надграждане. Разработката беше извършена с помощта на WinAVR и gcc C компилатора. Ограниченията на тактовата честота са описани по -долу за всеки процесор. Тъй като не мога да тествам всички възможни комбинации от аромати на процесора / тактова честота, просто ще се придържам към това, което всъщност мога да тествам и ще се опитам да посоча ограниченията и ограниченията. Ето функциите на драйвера и как да ги използвам. Моля, разгледайте примерите за повече подробности и за да видите функциите, които се използват в пълните програми. Ако искате да работите с други тарифи, тогава ще трябва да коригирате константи в драйверите. Изпратете ми имейл, ако имате нужда от помощ при това. Можете също така да получите някои съвети от бележките на приложенията Atmel в връзките в Стъпката на ресурсите. USI_TWI_Master_Initialise () Тази функция инициализира хардуера на USI за работа в режим I2C. Обадете се веднъж в началото на програмата. Той връща void и няма аргументи. USI_TWI_Get_State_Info () Тази функция връща информация за грешка I2C и се използва, ако възникне грешка по време на I2C транзакция. Тъй като тази функция връща само код за грешка, използвам функцията TWI_Act_On_Failure_In_Last_Transmission (TWIerrorMsg), за да мига светодиод за грешка. Кодовете за грешки са дефинирани в USI_TWI_Master.h. Ето как да го наречем: TWI_Act_On_Failure_In_Last_Transmission (USI_TWI_Get_State_Info ()) USI_TWI_Start_Read_Write () Тази функция се използва за четене и запис на единични байтове на I2C устройства. Използва се и за записване на множество байтове. Има 6 стъпки за използване на тази функция. 1) Декларирайте буфер за съобщения във вашата програма, за да държи подчинения адрес и байта данни за изпращане или получаване. unsigned char messageBuf (MESSAGEBUF_SIZE); 2) Поставете подчинения адрес като първия байт в буфера. Преместете го с един бит наляво и ИЛИ в бита за четене/запис. Обърнете внимание, че битът за четене/запис ще бъде 1 за четене и 0 за запис. Този пример е за четене. messageBuf (0) = (TWI_targetSlaveAddress << TWI_ADR_BITS) | (ИСТИНА << TWI_READ_BIT); 3) Когато правите запис, поставете байта за записване на следващото място в буфера. 4) Извикайте функцията USI_TWI_Start_Read_Write с буфера за съобщения и размера на съобщението като аргументи. върната стойност (в този случай temp) може да бъде тествана, за да се види дали е възникнала грешка. Ако е така, той се обработва, както е обсъдено по -горе. Вижте примери в програмите. 6) Ако е поискано четене, четенето на байта ще бъде на второ място в буфера. Ако трябва да бъдат записани няколко байта (например на устройство с памет), може да се използва същата процедура. Настройването на буфера и извикването на рутината са малко по -различни. Вторият байт в буфера ще бъде началният адрес на паметта, на който да се пише. Данните, които ще бъдат записани, ще бъдат в следващи байтове. Размерът на съобщението ще бъде размерът, включващ всички валидни данни. Така че, ако трябва да се запишат 6 байта, тогава размерът на съобщението ще бъде 8 (адрес на подчинен + адрес на паметта + 6 байта данни). USI_TWI_Start_Random_Read () Тази функция се използва за четене на множество байтове от I2C устройство, обикновено има значение само за някакъв спомен. Използването на тази рутина е много подобно на предишната, с две изключения. Настройката на бита за четене/запис няма значение. Извикването на тази рутина винаги ще доведе до операция за четене. MessageSize трябва да бъде 2 плюс броя на байтовете за четене. Ако не са възникнали грешки, данните ще бъдат в буфера, започващ на второто място. За ATmega168: Изискване за часовник: драйверите са проектирани за тактова честота от 4MHz за ATmega168. Примерният код показва как да настроите тази тактова честота. Ако искате да работите с други тарифи, тогава ще трябва да коригирате константи в драйверите. Изпратете ми имейл, ако трябва да направите това. TWI_Master_Initialise () Тази функция инициализира хардуера TWI за работа в режим I2C. Обадете се веднъж в началото на програмата. Той връща нищожност и няма аргументи. Не забравяйте да активирате прекъсванията, като извикате swi () след инициализиране. TWI_Get_State_Info () Тази функция връща информация за грешка I2C и се използва, ако възникне грешка по време на I2C транзакция. Тъй като тази функция връща само код за грешка, използвам функцията TWI_Act_On_Failure_In_Last_Transmission (TWIerrorMsg), за да мига светодиод за грешка. Кодовете за грешки са дефинирани в TWI_Master.h, но са модифицирани за сигнализиране на светодиод за грешка. Вижте примерния код за подробности. Ето как да го наречем: TWI_Act_On_Failure_In_Last_Transmission (TWI_Get_State_Info ()) Обърнете внимание, че проверката за грешка се извършва, като се уверите, че транзакцията I2C е завършена (функция, описана по -долу), и след това тествайте малко в глобалната дума за състоянието. две функции работят по същия начин като съответните функции, описани по -горе, но с няколко изключения. Те не връщат никакви стойности на грешки. Прочетените данни не се прехвърлят в буфера. Това ще бъде направено с функцията, описана по -долу. Тоест транзакциите I2C се стартират и след това се изпълняват независимо, докато основната рутина продължава да се изпълнява. Когато основната рутина иска данни от I2C транзакция, която е започнала, тя трябва да провери дали данните са налични. Същата е ситуацията при проверка на грешки. Основната рутина трябва да е сигурна, че транзакцията I2C е завършена, преди да се провери за грешки. Следните две функции се използват за тези цели. Примерните програми показват как се използва това. Тази функция ще се увери, че транзакцията I2C е завършена, преди да прехвърлите данните. Докато стойността се връща от тази функция, намирам проверката на грешката директно за по -надеждна. Ето как да го наречете. Размерът на съобщението трябва да бъде с един по -голям от желания брой битове данни. Данните ще бъдат в messageBuf, започвайки от второто място.temp = TWI_Read_Data_From_Buffer (messageBuf, messageSize);

Стъпка 4: Нека изградим

Да строим!
Да строим!
Да строим!
Да строим!
Да строим!
Да строим!
Да строим!
Да строим!

Започнете, като изтеглите файла I2C Schematics.zip. Може да искате да създадете папка I2C във вашата работна зона, за да съхранявате схемите и примерните програмни файлове. Разархивирайте схемите в тази директория. Ще намерите папка, наречена I2C Schematics. Отворете файла с името I2C.pdf. Тази схема показва системата за развитие на гето ATtiny2313 и разширителя за I/O порт PCA8574A (има голяма чертана кутия около нея). Схемата за разширител на портове е изградена върху макет. Разгледайте снимките, за да видите как изглеждат тези схеми. Те са наистина много прости. Частта от схемата ATtiny2313 е просто системата за развитие на Ghetto с три мигащи светлини (LED1, 2 и 3, плюс R4, 5 и 6) и бутон (S1), закачен към нея, плюс един допълнителен детайл. Този детайл е добавянето на джъмпери (JP4, 5 и 6), които могат да бъдат премахнати, за да се позволи свързването на линиите SCL и SDA на I2C шината. Джъмперите трябва да са на място за програмиране, след това да бъдат премахнати, за да могат да бъдат свързани SCL и SDA. Снимките показват джъмперите на място и отстранени. Разположението на тези джъмпери зависи от вас, просто трябва да ги поставите във вашата система за развитие на гето, ако искате да използвате шината I2C. I2C шината трябва да бъде изключена и джъмперите да бъдат поставени на място за програмиране. Имайте предвид, че наистина трябва да се интересувате само от JP4 и JP6 за I2C шината. Поставете JP5, ако смятате, че някога ще искате да използвате SPI шината. Бордбордингът на PCA8574A I/O Port Expander е много прост. Осигурете Vcc (+5 волта) и Gnd (заземяване) връзки и свържете AD0, 1 и 2 към земята (прави I2C slave адреса 38 шестнадесетичен). След това свържете 4 мигащи светлини и 4 DIP превключвателя. (Ако нямате DIP превключватели, можете просто да използвате проводници. Завържете към земята или оставете плаващ, за да включите или изключите съответно.) Накрая свържете свързващите резистори (R11 и 12) от SDA и SCL към Vcc. Те са показани като 3.3K, но всяка стойност от 1.8K до 5.1K трябва да работи (може би до 10K, но не съм опитвал това). След като програмирате ATtiny2313, можете да премахнете джъмперите и да свържете SDA и SCL за тестване. Сега за ATmega168. Единствената бръчка тук е, че може да не сте изградили система за развитие на гето за този процесор. Ако случаят е такъв, схемата, която предоставям (MEGA I2C.pdf), ще ви покаже как. Това е просто пермутация на версията ATtiny2313. Ако планирате предварително, можете да се уверите, че вашият кабел за програмиране ще отговаря на двете системи. Основната разлика е добавянето на C2 и C3. Вижте снимките за поставянето им, те трябва да са много близо до чипа; един от тях всъщност е под чипа. Те помагат да се предотврати по -специално шума от аналогово -цифровия преобразувател. Не е необходимо да поставяте джъмперите, освен ако не планирате да използвате SPI шината, тъй като те не са необходими за I2C шината на този чип. Обърнете внимание, че макетната платка PCA8754A ще бъде непроменена. Просто ще свържете SDA и SCL и ще си тръгнете! Лесно, а?

Стъпка 5: Нека кодираме и тестваме

Нека кодираме и тестваме!
Нека кодираме и тестваме!
Нека кодираме и тестваме!
Нека кодираме и тестваме!
Нека кодираме и тестваме!
Нека кодираме и тестваме!

Време е да изградите драйверите и примерните програми. Ще започнем с ATtiny2313 и макета PCA8574A, който току -що създадохме. Изтеглете файла I2C.zip във вашата работна директория на I2C и го разархивирайте. Ще имате нова папка, наречена I2C. В него ще намерите USI I2C (за ATtiny2313) и TWI I2C (за ATmega168). В USI I2C ще намерите папката I_O Port. Тази папка съдържа кода за нашата първа примерна програма и драйверите на USI I2C. Използвайки WinAVR, компилирайте и заредете кода в ATtiny2313. Поемете дълбоко въздух и включете захранването. Ето какво да очаквате: При включване, LED 1 на порт PD6 на ATtiny2313 мига два пъти. Нищо друго няма да се случи, докато не натиснете бутона (S1). При всяко натискане на бутона превключвателите се четат и настройката им ще се показва на светодиодите, свързани към PCA8574A. Променете стойността на превключвателите, натиснете бутона и светодиодите трябва да се променят. Продължавайте да правите това, докато не преодолеете тръпката да видите как работи. Ако (не дай Боже!) Нещата не работят както се очаква, внимателно проверете кабелите си. Грешките I2C ще бъдат сигнализирани с мигания на LED3 (PD4) и вероятно означават, че трябва да проверите дали SDA и SCL са свързани към правилните щифтове и са издърпани правилно. Ако нещата все още не работят, прочетете останалата част от този раздел, за да научите за отстраняването на грешки. Сега се върнете и нека да разгледаме кода. Отворете файла USI_I2C_Port.c. Това е кодът за примерната програма. (USI_TWI_Master.c и USI_TWI_Master.h съдържат драйверите - можете да ги игнорирате, освен ако не сте любопитни.) Използвайте примера, за да ръководите вашите собствени приложения за I2C. Най -вече програмата ви показва как да инициализирате и използвате драйверите на I2C, включително настройката нагоре на подчинения адрес и останалата част от буфера за съобщения и извличане на данните от него. Ще видите също как премахвам бутона и настройвам цикъла while. Има няколко подробности за програмата, които си струва да бъдат споменати. Обърнете внимание, че данните от превключвателите се инвертират, преди да бъдат записани в светодиодите на разширителя на порта. Също така имайте предвид, че входните портове на Port Expander трябва да бъдат записани като High, за да работят правилно. Тези подробности са описани в информационния лист PCA8574A. Винаги четете внимателно информационните листове! По -голям интерес представлява използването на условно отстраняване на грешки. Близо до началото на програмния файл е изявлението // #define DEBUG и разпръснати в кода са #ifdef DEBUG изрази. Докато DEBUG не е дефиниран (двете наклонени черти правят реда коментар и го предпазват от дефиниране), кодът в операторите #ifdef до #endif няма да бъде компилиран. Но ако нещата не работят както очаквате, прекомпилирайте и презаредете кода с #define DEBUG без коментар. Ще получите много повече мигания на светодиодите, които можете да декодирате, за да проследите изпълнението на вашата програма и да ви помогнат да намерите точно къде нещата се объркват. Всъщност препоръчвам да опитате това, само за да видите какво се случва. Това, което ще видите, е, че LED 2 (на PD5) ще мига, докато изпълнението напредва през програмата. Стойността, отчетена от превключвателите, ще мига на LED 1 (PD6), преди да се покаже на светодиодите за разширител на портове. Трябва да можете да проследявате програмата, докато тя работи, като използвате тези светодиоди. След това ще работим с ATmega168; пропуснете този раздел, ако се интересувате само от ATtiny2313. Все още с мен? Добре. Преместете се в папката TWI_I2C, променете работната си директория на IO_Port и компилирайте и заредете TWI_I2C_Port.c в ATmega168. Изключете SDA и SCL линиите от ATtiny2313 и ги свържете към ATmega168. Свържете захранването и земята и включете захранването. Операцията трябва да е същата! Играйте, докато тръпката утихне, след това нека разгледаме кода. Отворете TWI_I2C_Port.c. Кодът е почти идентичен, с изключение на обработката на грешки и настаняването на драйвери за прекъсване. Ето разликите: Имайте предвид, че часовникът трябва да бъде настроен на 4MHz, за да работи правилно I2C шината. Sei (); изразът включва прекъсвания след инициализация на драйверите на I2C. За да се провери за грешки, се тества специфичен бит на състоянието. По време на четене функцията TWI_Read_Data_From_Buffer трябва да бъде извикана, за да прехвърли прочетените данни в буфера за съобщения. По време на запис, докато (TWI_Transceiver_Busy ()) трябва да се използва, за да сте сигурни, че прехвърлянето е завършено, преди да проверите за грешки. Последните две функции са описани по -горе в описанието на драйверите. Освен това, кодът е почти същият като за ATtiny2313. DEBUG работи по същия начин, ако искате да експериментирате с това.

Стъпка 6: Използване на I2C памет

Използване на I2C памет
Използване на I2C памет
Използване на I2C памет
Използване на I2C памет
Използване на I2C памет
Използване на I2C памет
Използване на I2C памет
Използване на I2C памет

Сега, когато се научихме да използваме I2C шината за четене и запис на I/O Port Expander, нека преминем към използването на I2C памет, както RAM, така и EEPROM. Основната разлика е, че множество байтове могат да бъдат прочетени или записани от паметта с една команда I2C. За да се подготвим за тези експерименти, трябва леко да модифицираме хардуера и да изградим няколко нови схеми на макета. Запазете веригата за разширител на портове, тъй като ще я използваме за показване на някои стойности на паметта. Извадете DIP превключвателите от PCA8574A и поставете мигащи светлини върху тези щифтове. Ако нямате достатъчно мигащи светлини, преместете тези от P4 през P7 до P0 през P3. (Стойностите, които трябва да бъдат показани, са достатъчно малки.) Сега погледнете схематичния I2C Ram.pdf и свържете PCF8570 на макета. Разгледайте и снимката. Не забравяйте да свържете щифт 7 към Vcc. Проведете проводници за SDA и SCL от PCA8574A. Не се изискват допълнителни издърпващи се резистори. Ако също се интересувате от EEPROM, изградете тази схема също като използвате I2C EEPROM.pdf за 24C16, но бъдете предупредени, че примерът използва ATmega168. Тази схема е наистина проста. Както бе обсъдено по -горе, битовете на адреса трябва да бъдат игнорирани. Просто свържете захранването и заземете. Все още не свързвайте SDA и SCL, тъй като не сме приключили с експериментите с Ram. Ще започнем нашите експерименти с паметта с ATtiny2313, свързан към PCA8574A Port Expander и към PCF8570 Ram. Програмата ще запише някои номера в рамката, след това ще ги прочете и ще ги покаже на Port Expander. Сменете работната си директория на RAM под USI I2C. Използвайте make файла, за да компилирате и изтеглите USI_I2C_RAM.c. Обърнете внимание, че файловете с драйвери на I2C са идентични с тези, които използвахме по -рано. Включете захранването и трябва да видите единично мигане на LED 1 (PD6). Данните ще бъдат записани в първите 4 байта памет. Натиснете бутона и два байта ще бъдат прочетени и показани. Трябва да видите една LED светлина на разширителя на порта (P0), пауза от две секунди, след това два светодиода (P0 и P1). Още две секунди пауза и светодиодите трябва да се изключат. Натиснете бутона отново, за да започнете поредицата отначало. Отстраняването на грешки е подобно на описания по -горе метод. Нека да разгледаме кода. Отворете USI_I2C_RAM.c. Трябва да изглежда доста подобно на предишния код. Основните разлики са детайлите на паметта за четене и писане. Вижте начина, по който се зарежда буферът за съобщения преди извикването, което действително извършва записването. Първият байт е подчиненият адрес с правилно зададен бит за четене/запис. Но следващият байт е адресът на паметта, на който да започнете да записвате данни. След това идват действителните байтове от данни, които последователно ще се зареждат в паметта, като се започне от адреса, който посочихме. Определяме размера на съобщението като 6. Затова започваме да пишем на адрес 00 и записваме стойностите 01, 03, 02 и 06 в местата на паметта от 00 до 03. За да прочетем данните обратно от паметта, трябва да използваме функцията USI_TWI_Start_Random_Read. Буферът за съобщения получава подчинения адрес в първия байт и началния адрес във втория байт. След това извикайте функцията с размер на съобщението, зададен на броя байтове за четене плюс 2. Обърнете внимание, че битът за четене/запис няма значение, тъй като четенето ще се извършва независимо. Върнатите данни ще започнат на второто място в буфера за съобщения. След като данните бъдат прочетени, те се инвертират за показване на Port Expander и се записват един по един байт в него с пауза между стойностите. Накрая светодиодите за разширител на портове се изключват. Записите към Port Expander са идентични с това, което беше направено в предишните примери. За забавление можете да декомментирате изявлението #define DEBUG както по -горе и да видите много мигащи светодиоди. Изчервени от вълнение след друг успешен експеримент, нека преминем към ATmega168 и EEPROM. Променете работната си директория на EEPROM под TWI I2C. Използвайте make файла, за да компилирате и изтеглите TWI_I2C_EEPROM.c. Обърнете внимание, че файловете с драйвери на I2C са идентични с тези, които използвахме по -рано за PCA8574A. За да тествате програмата, изключете ATtiny2313 и свържете ATmega168. Оставете автобуса I2C закачен към Ram и включете захранването. Резултатите са различни, тъй като сега пишем и четем повече данни. LED 1 на PD7 трябва да мига при инициализация. Натиснете бутона и данните ще бъдат прочетени обратно от паметта и показани. Светодиодите на PCA8574 трябва да мигат в следната последователност: P1, P0 & P2, (всички изключени), P0 & P1, P1 и P2. Накрая всички светодиоди на порта трябва да изгаснат. Натиснете бутона отново, за да повторите това. О, но изчакайте, казвате. Тази програма не е ли за EEPROM? Тъй като имаме достъп до устройство с памет на същия I2C адрес, същата програма работи както за Ram, така и за EEPROM. Изключете захранването и преместете SDA и SCL от рамката към EEPROM и стартирайте програмата отново. Тя трябва да работи абсолютно същото. Обърнете внимание, че EEPROM и Ram не могат да бъдат свързани към I2C шината едновременно, тъй като споделят един и същ адрес. (Умните сред вас може да помислят за промяна на програмируемите битове за адрес на Ram, но това все още няма да работи. 24C16 използва целия блок адреси, които могат да бъдат програмирани за Ram.) Добре, нека да разгледаме последната програма. Отворете TWI_I2C_EEPROM.c. Първото нещо, което трябва да забележите, е, че съм посочил как да се обърнем към пълния 24C16 EEPROM. Той може да бъде достъпен в 256 байтови парчета на 8 различни I2C подчинени адреса. Вижте как MEMORY_ADDR е дефиниран като начален адрес на 50 шестнадесетичен; затова Рамът работеше. Ако искате да получите достъп до други блокове на 24C16, използвайте другите адреси, както съм посочил. Вижте как настроих да пиша в паметта. Първо подчиненият адрес с набор битове за четене/запис се поставя в буфера, след това началният адрес на 00, след това 16 байта данни. Функцията TWI_Start_Read_Write се извиква за запис на данните (както преди) с размер на съобщението, зададен на 18. Когато бутонът е натиснат, използваме TWI_Start_Random_Read и TWI_Read_Data_From_Buffer, за да прочетем данните обратно. Всеки трети байт се показва на светодиодите за разширител на портове. Накрая светодиодите се изключват, за да изчакат следващото натискане на бутон. Може би се чудите защо избрах да напиша 16 байта. Ако прочетете внимателно информационния лист, ще видите, че 24C16 прави цикъл на запис, когато получава 16 байта, дори ако се изпращат повече байта. Така че това изглеждаше като хубаво число за използване. Ако решите да увеличите това, ще трябва да промените размера на MESSAGEBUF_SIZE. Също така ще трябва да промените стойността TWI_BUFFER_SIZE в TWI_Master.h. Това е така, защото драйверът копира данните от буфера за съобщения за използване от рутинната услуга за прекъсване. Честито! Вече сте готови да използвате I2C шината в собствените си проекти!

Стъпка 7: Уеб ресурси

Ето връзките към информационните листове за частите, използвани за експериментите. Определено трябва да ги вземете, ако не получите нищо друго. (Те обичат да използват квадратни скоби в своите URL адреси, така че не мога правилно да ги включа тук. Съжалявам.) За да стигнете до I2C областта, изберете Interface от списъка с продукти. Ще можете да стигнете до техния I2C сайт и достъп до всички таблици с данни и приложения, които предлагат. Описанието на I2C шината и по -специално техническите подробности са тук. Вземете листа с данни ATtiny2313 и ATmega168 (книги с данни?) от Atmel. Бележките за приложението Atmel са тук. Вижте AVR310 и AVR315. Вземете кода също. Потърсете тук за много повече I2C неща.

Стъпка 8: Бележки за отрепки

За истинския маниак, който иска да знае подробностите, ето някои неща, които трябва да имате предвид, ако погледнете бележките на Atmel Apps и кода на драйвера:- Методът за адресиране и командване на I2C устройство не е част от спецификацията! Освен подчинения адрес и бита за четене/запис, команди, режими и т.н. не са посочени и са специфични за дадено устройство. За да стане това много ясно, имайте предвид, че схемата, използвана в примера на Atmel, се отнася само за този пример и е почти нестандартна.- Изпълнението на USI се различава от изпълнението на TWI по няколко важни начина. + С USI часовникът се осигурява от софтуер; с TWI се осигурява от генератор на битрейт. + Методът USI не използва прекъсвания; прави TWI. Това има известен смисъл, тъй като семейството на Mega (използвайки TWI) може да прави много други неща и не трябва да бъде задържано от I2C трансфери. Версия с прекъсване за USI със сигурност е възможна, просто не е внедрена в тази инструкция. + Хардуерът на USI не е оптимизиран за I2C и може да обработва само 8 -битови трансфери. Това означава, че са необходими два трансфера за изпращане на деветия бит (NACK или ACK). Хардуерът TWI се справя автоматично с това. Това прави внедряването на драйвера на USI малко по -сложно. + Откриването на грешки за TWI се обработва хардуерно. USI изисква работа в софтуер, който донякъде усложнява нещата. + Хардуерът TWI контролира директно конфигурацията на порта. Хардуерът на USI изисква битовете на порта да бъдат конфигурирани, преди да може да се използва портът. Ще видите това в рутината Master_Initialize за USI.-Atmel твърди, че е възможно да се използват изтегляния на AVR порт за издърпвания на I2C шина. Не съм измислил начин да накарам този подход да работи. Използването на два външни резистора изглежда доста проста схема, така че не отделих много време за това.

Препоръчано: