Работа USI в трехпроводном режиме
На шине есть ведущее (Master) и ведомое (Slave) устройства, которые обмениваются данными своих регистров USIDR побитово, при этом Master задает тактирование. Интерфейс состоит из трех линий: DO (data output), DI (data input), USCK (USI clock ):
На каждом такте USCK из регистра USIDR одного устройства "выдавливается" один старший битик, который записывается в младший разряд аналогичного регистра другого устройства. Таким образом, через восемь тактов оказывается, что устройства обменялись данными, и выставляется соответствующий флаг (а если хотите, то и прерывание).
Подключение сдвигового регистра 74HC595 к USI
Возьмем микроконтроллер с USI, пусть это будет Attiny45, и посмотрим на его распиновку:
Я пометил ноги 5, 6 и 7 - они имеют функции USI. Сдвиговый регистр все же требует защелкивающего строба, который ранее реализовывался нами в виде линии SS. Сделаем его тупо на PB4.
Подключим
DO (6 нога Attiny) к DS (14 нога 74HC595),
USCK (7 нога Attiny) к SHCP (11 нога 74HC595),
PB4 (3 нога Attiny) к STCP (12 нога 74HC595),
как показано на рисунке:
DI не подключаем никуда, потому что принимать нам и нечего. Я не стал на схеме рисовать светодиоды и резисторы - они занимают много места.
В живую, конечно, выглядит страшно, тем более, что у меня там еще 6 проводов от программатора:
Описание регистров USI
У процессора есть четыре регистра, ответственных за USI:
USIDR - USI Data Register - Регистр данных USI,
USIBR - USI Buffer Register - Регистр буфера USI,
USISR - USI Status Register - Регистр состояния USI,
USICR - USI Control Register - Управляющий регистр USI.
7 bit | 6 bit | 5 bit | 4 bit | 3 bit | 2 bit | 1 bit | 0 bit | |
USIDR | MSB | LSB |
Этот регистр содержит данные, пересылаемые по USI. До сеанса пересылки он содержит отправляемый данные, а после - принимаемые.
7 bit | 6 bit | 5 bit | 4 bit | 3 bit | 2 bit | 1 bit | 0 bit | |
USIBR | MSB | LSB |
Этот регистр содержит копию данных из USIDR, доступную только для чтения.
7 bit | 6 bit | 5 bit | 4 bit | 3 bit | 2 bit | 1 bit | 0 bit | |
USISR | USISIF | USIOIF | USIPF | USIDC | USICNT3 | USICNT2 | USICNT1 | USICNT0 |
Четыре старших бита регистра - это флаги, а четыре младших хранят значение счетчика USI.
USISIF - Start Condition Interrupt Flag - флаг условия старта. Изменение сигнала на линии SCK поднимет этот флаг. Опустить флаг можно, только записав 1 в бит USISIF. Флаг может сгенерировать прерывание, если выставлен бит USISIE в регистре USICR. Это прерывание выведет процессор из любого режима сна.
USIOIF - Counter Overflow Interrupt Flag - флаг переполнения счетчика. Поднимается, когда счетчик досчитает от 15 до 0. Опустить флаг можно, только записав 1 в бит USIOIF. Флаг может сгенерировать прерывание, если выставлен бит USIOIE в регистре USICR. Это прерывание выведет процессор из режима Idle.
USIPF - Stop Condition Flag - флаг условия остановки. Если выбран двухпроводной режим, этот флаг поднимается, когда обнаруживается условие остановки. Опустить флаг можно, записав 1 в этот бит. Этот сигнал используется при арбитраже двухпроводной шины.
USIDC - Data Output Collision Flag - флаг коллизии вывода данных. Этот флаг поднимается, когда 7-й бит регистра USIDR отличается от физического значения пина. Этот флаг работает только в двухпроводном режиме и используется для арбитража шины.
USICNT[3:0] - Counter Value - значение счетчика. Значение увеличивается на 1 каждый раз, когда генерируется строб детектором внешнего источника или софтверно, с помощью битов USICLK или USITC. Источник задается битами USICS[1:0] в регистре USICR.
7 bit | 6 bit | 5 bit | 4 bit | 3 bit | 2 bit | 1 bit | 0 bit | |
USICR | USISIE | USIOIE | USIWM1 | USIWM0 | USICS1 | USICS0 | USICLK | USITC |
USISIE - Start Condition Interrupt Enable - разрешение прерывания при условии старта. Установка этого бита в 1 разрешает прерывание детектором условия старта. Прерывание будет генерироваться, если флаги USISIE и Global Interrupt Enable Flag подняты.
USIOIE - Counter Overflow Interrupt Enable - разрешение прерывания при переполнении счетчика. Прерывание будет генерироваться, если флаги USIOIE и Global Interrupt Enable Flag подняты.
USIWM[1:0] - Wire Mode - режим шины. Эти два бита задают режим использования шины.
USIWM1
|
USIWM0
|
Описание
|
0
|
0
|
USI отключен.
|
0
|
1
|
Трехпроводной
режим. Используются пины DO,
DI и
USCK.
|
1
|
0
|
Двухпроводной
режим. Используются пины SDA
(DI) и SCL (USCK).
Линия USCL удерживается
низкой, когда обнаруживается условие старта. Сброс флага USISIF отпускает
линию.
|
1
|
1
|
Двухпроводной
режим. Используются пины SDA
(DI) и SCL (USCK).
Линия USCL удерживается
низкой, когда обнаруживается переполнение счетчика. Сброс флага USIOIF отпускает
линию.
|
USICS[1:0] - Clock Source Select - выбор источника тактирования. Сброс битов USICS[1:0] разрешает софтверное стробирование. При этом запись 1 в бит USICLK тактирует регистр USIDR и счетчик. При использовании внешнего источника (USICS1 = 1), USICLK не используется как строб, а задает режим тактирования от внешнего источника или от USITC.
USICS1
|
USICS0
|
USICLK
|
Источник тактирования
|
Источник тактирования счетчика
|
0
|
0
|
0
|
Нет
|
Нет
|
0
|
0
|
1
|
Софтверный строб (USICLK)
|
Софтверный строб (USICLK)
|
0
|
1
|
X
|
Timer/Counter0
CNC
|
Timer/Counter0
CNC
|
1
|
0
|
0
|
Внешний, положительный фронт
|
Внешний, оба фронта
|
1
|
1
|
0
|
Внешний, отрицательный фронт
|
Внешний, оба фронта
|
1
|
0
|
1
|
Внешний, положительный фронт
|
Софтверный строб (USITC)
|
1
|
1
|
1
|
Внешний, отрицательный фронт
|
Софтверный строб (USITC)
|
USICLK - Clock Strobe - Тактирующий строб. Запись 1 в этот бит заставляет регистр USIDR совершить сдвиг и инкрементирует счетчик, если выбрано софтверное тактирование (USICS[1:0] = 0). Если выбран внешний источник тактирования (USICS1 = 1), то функция USICLK меняется - запись 1 в этот бит выбирает строб USITC в качастве источника тактирования счетчика.
USITC - Toggle Clock Port Pin - переключение пина порта тактирования. Запись 1 в этот бит переключает значение USCK/SCL с 0 на 1 или с 1 на 0. Если выбран внешний источник тактирования (USICS1 = 1) и USICLK установлен в 1, то запись в USITC тактирует счетчик.
Пишем код
//Подключаем самую нужную библиотеку io #include </usr/lib/avr/include/avr/io.h> //Подключаем библиотеку, которая обеспечивает функцию delay #include </usr/lib/avr/include/util/delay.h> int main(void){ //Настраиваем нужные пины на выходы DDRB = (1 << DDB1) | (1 << DDB2) | (1 << DDB3) | (1 << DDB4); //Бесконечный цикл while(1){ //Пробегаем по номерам светодиодов for (int i=0;i<8;i++){ //В качестве данных для USI указываем номер светодиода USIDR=(1<<i); //Опускаем флаг переполнения таймера USISR|=(1<<USIOIF); //Отпускаем защелку регистра 74HC595 PORTB&=(0<<PORTB4); //Пока не поднялся флаг переполнения счетчика while((USISR&(1<<USIOIF))==0){ //Выставляем трехпроводной режим; //Выбираем внешний источник тактирования, с положительным фронтом; //Выставляем тактирование по стробу USITC; //Собственно, генерируем сам строб USITC USICR=(1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC); } //Защелкиваем данные в регистре 74HC595 PORTB|=(1<<PORTB4); //Пауза 100 миллисекунд _delay_ms(100); } } //main возвращает 0, как всегда return 0; }
Комментариев нет:
Отправить комментарий