Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вопрос по SPI
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Halfback
Только начинаю нормально осваивать AVR и столкнулся со следующей проблемой.
Задача такая - во время посылки пакета из 8 бит формировать на каком-либо пине импульс (нулевой или +5В - не столь важно) на время формирования этого байта. Делаю а CAVR. Микрик - Мега88
Вот что получилось:
Код
void main(void)
{
...
SPCR=0x52;
SPSR=0x00;

// Clear the SPI interrupt flag
#asm
    in   r30,spsr
    in   r30,spdr
#endasm

// Global enable interrupts
#asm("sei")

while (1)
      {
      // Place your code here
      
      PORTC.0 &= 0;
      PORTD = SPSR;
      SPDR = 0x15;
      
      while(!((SPSR & 0x80) >> 7)); // Следим за SPIF
      PORTC.0 |= 1;
      delay_us(200);
      };
};


при этом коде всё нормально работает. Но когда в визарде проекта CAVR в опциях МЦУ SPI ставлю галочку Enable Interrupt то регистр SPCR приобретает значение 0xD2, т.е. "1" записалась в разряд SPE. При таком раскладе появляется ф-ция обработки прерывания interrupt [SPI_STC] void spi_isr(void).
Но в итоге код не работает. Ес-но я открыл литературу и там написано про SPE - что она активизирует SPI, а SPIF мол является флагом прерываний от SPI и флаг устанавливатеся когда произошла передача пакета. Но как показывает отладка если в SPCR записать 0xD2 то из цикла
Код
while(!((SPSR & 0x80) >> 7)); // Следим за SPIF

программа никогда не выходит.
Можно ли мне разжевать почему так происходит? И как сделать так чтобы программа выходила из while(!((SPSR & 0x80) >> 7)); ???
Заранее признателен!
rezident
Если вы используете прерывание, то обработку флагов нужно вести в самой функции прерывания. Потому, что флаги обычно непосредственно связаны с обработчиком прерывания, например, могут автоматически сбрасываться при переходе по адресу вектора прерывания.
К тому же арифметический сдвиг в проверке логического условия - явно лишняя операция. Условие проверяется на "равно нулю" или "не равно нулю", а вовсе не "равно 1" или "не равно 1". True = 1 и false = 0 это всего лишь абстракция.
rvk
Конечно трудновато с такими нестандартными обозначениями.
В даташите на мегу88 есть регистры UCSRnA, UCSRnB, и флаги
RXCn, RXCIEn. А эти названия SPCR,SPIF, я так понимаю придумали
разработчики CVAVR.
Но в любом случае считаю можно сделать следующее.
Во первых установлены ли флаги разрешения прерывания для UART,
т.е. кроме глобального еще должен быть конкретно на RX,TX.
Если они стоят и в прерывании происходит чтение принятого байта,
то Вы никогда не поймаете флаг готовности. Он сбрасывается в прерывании. Поэтому там же в программе прерывания нужно установить
свой флажок. И его проверять в основной программе.
Halfback
rvk Причем тут UART? речь об SPI...

rezident На счет сдвига - согласен, операция не к чему...

По вопросу - как я понял если я взвожу SPE то флаг SPIF должен сам устанавливать? Без взвода SPE аппаратная часть МЦУ сама выставляет нужные флаги, так?
defunct
Цитата
По вопросу - как я понял если я взвожу SPE то флаг SPIF должен сам устанавливать? Без взвода SPE аппаратная часть МЦУ сама выставляет нужные флаги, так?

Наверное Вы говорите не про SPE, а про SPIE (Interrupt Enable) flag (тот который MSB в SPCR).
Аппаратная часть выставляет флаг SPIF по окончанию трансфера в любом случае, другой вопрос когда он сбрасывается. А сбрасывается флаг SPIF автоматически одним из двух возможных путей:

1. При входе в обработчик прерывания SPI.
2. При прочтении SPSR и затем SPDR.

вот цитата из ДШ:
SPIF is cleared by hardware when executing the corresponding interrupt handling vector.
Alternatively, the SPIF bit is cleared by first reading the SPI Status Register with SPIF set, then accessing
the SPI Data Register (SPDR).

Если Вы устанавливаете SPIE, то должны организовать обслуживание SPI должным образом, без циклов задержки. Читайте данные из SPDR в обработчике прерывания, и загружайте новые данные (если есть) в нем же. Это же настолько естественно - факт вызова обаботчика прерывания означает, что:

A. Байт данных получен, прямо сейчас его нужно прочитать из SPDR.
B. Байт данных отправлен и прямо сейчас можно слать следующий байт.
C. SPIF флаг очищен аппартно, можно о нем забыть.
Svin62
Помогите пожалуйста с SPI.
Имеется такой код для ATTINY2313, который я вызываю из основного цикла:
________________________________________________________________________
USI_Transfer:
out USIDR,Temp //байт для отправки
ldi Temp,(1<<USIOIF)
out USISR,Temp
ldi Temp,(1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC)
USI_Loop:
out USICR,Temp
sbis USISR,USIOIF
rjmp USI_Loop
in Temp,USIDR
ret
________________________________________________________________________

Порт Б сформирован на выход для UCSK и MISO, а для MOSI на вход.

Что ещё нужно инициализировать для запуска этого протокола?
Просто при отладке в АВР Студио в регистр USISR данные не записываются, и ваще нихрена не работает. В железе ещё не запускал...
Может ссылку на ассемблерный пример дадите? laughing.gif
smac
Цитата(Svin62 @ Jan 28 2009, 23:01) *
Помогите пожалуйста с SPI.
...

Какого эффекта вы ожидаете от команд приведенных ниже?
Код
    
[code]ldi    Temp,(1<<USIOIF)
out    USISR,Temp

Это я к тому, что непонятны ваши слова
Цитата
просто при отладке в АВР Студио в регистр USISR данные не записываются
, USISR - это регистр флагов записью 1 флаги сбрасываются, а при отладке для эмуляции прерывания нужно устанавливать флаг вручную щелчком мыши.
Svin62
Цитата(smac @ Jan 29 2009, 10:07) *
Какого эффекта вы ожидаете от команд приведенных ниже?
Код
    
[code]ldi    Temp,(1<<USIOIF)
out    USISR,Temp

Это я к тому, что непонятны ваши слова , USISR - это регистр флагов записью 1 флаги сбрасываются, а при отладке для эмуляции прерывания нужно устанавливать флаг вручную щелчком мыши.


1<<USIOIF - сброс флага переполнения. Что они сбрасываются единицей не знал. smile3046.gif

Я просто не пойму, если мне без прерываний, в "линейном" режиме работать с протоколом, то нужно ли инициализировать ещё какие-нибудь регистры?
Ну типа сторожевой таймер нужно сначала "инитнуть" в начале проги, а уже потом его сбрасывать по ходу дела. А для SPI такое нужно делать? Как установить скорость? Или она автоматом F/4 фигарит?
Надеюсь, что объяснил внятно...
Спасибо.
GDI
Конечно надо установить скорость, направление сдвига, фазы клока и данных - читайте описание регистров SPI.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.