AVR Урок 25

Урок 25

SPI. Підключаємо зсувний регістр 74HC595

Сьогодні ми продовжимо працювати з шиноюSPI, яку ми вивчили на попередньому занятті . Точніше ми продовжимо її — цю шину вивчати, тільки заняття тепер буде практичним. Ми візьмемо певний пристрій і спробуємо цим пристроєм покерувати.

А як пристрій ми візьмемо найпростішу мікросхему74HC595, яка керується саме за інтерфейсом SPI і є зсувним регістром. Судячи з технічної документації на цей регістр, розробником його компанія Philips.

Звернімо увагу на деякі технічні характеристики даного регістру зсуву.

Гранична частота тактування має перевищувати 100 МГц, отже з нашими 8 чи 16 МГц тактирової частоти контролера ми навряд чи цю частоту перевищимо.

Напруга живлення мікросхеми - від 2 до 6 Ст.

Дана мікросхема існує у двох типах корпусів - звичайний DIP, а також DHVQFN16, Ми будемо використовувати перший варіант, тому і подивимося розпинання за цим варіантом

PORTB2

У мікросхеми 16 ніжок. Подивимося їх призначення у таблиці

дані

Трохи розшифруємо дані ніжки

Q0-Q7 - вісім паралельних виходів загального призначення. Дані виходи потрібні для того, щоб ми могли якось скористатися даними, що прийшли по SPI - підключити лінійку світлодіодів, або сегменти якогось індикатора, або дешифратор і т.д.

VCC - напруга живлення.

GND - загальний провід.

Q7' - Послідовний вихід даних. Той самийMISO.

DS — послідовний вхід даних абоMOSI.

MR - це master reset. Будевивчений у процесі використання.

SH_CP - у нашому випадку це буде chip select.

ST_CP - це ніжка управління регістром зберігання, у нашому випадку це буде ніжка синхронізації, на яку ми будемо подавати тактові імпульси.

OE - задіяння виходу. При негативному значенні послідовний вихід увімкнений, при позитивному вимкнений.

Також ще нам допоможе до кінця зрозуміти призначення ніжок допоможе ось така блок-схемка

рівень

Найцікавіше в цій схемі — те, що ми бачимо тут не один регістр, а два. Один з них - це звичайний зсувний регістр, в який приходять і з якого йдуть наші дані SPI. Але також є ще один регістр, який ці дані потрапляють не автоматично, а за певних умов. Вже до цього регістру, що називається регістром зберігання і прив'язаний жорстко паралельний 8-розрядний вихід.

Тому перед нами тепер постає завдання. Як перенести наші дані з верхнього регістру в нижній. А виявляється, для цього нам необхідний квадратний імпульс на ніжці12 — ST_CP. І негативний фронт даного імпульсу і "попросить" дані спуститися згори донизу.

Наступне завдання - підключити даний зсувний регістр74HC595 до контролера ATmega8.

Так як ми не будемо користуватися послідовним виходом з нашої мікросхеми, то висновокMISO контролера ми задіяти не будемо.

А до ніжок паралельного виходу ми підключимо світлодіоди через струмообмежуючі резистори. Вийде у нас ось така схема

PORTB2

Ось так все і підключається. Вихід ми увімкнули, хоча він нам не потрібен. Пізніше знадобиться. Включається як ми пам'ятаємо він ніжкою OE низьким рівнем. Вихід MR нам не потрібний. Він для перезавантаження, тому підтягнемо його до живлення.Та й відповідно SPI. Тут також все нескладно. Під'єднані ніжки MISO, SCK та SS. Останню можна було підключити з будь-якої ніжки МК, оскільки апаратно не управляється.

Тепер нам необхідно якось написати код та змусити все це працювати.

Створимо проект з ім'ям 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)); //низький рівень

while (1)

Тепер налаштуємо саму шину SPI

((1 PORTB2) (1 PORTB3) (1 PORTB5)); //низький рівень

SPCR = ((1 SPE) (1 MSTR)); //Включимо шину, оголосимо провідним

SPDR = 0b00000000;

Дільник і помножувач ми не включаємо, оскільки частота мікросхемі підтримується велика. Також ми включили SPI та налаштували мікроконтролер провідним пристроєм.

Потім занесли до регістру даних нулі.

Ну, тепер спробуємо ці дані передати мікросхемі.

while (!( SPSR & (1 SPIF ))); //Почекаємо поки дані передадуться

Тобто, яктільки ми занесли до регістру даних значення, контролер почне їх намагатися передавати. Після цього ми в циклі чекаємо на той момент, коли включиться біт SPIF в регістрі SPSR. Як тільки він увімкнеться, це означатиме, що весь повний байт передався на ведений пристрій.

Після цього щоб дані в регістрі зсуву перейшли в нижній регістр зберігання, ми повинні сформувати там негативний фронт. Але, оскільки дана ніжка SS вже знаходиться в низькому логічному рівні, то спочатку включимо їй високий, а потім низький, тим самим формуючи негативний фронт або низхідний

while (! (SPSR & (1 SPIF))); //почекаємо поки дані передадуть

//згенеруємо негативний фронт для запису в STORAGE REGISTER

PORTB = (1 PORTB2); //високий рівень

(1 PORTB2); //низький рівень

Тим самим ми в даному коді сформували на всіх ніжках паралельного виходу мікросхеми низький логічний рівень і світлодіоди у нас повинні будуть згаснути, якщо вони якось загорілися при старті.

Зачекаємо дві секунди і те саме повторимо ще раз, але з усіма логічними одиницями в регістрі даних, тим самим всі світлодіоди, підключені до паралельного виходу мікросхеми, повинні засвітитися. Потім зачекаємо ще дві секунди

(1 PORTB2); //низький рівень

_delay_ms (2000);

SPDR = 0b11111111;

while (!( SPSR & (1 SPIF ))); //Почекаємо поки дані передадуться

//згенеруємо негативний фронт для запису в STORAGE REGISTER

PORTB = (1 PORTB2); //високий рівень

(1 PORTB2); //низький рівень

_delay_ms (2000);

Подивимося тепер схему практично, як у нас усе зібрано

рівень

Все підключено також, як ми бачили впротеусі. Замість 8 світлодіодів у нас підключено матрицю світлодіодів.

Спробуємо зібрати код та прошити наш контролер. Спочатку світлодіоди перебувають у згаслому стані і через 2 секунди всі вони починають світитися. Значить, все у нас передалося.

Ну, і тепер для більшої краси і для точного переконання, що байти доходять правильно, не перевертаються і не спотворюються, ми напишемо код у нескінченний цикл, який відправлятиме в шину SPI числа від 0 до 255, тим самим у нас на світлодіодів буде імітація інкрементування двійкових чисел У main() ми спочатку додамо локальну змінну для рахунку

unsigned int i =0;

Напишемо тепер тіло нескінченного циклу

for (i = 0; i i ++)

SPDR = i;

while (!( SPSR & (1 SPIF ))); //Почекаємо поки дані передадуться

//згенеруємо негативний фронт для запису в STORAGE REGISTER

PORTB = (1 PORTB2); //високий рівень

(1 PORTB2); //низький рівень

_delay_ms (50);

i = 0;

Зберемо код, прохаємо контролер і подивимося результат нашої роботи над кодом

Все добре працює.

Таким чином ми тепер потренувалися з шиною SPI на практиці.

Програматор та зсувні регістри можна придбати тут:

Дивитись ВІДЕОУРОК (натисніть на картинку)

У тексті статті зазначено, що "

SH_CP - у нашому випадку це буде chip select.

ST_CP — це ніжка керування регістром зберігання, у нашому випадку це буде ніжка синхронізації, на яку ми будемо подавати тактові імпульси.",

але на схемі – навпаки. Поправте опис ніжок.

Та начебто все нормально.ST_CP - вона ж PORTB2. Ми цією ніжкою клацаємо кожен біт. Тобто цим створюємоімітацію імпульсів тактування. SH_CP — вона PORTB5 у нас завжди в низькому рівні. Вона і є ніжка вибору (саме у нашому випадку). Якщо ми піднімемо її у високий рівень, передача прикриється.

У уроці протиріччя згоден з шемотехніком.

Добридень! Просто трохи незрозуміло. Виходить клацати біт можна будь-якою ногою? Для цього випадку sh_cp можна було просто посадити на землю? Ніжка вибору SS(у контролера) з'єднана з «ST_CP — це ніжка управління регістром зберігання, у нашому випадку це буде ніжка синхронізації, на яку ми будемо подавати тактові імпульси». Ніжка SCK(у контролера) з'єднана з «SH_CP — у нашому випадку це буде chip select». Чому навпаки? Дякую!

У вас є помилка. Читаємо даташит: SH_CP - shift register clock input, тобто вхід для синхроімпульсів зсувного регістру ST_CP - storage register clock input, тобто вхід для синхроімпульсів регістра зберігання.

Звідси можна дійти невтішного висновку, що до SH_CP потрібно підключати якраз SCK від майстра, а до ST_CP будь-який інший пін, який треба буде смикати, щоб дані потрапили зі зсувного регістру в регістр зберігання. Як такий CS/SS (chip select) від SPI тут до пуття і не потрібний.

І так, останній приклад – відображення чисел у двійковому вигляді за допомогою циклу від 0 до 255 працюватиме неправильно. Тому що DORD біт в SPCR у вас встановлений в 0, таким чином дані будуть передаватися від старшого біта до молодшого (MSB), тобто. старший біт у зсувному регістрі поїде до молодшого і наприклад замість 0b00000001 на виході отримаєте 0b10000000

А SN74HC595N підійде замість 74HC595?

Це виходить ми можемо використовуючи SPI Витративши заздалегідь 4 лапки, і надалі на кожен пристрій, підключений по SPi, зачіпати додатково 1 лапку на пристрій? тобто. 1пристрій 5 лап, 3 пристрої - 7 лап?

А якщо підключити зсувний регістр, то ми їм можемо заощаджувати 7 лап, не враховуючи лапки SPI

Чи можна реалізувати на цій мікросхемі свій драйвер для дисплея 16×2? чи не вийде через таймінги? нібито високий рівень, чекаємо на 50us низький 50us.