Обсуждаем контроллеры компании Atmel.
Ответить

Отсутствие данных в SPDR

Вт сен 12, 2017 10:13:40

Добрый день. Возникла проблема. Сначала кратко. Есть 2 Atmeg8, которые соединены так, чтобы мастер передавал данные к слейву. Сама проблема - слейв не записывает принятые данные в регистр SPDR.
Теперь подробно. На изображениях ниже приведена схема в протеусе и настройки самих микроконтроллеров.Изображение, Изображение.
Далее, приведен код прошивки каждого из устройств.
Мастер (U1):
Код:
#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>

void SPI_Init(void)
{
   DDRB |= (1 << PB2) | (1 << PB3) | (1 << PB5); //Настроить выводы DDRB на выход
   SPCR |= (1<<MSTR)|(1<<SPR0); //Режим мастер, F=Fosc/16
   SPCR |=(1<<SPE);//Включить SPI
        PORTB |= (1 << PB2);
}

 void SPI_Send_byte(char data)
{
        PORTB &= ~(1 << PB2);
   SPDR = data; //Отправить байт
   while(!(SPSR&(1<<SPIF))) ; //Дождаться окончания передачи
   PORTB |= (1 << PB2);
}



int main(void)
{
   SPI_Init();
   _delay_ms(20);
   while (1)
   {
      SPI_Send_byte('H');
   }
}


Слейв (U2)
Код:
#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>


void SPI_Init_Slave(void)
{
   DDRB &= ~((1<<2)|(1<<3)|(1<<5));   // SCK, MOSI and SS as inputs
   DDRB |= (1<<4);
   SPCR |= (1<<SPR0);
   SPCR |=(1<<SPE);      //Включить SPI
   SPSR = 0x00; SPDR = 0x00;
}

char SPI_Receive(void)
{
   while (!(SPSR & (1 << SPIF)));
   return SPDR;
}

int main(void)
{
   char letter;
   SPI_Init_Slave();
   
    while (1)
    {
       letter = SPI_Receive();
    }
}
.
Привожу фотку, на которой показана передача данных, а так же факт того, что данные не записываются в регистр SPDR (U2) - Изображение.
Прошу помочь понять на каком этапе я ошибаюсь, чтобы исправить проблему. Заранее спасибо!

Re: Отсутствие данных в SPDR

Вт сен 12, 2017 10:50:19

Вы лучше поглядите переменную letter, только как volatile ее объявите, а то наверняка с оптимизирована.

Re: Отсутствие данных в SPDR

Вт сен 12, 2017 11:04:34

О, спасибо большое. Заработало. Пойду читать что это за зверь такой volatile. Еще раз спасибо.

Re: Отсутствие данных в SPDR

Ср сен 13, 2017 05:48:32

При окончании приема данных в регистре SPSR выставляется флаг SPIF. В блоке инициализации перед работой с SPI этот флаг нужно сбрасывать записывая в него 1 (даташит). В программе проверяем этот флаг. Если установлен, сбрасываем флаг, считываем содержимое.
Если включаем прерывание, то этот флаг сбрасывается аппаратно при входе в прерывание.
volatile в вашем случае не обязательно. Можно объявить переменную как extern, но применение глобальных переменных рекомендуется минимизировать. Можно объявить как static. Но нужно учитывать, что static - локальная переменная, и применяется только в своем программном модуле (файле, если программа разбита на модули-файлы). В вашем случае все в одном файле-простыне, так что можно.

Re: Отсутствие данных в SPDR

Ср сен 13, 2017 06:27:56

Demiurg писал(а):В блоке инициализации перед работой с SPI этот флаг нужно сбрасывать
Необходимости в этом никакой нет, если инициализация происходит после сброса МК.
Demiurg писал(а):нужно сбрасывать записывая в него 1 (даташит).
Это в каком ДШ так написано?
Demiurg писал(а):volatile в вашем случае не обязательно.
Человеку надо было посмотреть что принял МК. Регистр SPDR, по факту буферный на сколько я знаю, чтобы в него попали данные из сдвигового регистра надо его прочитать. Протеус , опять же скорее всего, не отображал принятые данные из сдвигового регистра, кроме того это всего-лишь симулятор. А так как переменная была выкинута оптимизатором, то по факту с регистра ничего не читалось.
Demiurg писал(а):Можно объявить переменную как extern,
Приведите пример, касательно исходника ТС. Лично я не понял как это.

Re: Отсутствие данных в SPDR

Ср сен 13, 2017 06:50:41

Demiurg писал(а):volatile в вашем случае не обязательно. Можно объявить переменную как extern
volatile != extern
volatile означает, что переменная может измениться в любой момент, и поэтому её нельзя никак кэшировать
extern означает лишь объявление переменной где-то в другом модуле, т.е. эта переменная подлежит кэшированию.

в выражении a = b + b + b + b; при extern b компилятор имеет полное право сделать a = b << 2 (для оптимизации по скорости или размеру; более того, если b уже была где-то выше по тексту помещена в промежуточный регистр, все действия компилятор может делать именно с этим регистром), в то время как при volаtile b он не только сложит 4 раза, но и перед каждым сложением будет считывать содержимое соответствующих ячеек памяти.

то есть если предположить, что переменная b=0 инкрементируется в прерывании с очень большой скоростью, с extern вы получите, допустим, 0, а с volatile получите 6.

Re: Отсутствие данных в SPDR

Ср сен 13, 2017 06:56:42

Z_h_e писал(а):Необходимости в этом никакой нет, если инициализация происходит после сброса МК.

При работе устройства МК может сброситься (теоретически). Поэтому при работе с периферией этот момент нужно учитывать всегда. Также при работе с периферией нужно учитывать, что в одном регистре ввода-вывода могут висеть несколько периферийных модулей.
Есть непосредственная запись значения. Также есть чтение-модификация-запись.
Здесь могут быть различные варианты инициализации периферийных модулей.
С непосредственной записью значений все понятно. Пусть даже МК сбросился и в регистрах ввода-вывода непонятная каша, мы все равно записываем нужные данные, сбрасывая ненужные биты и выставляя нужные.
С вариантом чтение-модификация-запись посложнее. Берем для примера регистр TIMSK. В нем настройка нескольких таймеров. И если у нас работают несколько таймеров, то порядок инициализации в программе должен быть следующий: инициализируем первый таймер (порядок не аппаратный, а по проекту) - непосредственная запись. Инициализация следующих таймеров уже по варианту чтение-модификация-запись. Иначе, если мы будем делать непосредственную запись, мы похерим настройки предыдущего таймера.
Но представим следующую ситуацию. МК нештатно сбросился, в регистре каша, а мы делаем чтение-модификация-запись. Сами понимаете, что в этом случае программа будет работать некорректно.

Z_h_e писал(а):
Demiurg писал(а):нужно сбрасывать записывая в него 1 (даташит).

Это в каком ДШ так написано?

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

Z_h_e писал(а):
Demiurg писал(а):Можно объявить переменную как extern

Приведите пример, касательно исходника ТС. Лично я не понял как это.

Позже, я на работе.

Компилятор выкинул letter по простой причине: эта переменная больше нигде не используется. Да, объявляя ее volatile, вы заставили компилятор не выкидывать соответствующий кусок кода. Но зная, как ведет себя тот компилятор, с которым вы работаете, можете варьировать свою программу при работе с переменными.

Re: Отсутствие данных в SPDR

Ср сен 13, 2017 07:08:56

Demiurg писал(а):...МК нештатно сбросился, в регистре каша, а мы делаем чтение-модификация-запись. ...
Та же чушь, как и про случайные прерывания вдругом топике. Если МК сбросился, значит регистры переинициализированы МК аппаратно.
Demiurg писал(а): то сброс соответствующих флагов при непосредственном опросе - обязанность программиста.
Я не спрашивал зачем сбрасывать. Вы говорите что сброс данного флага производится записью 1 и ссылаетесь на ДШ. В каком ДШ это написано?

Добавлено after 4 minutes 52 seconds:
Demiurg писал(а):Да, объявляя ее volatile, вы заставили компилятор не выкидывать соответствующий кусок кода.
Вы невнимательно прочитали вопрос ТС и мое объяснение почему так вышло. ТС не видел принятых данных, наблюдая за регистром SPDR (а на самом деле они были и все работало и так).

Re: Отсутствие данных в SPDR

Ср сен 13, 2017 07:19:43

Z_h_e писал(а):ТС не видел принятых данных, наблюдая за регистром SPDR
Та же песня и с SDR для USART: протеус (и, если не ошибаюсь, даже студия) не понимает, какое содержимое "двойного" регистра показывать при отладке - то, которое было записано из кода, или то, которое было записано из аппаратуры.

почему разработчики симуляторов не дотумкали отображать сдвоенный регист в виде двух "теневых" - не понятно...

Re: Отсутствие данных в SPDR

Ср сен 13, 2017 07:22:53

Тут вроде как не двойной, ибо сдвигается один и тот же регистр и при приеме и при передаче, все же скорее буферный. Но песня все равно та же :).

Re: Отсутствие данных в SPDR

Ср сен 13, 2017 07:24:22

Z_h_e писал(а):...

1 - Я не собираюсь с вами спорить. Это ваши проекты. Что хотите, то и делайте. Ваша ответственность.
2 - Откройте даташит на любой AVR, раздел SPI, сводка регистров, флаг SPIF. Там все увидите.
Bit 7 – SPIF0: SPI Interrupt Flag
When a serial transfer is complete, the SPIF Flag is set. An interrupt is generated if SPIE in SPCR is set
and global interrupts are enabled. If SS is an input and is driven low when the SPI is in Master mode, this
will also set the SPIF Flag. 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).

3 - Нужно смотреть листинг кода. Либо прогонять программу в симуляторе AVR-Studio. Это товарищ еще неопытный, потому еще и не знает куда смотреть, чтобы понять, что вообще происходит.

Re: Отсутствие данных в SPDR

Ср сен 13, 2017 07:27:46

Demiurg писал(а):Откройте даташит на любой AVR, раздел SPI, сводка регистров, флаг SPIF. Там все увидите.
Ну и прочитайте сами что там написано, а не тупо цитируйте.

Добавлено after 1 minute 28 seconds:
Demiurg писал(а):Это товарищ еще неопытный, потому еще и не знает куда смотреть,
Это не повод писать ему всякую ересь.

Re: Отсутствие данных в SPDR

Ср сен 13, 2017 07:32:04

[занудство ON]
Z_h_e писал(а):Это не повод писать ему всякую ересь
ему-то как раз и можно писать ересь, а вот для него писать ересь совсем не стоит. ну или советовать ему... :))) :beer:
[занудство OFF]

Re: Отсутствие данных в SPDR

Ср сен 13, 2017 07:40:41

Ему, в смысле для ТСа а не ТСом.

Добавлено after 2 minutes 44 seconds:
Да не, вроде правильно все написал, по-русски. Ему, значит для кого, дательный падеж... :dont_know:

Re: Отсутствие данных в SPDR

Ср сен 13, 2017 07:46:44

Йопт. Походу не совсем еще проснулся. Так, действительно флаг SPIF сбрасывается при чтении SPDR. Но, при ПЕРВОМ чтении! То есть, может быть ситуация, когда флаг нужно сбрасывать.
Написал про сброс статусных флагов по привычке, статусные флаги нужно сбрасывать записью в них 1. Так что не совсем ересь. Вы лучше сразу уточняйте в следующий раз. Чем сходу обвинять в ереси.

Re: Отсутствие данных в SPDR

Ср сен 13, 2017 07:52:27

Кстати, alarig1995A, Вы молодец и правильно задали свой вопрос. Выложили именно то, что нужно, чтобы получить ответ. Обычно вопросы задают, так что без спиритического сеанса ничего не понятно.

Добавлено after 4 minutes 5 seconds:
Demiurg писал(а):Так, действительно флаг SPIF сбрасывается при чтении SPDR. Но, при ПЕРВОМ чтении!
Опять неверно. А так как Вы профессионал, объяснять не буду.

Demiurg писал(а):Вы лучше сразу уточняйте в следующий раз. Чем сходу обвинять в ереси.
Я бы сразу написал, но так уверенно на ДШ ссылались. Но это мелочь в целом. А вот случайные какие-то сбросы МК приводящие к случайным состояниям...

Re: Отсутствие данных в SPDR

Ср сен 13, 2017 08:24:55

Должна быть таблица регистров ввода-вывода, сбрасываемых аппаратно при сбросе. Притом должно быть уточнение, по какой причине был сброс. Не могу найти. Я занят, был бы признателен, если вы знаете, где есть такие таблицы. Либо текстовое указание диапазона адресов регистров ввода-вывода, сбрасываемых аппаратно при сбросе.

Re: Отсутствие данных в SPDR

Ср сен 13, 2017 08:46:35

Demiurg писал(а): таблица регистров ввода-вывода, сбрасываемых аппаратно при сбросе.
ну вот для atmega8 например
Изображение
Demiurg писал(а):Притом должно быть уточнение, по какой причине был сброс
причина сброса не важна
Вложения
screenshot-www.atmel.com-2017-09-13-09-43-29.png
(18.99 KiB) Скачиваний: 967

Re: Отсутствие данных в SPDR

Ср сен 13, 2017 09:18:11

Причину сброса выяснить можно, вот для той же меге8
СпойлерИзображение


Добавлено after 5 minutes 43 seconds:
Demiurg писал(а):Должна быть таблица регистров ввода-вывода, сбрасываемых аппаратно при сбросе.
Я не встречал такого. Может есть конечно где. У STM есть такие, только они не обобщенные для всех, а только для конкретной каждой периферии. Но я ими не пользуюсь, по-моему все равно надо смотреть описание каждого регистра отдельно, а на память свою я давно не полагаюсь, очень она у меня ненадежная :).
Вложения
res.gif
(23.19 KiB) Скачиваний: 287

Re: Отсутствие данных в SPDR

Ср сен 13, 2017 09:22:12

Про initial value забыл. Помню, что где-то была информация, какое значение в регистре при сбросе.
Про флаги причины сброса можно было не писать.
Кстати, в последней же вашей приведенной картинке указано, что сброс флагов запись 1-цы в соответствующий бит. Я из этого исходил, когда говорил про это. Написал по привычке.
Тут есть один нюанс с регистрами ввода-вывода. Часть регистров лежит в определенной области. Начиная с определенного адреса обычными командами до этих регистров не добраться, только через lds-sts.
Ответить