AVR Урок 25
Урок 25
SPI. Свържете преместващ регистър 74HC595
Днес ще продължим с автобусаSPI, който научихме впредишния урок. По-скоро ще го продължим - за да изучаваме тази гума, само урокът вече ще бъде практически. Ще вземем определено устройство и ще се опитаме да контролираме това устройство.
И като устройство ще вземем най-простата микросхема74HC595, която се управлява точно чрез SPI интерфейса и е регистър за смяна. Съдейки по техническата документация за този регистър, неговият разработчик е Philips.
Нека обърнем внимание на някои технически характеристики на този преместващ регистър.
Граничната тактова честота не трябва да надвишава 100 MHz, така че с нашата тактова честота на контролера от 8 или 16 MHz е малко вероятно да надвишим тази честота.
Захранващото напрежение на микросхемата е от 2 до 6 V.
Тази микросхема съществува в два вида пакети - обичайният DIP, както и DHVQFN16, Ще използваме първата опция, така че ще видим pinout за тази опция
Чипът има 16 крака. Нека видим предназначението им в таблицата
Нека разшифроваме малко тези крака
Q0-Q7 - осем паралелни изхода с общо предназначение. Тези изходи са необходими, за да можем по някакъв начин да използваме входящите данни през SPI - да свържем линия от светодиоди, или сегменти от някакъв индикатор, или декодер и т.н.
VCC — захранващо напрежение.
GND — общ проводник.
Q7' - сериен изход на данни. СъщиятMISO.
DS - серийно въвеждане на данни илиMOSI.
MR е основното нулиране. Щенаучен по време на употреба.
SH_CP - в нашия случай това ще бъде избор на чип.
ST_CP е контролният щифт на регистъра за съхранение, в нашия случай това ще бъде щифтът за синхронизиране, към който ще изпращаме тактови импулси.
OE — активиране на изхода. Отрицателна стойност ще активира серийния изход, а положителна стойност ще деактивира серийния изход.
Освен това тази блокова диаграма ще ни помогне да разберем напълно предназначението на краката.
Най-интересното в тази схема е, че тук виждаме не един регистър, а два. Един от тях е обикновен регистър за смени, в който влизат и излизат нашите SPI данни. Но има и друг регистър, в който тези данни не попадат автоматично, а при определени условия. Вече към този регистър, наречен регистър за съхранение, е свързан твърдо паралелен 8-битов изход.
Затова сега сме изправени пред предизвикателство. Как да прехвърлим нашите данни от главни в малки букви. И се оказва, че за това се нуждаем от квадратен импулс на крака12 - ST_CP. И отрицателният ръб на този импулс ще "помоли" данните да се спуснат отгоре надолу.
Следващата задача е да свържете този74HC595 преместващ регистър към контролера ATmega8.
Тъй като няма да използваме серийния изход от нашата микросхема, няма да използваме изхода на контролераMISO.
И към краката на паралелния изход ще свържем светодиодите чрез резистори за ограничаване на тока. Получаваме следната схема
Ето как всичко се свързва. Включихме изхода, въпреки че не се нуждаем от него. Нужен по-късно. Включва се, както си спомняме, с ниско ниво на OE. Нямаме нужда от MR изход. Това е за рестартиране, така че нека го издърпаме до захранване.Е и съответно SPI. И тук всичко е лесно. Свързани щифтове MISO, SCK и SS. Последният може да бъде свързан от всеки крак на MK, тъй като не се управлява хардуерно.
Сега трябва по някакъв начин да напишем кода и да накараме всичко да работи.
Нека създадем проект с името MYSPI595, създадем и включим заглавния файл main.h със следното съдържание
#ifndef MAIN_H_
#define MAIN_H_
#define F_CPU 8000000UL
#include
#include
#include
#endif /* MAIN_H_ */
Можете също така да използвате примера в техническата документация за нашия контролер в раздела за SPI шината.
Е, нека започнем да мислим.
Съответно, както обикновено, първо ще трябва да конфигурираме краката на порта. Всички SPI пинове ще бъдат настроени на изход, тъй като не използваме MISO, и също така ще ги настроим на ниско логическо ниво
#include "main.h"
int main ( void )
unsigned int i =0;
DDRB = ((1 PORTB2 )(1 PORTB3 )(1 PORTB5 )); //SPI пинове за изход
((1 PORTB2 )(1 PORTB3 )(1 PORTB5 )); //ниско ниво
докато (1)
Сега нека конфигурираме самата SPI шина
((1 PORTB2 )(1 PORTB3 )(1 PORTB5 )); //ниско ниво
SPCR = ((1 SPE )(1 MSTR )); //Включете шината, декларирайте я като главна
SPDR = 0b00000000;
Ние не включваме делителя и умножителя, тъй като честотата на микросхемата се поддържа от голяма. Също така активирахме SPI и конфигурирахме микроконтролера като главно устройство.
След това в регистъра с данни бяха въведени нули.
Е, сега нека се опитаме да прехвърлим тези данни към микросхемата
докато (!( SPSR & (1 SPIF ))); //изчакайте, докато данните бъдат прехвърлени
И какведнага след като сме въвели стойност в регистъра на данните, администраторът ще започне да се опитва да ги прехвърли. След това изчакваме в цикъл момента, в който SPIF битът в регистъра SPSR се включи. Веднага щом се включи, това ще означава, че целият пълен байт е прехвърлен към подчинения.
След това, за да могат данните в регистъра за изместване да отидат в долния регистър за съхранение, трябва да формираме отрицателен ръб там. Но тъй като този SS щифт вече е в логическо ниско ниво, първо ще го завъртим високо и след това ниско, като по този начин ще формираме отрицателен ръб или низходящ
докато (!( SPSR & (1 SPIF ))); //изчакайте данните да бъдат прехвърлени
//генериране на падащ фронт за запис в РЕГИСТЪРА ЗА СЪХРАНЕНИЕ
PORTB = (1 PORTB2); //високо ниво
(1PORTB2); //ниско ниво
По този начин в този код сме формирали ниско логическо ниво на всички крака на паралелния изход на микросхемата и светодиодите ще трябва да изгаснат, ако внезапно светнат по някакъв начин в началото.
Нека изчакаме две секунди и повторим същото нещо отново, но с всички логически единици в регистъра на данните, като по този начин всички светодиоди, свързани към паралелния изход на микросхемата, трябва да светят. След това изчакайте още две секунди
(1PORTB2); //ниско ниво
_delay_ms(2000);
SPDR = 0b11111111;
докато (!( SPSR & (1 SPIF ))); //изчакайте, докато данните бъдат прехвърлени
//генериране на падащ фронт за запис в РЕГИСТЪРА ЗА СЪХРАНЕНИЕ
PORTB = (1 PORTB2); //високо ниво
(1PORTB2); //ниско ниво
_delay_ms(2000);
Сега нека видим схемата на практика, как сме сглобили всичко
Всичко е свързано точно както видяхмепротей. Вместо 8 светодиода, имаме свързана матрица от светодиоди.
Нека се опитаме да компилираме кода и да флашнем нашия контролер. Първоначално светодиодите са в изгасено състояние и след 2 секунди всички започват да светят. Така че всичко ни е предадено.
Е, сега, за по-голяма красота и за да сме сигурни, че байтовете пристигат правилно, не са обърнати или изкривени, ще напишем код в безкраен цикъл, който ще изпрати числа от 0 до 255 към SPI шината, като по този начин ще имаме имитация на нарастващи двоични числа на светодиодите. В main() първо добавяме локална променлива за броя
unsigned int i =0;
Сега нека напишем тялото на безкрайния цикъл
за ( i =0; i i ++)
SPDR = i ;
докато (!( SPSR & (1 SPIF ))); //изчакайте, докато данните бъдат прехвърлени
//генериране на падащ фронт за запис в РЕГИСТЪРА ЗА СЪХРАНЕНИЕ
PORTB = (1 PORTB2); //високо ниво
(1PORTB2); //ниско ниво
_закъснение_ms(50);
i =0;
Нека да съберем кода, да флашнем контролера и да видим резултата от нашата работа върху кода
Всичко работи отлично.
Така вече се упражнихме на практика със SPI шината.
Програматорът и регистрите за преместване могат да бъдат закупени тук:
Гледайте ВИДЕО УРОК (щракнете върху снимката)
Текстът на статията гласи, че "
SH_CP - в нашия случай това ще бъде избор на чип.
ST_CP е контролният щифт на регистъра за съхранение, в нашия случай това ще бъде щифтът за синхронизиране, към който ще изпращаме тактови импулси.",
но на диаграмата е обратното. Коригирайте описанието на краката.
Да, всичко изглежда наред.ST_CP - известен още като PORTB2. Ние щракаме този крак всеки момент. Тоест създавамеимитация на тактови импулси. SH_CP - тя е PORTB5, винаги имаме ниско ниво. Тя е избраният крак (в нашия случай). Ако го вдигнем на високо ниво, предаването ще бъде покрито.
В урока за противоречие съм съгласен с shemotehnik.
Добър ден Просто е малко неясно. Така че можете да щракнете върху ритъма с двата крака? В този случай sh_cp може просто да се постави на земята? Изборният щифт SS (на контролера) е свързан към "ST_CP е контролният щифт на регистъра за съхранение, в нашия случай това ще бъде тактовият щифт, към който ще доставяме тактови импулси." Пинът SCK (на контролера) е свързан към "SH_CP - в нашия случай ще бъде избор на чип". Защо обратното? Благодаря ви!
Имате грешка. Четем листа с данни: SH_CP - вход за часовник в регистъра за смяна, т.е. вход за часовника на регистъра за смяна ST_CP - вход за часовник на регистъра за съхранение, т.е. вход за часовника на регистъра за съхранение.
От това можем да заключим, че само SCK от главния трябва да бъде свързан към SH_CP и всеки друг щифт, който трябва да бъде изтеглен към ST_CP, така че данните да се прехвърлят от регистъра за смяна към регистъра за съхранение. Като такъв, CS / SS (избор на чип) от SPI наистина не е необходим тук.
И да, последният пример - показването на числа в двоична система с помощта на цикъл от 0 до 255 няма да работи правилно. Тъй като битът DORD във вашия SPCR е настроен на 0, така че данните ще бъдат прехвърлени от най-значимия бит към най-малко значимия (MSB), т.е. високият бит в регистъра за смяна ще премине към ниския бит и например вместо 0b00000001 ще получите 0b10000000 на изхода
Ще пасне ли SN74HC595N вместо 74HC595?
Оказва се, че можем да използваме SPI След като сме прекарали 4 лапи предварително и в бъдеще за всяко устройство, свързано чрез SPi, да повлияем на допълнителна 1 лапа на устройство? тези. 1уред 5 лапи, 3 уреда - 7 лапи?
И ако свържете Shift регистъра, тогава можем да им спестим 7 лапи, без да вземаме предвид SPI лапите
Мога ли да внедря собствен драйвер за 16x2 дисплей на този чип? Или няма да работи заради времената? предполагаемо високо ниво, чакане за 50us ниско 50us.