0 / 0 / 0
Регистрация: 26.08.2013
Сообщений: 128
1

Интерфейс SPI ответные данные

24.10.2013, 11:59. Показов 21364. Ответов 52
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
И снова про SPI...

Помогите, уважаемые форумчане, уже всю голову сломал...

Описание задачи и проблем:

Есть два мк - атмега8
Связаны по интерфейсу SPI
У Атмеги, которая Мастер, включен USORT

Мастеру по USORT всё время приходят данные, которые могут меняться в определённый момент времени
Слейв эти данные обрабатывает и что-то у себя делает (например зажигает светодиодики на порте D)

Выводы SS запараллелены, то есть SS Мастера соединён с SS Слейва. Это я сделал для того, чтобы переводить Слейв в режим ожидания после передачи очередного байта от Мастера

Согласно теории известно, что обмениваясь данными по SPI, Слейв отсылает Мастеру так называемую "ответку", то есть одновременно с передачей данных от Мастера к Слейву происходит и передача в обратном направлении.

У меня задача стоит так, чтобы в "ответке" от Слейва посылать не чушь какую нибудь, а например, состояние порта С, а потом, Мастером считывать эту ответку и отправлять по USORT. То есть осуществить полный цикл взаимообмена между двумя микроконтроллерами.

Как это сделать? Я это делаю управлением флагом SPIF. То есть ожиданием окончания передачи очередного байта. Как байт передался, а записываю в регистр SPDR "ответку":

Код
...
while (1)
{
PORTD=SPDR;        //зажигаем светодиодики, по приходу данных от Мастера
while(!(SPSR & (1<<SPIF))){};  //ждём окончания передачи
SPDR = PINC;        //записываем состояние порта С в сдвиговый регитр -
// - "ответка"
};
В Мастере я делаю аналогичным образом:

Код
...
char spyperemen;                //объявление переменных
char spyperemen2;

while (1)
{

spyperemen = getchar();      //записал принятые данные от USORT в переменную

PORTB.2 = 0;                     //подал на вывод SS напряжение низкого лог. ур.
SPDR = spyperemen;            //записал в сдвиговый регистр SPI значение
//переменной USORTа - инициировал передачу
//по SPI

while(!(SPSR & (1<<SPIF))) {}  //жду окончания передачи

spyperemen2 = SPDR;           //вот тут пришла "ответка" от Слева и я её записал
//в переменную

putchar(spyperemen2);         //отправил "ответку" по USORT

PORTB.2 = 1;                     //подал на вывод SS напряжение высокого лог. ур.
//перевёл Слейв в режим ожидания следующего
//байта
}
Так вот, и вроде бы всё хорошо, и должно работать...
Но, почему то, Мастер кидает по USORT два значения регистра SPDR. Значение "ответки" и уже переданное по SPI значение (назовём его байт передачи)...

Как я только не извращался чтобы оставить только "ответку" и только её передавать по USORT (пробывал методами сравнения, с помощью if, типо если переменные не равны между собой только тогда отправлять значение регистра; задержки пробывал ставить в разных местах; через прерывание по SPI делать...), но у меня ничего не вышло - всё равно так или иначе просачивался байт передачи.

Как итог в USORT приходило то состояние порта С Слейва, то данные, которые пришли по USORT Мастеру.

Как я думаю Мастер опознаёт два разных значения сдвигового регистра SPDR как одно и шлёт то то, что нужно, а то то, что записали в регистр

Может кто сталкивался с подобным... Или подскажет как другими методами организовать полный взаимный обмен по SPI между двумя мк...

Как всегда буду признателен за все советы и оказанную помощь

ЗЫ: извиняюсь за быдлокод, работаю в CodeVisionAVR
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.10.2013, 11:59
Ответы с готовыми решениями:

не успеваю отправлять данные по шине SPI
Всем привет! Я столкнулся со следующей проблемой. происходит обмен между AVR ATMEGA328P(slave) и...

Использование microSDHC карт через SPI интерфейс
Собственно вопрос таков, можно ли использовать microSDHC карты через SPI а не через SDIO интерфейс....

Запись данных в флэш W25Q, интерфейс SPI. STM32F103
Всем привет.:) Появилась идея записывать данные сенсора / сенсоров в флэш память W25Q128. Ни разу...

STM32f4 Spi - при первой передаче искажаются данные
Здравствуйте Задача получать данные устройством по spi Проблема в том, что первые полученные...

ILI9341 SPI DMA, SPI, UART библиотеки
Доброго времени, форумчане... Посоветуйте библиотек плиз... 0) Либа для работы с контроллером по...

52
0 / 0 / 0
Регистрация: 26.08.2013
Сообщений: 128
27.10.2013, 16:32 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от OtyxPM
На внутреннем RC нельзя обеспечить стабильную работу USORT
хорошо, попробую с кварцем, отпишусь, спасибо... какое то странное поведение вобще, вроде всё так, а почему то проскакивает этот байт, хотя никаким образом бы не должен согласно коду
0
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
27.10.2013, 17:36 22
Значит , код написан так , что в определённый момент возникает ситуация для отсылки байта.
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
27.10.2013, 17:59 23
Цитата Сообщение от YTYOUT
Значит , код написан так , что в определённый момент возникает ситуация для отсылки байта.
Можно с чем-то в коде сопоставить этот "определённый момент" (к каким событиям/условиям он привязан)? Если сложно предположить, то мог бы помочь логический анализатор.
Стабильна ли частота возникновения "определённого момента"? Если да, то чему примерно равна эта частота?
Как отправляется этот лишний байт - в дополнение к нужным или вместо одного из нужных?
0
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
27.10.2013, 18:13 24
Можно с чем-то в коде сопоставить этот "определённый момент" (к каким событиям/условиям он привязан)?
По идее можно. Так или иначе , но что-то запихивает байт в буфер передатчика и при этом передача разрешена. Или байт запихнули , а передачи запретили , затем разрешили.
0
0 / 0 / 0
Регистрация: 26.08.2013
Сообщений: 128
30.10.2013, 12:48 25
Цитата Сообщение от OtyxPM
Можно с чем-то в коде сопоставить этот "определённый момент" (к каким событиям/условиям он привязан)? Если сложно предположить, то мог бы помочь логический анализатор.
Стабильна ли частота возникновения "определённого момента"? Если да, то чему примерно равна эта частота?
Как отправляется этот лишний байт - в дополнение к нужным или вместо одного из нужных?
Дело в том, что этот байт проникал совершенно спонтанно, если бы с какой то частотой, я бы это и на глаз заметил... Конечно Вы правы, нужен логический анализатор чтобы точно утверждать
Но как выход из ситуации, я всё таки применил оператор if на приёмной стороне данных USORTа, как то так:
Код
if (getchar() != PINB)       //если принятая посылка не равна байту передачи
//то обрабатываем данные
{
use_function();              //функция обработки принятых данных
}
Но чем вызвано проникновение байта передачи для меня пока остаётся загадкой...
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
30.10.2013, 13:13 26
Цитата Сообщение от sko33
Но как выход из ситуации, я всё таки применил оператор if на приёмной стороне данных USORTа, как то так:Код:
if (getchar() != PINB) //если принятая посылка не равна байту передачи
//то обрабатываем данные
{
погасить_индикатор_бага();
use_function(); //функция обработки принятых данных
}
else
{
включить_индикатор_бага(); //так можно будет визуально следить за спонтанной ошибкой - может, наведёт на мысль
}
Индикатор - сверхяркий светодиод (с резистором, конечно) на каком-нибудь свободном пине МК.
0
0 / 0 / 0
Регистрация: 26.08.2013
Сообщений: 128
30.10.2013, 16:06 27
Цитата Сообщение от stritsh
Попробуйте так, для слейва
Код:
while(!(SPSR & (1<<SPIF))); // ожидание окончания передачи
temp = SPSR; //обнуляем флаг SPIF
data = SPDR; //считываем данные от мастера
SPDR = данные мастеру;

для мастера
Код
 CS = 0;
SPDR = данные слейву;
while(!(SPSR & (1<<SPIF)));   // ожидание окончания передачи
temp = SPSR;  //обнуляем флаг SPIF
data = SPDR;    //считываем данные от слейва
CS = 1;
А как организовать передачу двух байт по SPI ?

Мне нужно мастером последовательно отправить два одинаковых байта, слейвом их принять, а в значениях "ответок" слать два разных байта, потом эти ответки слать по USORTу. А на приёмной стороне USORTа объединять эти ответки в одну переменную типа int (назову её "общаяя ответка").

Я сейчас пытался это сделать. Делал так:

Мастер:
Код
PORTB.2=0;                             //CS = 0

SPDR = spyperemen;                  //записал в сдвиговый регистр SPI первый байт
while(!(SPSR & (1<<SPIF)));       //жду окончания передачи
spi_tumbler1 = SPDR;                //сбрасываем флаг SPIF, считываем данные от
//Слейва - "ответка1"

SPDR = spyperemen;                  //записал в сдвиговый регистр SPI второй байт
while(!(SPSR & (1<<SPIF)));       //жду окончания передачи
spi_tumbler2 = SPDR;                //сбрасываем флаг SPIF, считываем данные от
//Слейва - "ответка2"

PORTB.2=1;                             //CS = 1
Слейв:
Код
char temp;                              //переменные для двух раных "ответок"
char temp2;

while(!(SPSR & (1<<SPIF)));       //жду
PORTD=SPDR;                          //принял от Мастера первый байт,
//зажёг светодиодики
SPDR = temp;                          //записал "ответку1"

while(!(SPSR & (1<<SPIF)));        //жду
PORTD=SPDR;                          //принял от Мастера второй байт,
//зажёг светодиодики
SPDR = temp2;                         //записал "ответку2"
Но что то на приёмной стороне от USORTа получал столько разных значений "общей ответки"... Возможно это можно объяснить тем, что регистр SPDR один, и поэтому Мастер опознаёт их по разному в определённый момент времени и соответственно шлёт разные данные по USORTу.

И как организовать просто взаимный обмен двумя байтами? - тут я затрудняюсь.. Уверенности нет в том, что Мастер отправлял именно два байта, так как я посылаю их одинаковыми

совсем я запутался :(

благо с циклом полного обмена одним байтом разобрался благодаря Вам, однако с небольшим багом, который описал выше, тут пока никак
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
30.10.2013, 16:27 28
Цитата Сообщение от sko33
И как организовать просто взаимный обмен двумя байтами? - тут я затрудняюсь.. В даташите написано, что после передачи очередного байта Мастер может начать передачу следующего.
Комментарии в коде настораживают. Вы понимаете, что ответ от slave всегда приходит с задержкой в один байт? Нарисуйте на листке буниги диаграмму обмена, чтобы точно всё было ясно.
<ul><li>Master послал байт M1; байт дошёл до Slave целиком (8 бит); взамен Master получил какой-то старый байт от Slave;</li><li>только после этого на стороне Slave взвёлся флаг "что-то прислано, можно брать";</li><li>Slave забирает M1 и кладёт свой байт S1 в регистр SPDR - Master когда-нибудь потом его заберёт, тактируя шину клоками SCL;</li><li>Master решает послать байт M2; байт дошёл до Slave целиком (8 бит); взамен Master получил байт S1 от Slave;</li><li>только после этого на стороне Slave взвёлся флаг "что-то прислано, можно брать";</li><li>Slave забирает M2 и кладёт свой байт S2 в регистр SPDR - Master когда-нибудь потом его заберёт, тактируя шину клоками SCL;</li><li>и так далее.</li></ul>
Если Вам так необходимо убрать задержку в один байт (надо ли? ведь тогда ответ Slaveа не сможет зависеть от команды Masterа), то введите в протокол обмена дополнительный сигнал, которым Master будет предупреждать Slave о том, что сейчас начнётся обмен.
0
0 / 0 / 0
Регистрация: 26.08.2013
Сообщений: 128
30.10.2013, 16:42 29
Цитата Сообщение от OtyxPM
Вы понимаете, что ответ от slave всегда приходит с задержкой в один байт?
спасибо за столь подробное описание, да, действительно Мастеру в начале приходит какой то старый байт от Слейва, что я с ним могу сделать? записать куда-нибудь в самом начале кода перед циклом обмена?
Постите за нубство, ну а в случае с полным взаимным обменом одного байта я ничего ведь не делал со старым ответным байтом - и всё работало
Или Вы имеете ввиду такое нужно только в протоколе обмена несколькими байтами
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
30.10.2013, 17:14 30
Ненужный байт просто игнорируйте, его можно никуда не записывать.
0
0 / 0 / 0
Регистрация: 26.08.2013
Сообщений: 128
30.10.2013, 17:53 31
Цитата Сообщение от OtyxPM
Ненужный байт просто игнорируйте, его можно никуда не записывать.
хорошо, ещё более тупой вопрос, как сделать этот игнор до начала передачи
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
30.10.2013, 18:03 32
Цитата Сообщение от sko33
как сделать этот игнор до начала передачи
Статический флаг (переменную) объявите:
Код
bool уже_что_то_принимали_от_слейва = FALSE;
А в коде Masterа вставьте проверку:
Код
принятый_байт = spi_send_receive(передаваемый_байт);
if (уже_что_то_принимали_от_слейва == TRUE) {
использование(принятый_байт);
}
else {
уже_что_то_принимали_от_слейва = TRUE;  //на первый раз игнорируем байт, но впредь будем использовать
}
0
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
30.10.2013, 19:24 33
А можно сразу начинать с пункта :)
кладёт свой байт S1 в регистр SPDR - Master когда-нибудь потом его заберёт
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
30.10.2013, 19:41 34
[QUOTE="YTYOUT"]А можно сразу начинать с пункта :)
[QUOTE="Цитата:[/QUOTE]
кладёт свой байт S1 в регистр SPDR - Master когда-нибудь потом его заберёт
Конечно! :-)

Если только:
(*) значение S1 имеет смысл до получения команды от Masterа;
(**) slave точно успеет положить S1 на отправку раньше, чем Master начнёт передачу;
(***) данные S1 уже готовы (это могут быть данные от датчиков, например, а им нужно стартовое время) в этот момент.

В общем, автору сподручнее будет выбрать удобный вариант начала обмена. Будь мы телепаты (добрые телепаты) - сразу могли бы подсказать правильный способ ;-)
0
0 / 0 / 0
Регистрация: 26.08.2013
Сообщений: 128
30.10.2013, 19:42 35
A CS опускать и поднимать только в начале и конце пакета данных?
Код
CS=0;                             //слейв готов принимать данные
пакет байтов данных
CS=1;                             //перевели слейв в состояние ожидания
или же ещё как то надо управлять CS для передачи нескольких байт...
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
30.10.2013, 19:52 36
Цитата Сообщение от sko33
A CS опускать и поднимать только в начале и конце пакета данных?
Если специфика SPI-девайса не требует обрамления каждого байта сигналом CS (а у Вас микроконтроллеры - они этого не требуют), то удобнее сразу весь пакет обрамлять. Заодно slaveу будет синхронизация "начало пакета - конец пакета".
0
0 / 0 / 0
Регистрация: 26.08.2013
Сообщений: 128
30.10.2013, 19:56 37
Интересно, но сложновато, завтра буду осваивать в железе, отпишусь
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
30.10.2013, 20:18 38
Почему сложновато? Это же буквально то, что Вы предложили:
Код
CS=0;
пакет байтов данных
CS=1;
0
0 / 0 / 0
Регистрация: 26.08.2013
Сообщений: 128
30.10.2013, 20:22 39
Цитата Сообщение от OtyxPM
Почему сложновато?
я имел ввиду про общую реализацию :-)
0
0 / 0 / 0
Регистрация: 26.08.2013
Сообщений: 128
30.10.2013, 20:29 40
а так конечно переживаю за ответные от слейва данные, получится ли без мусора у меня или нет
0
30.10.2013, 20:29
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
30.10.2013, 20:29
Помогаю со студенческими работами здесь

SPI интерфейс
Привет всем, начинаю программировать с интерфейсами SPI используя SUB-20 , хочу узнать занимается...

SPI-подобный интерфейс
Цель: организовать последовательный интерфейс обмена данными. Входные сигналы: CLK (тактовая),...

Отладочный интерфейс на SPI и ЖКИ
Появилась у меня идея. Нужна в проекте какая-то отладочная &quot;печать&quot;. Поскольку UART у меня уже...

Таймаут ожидание ответа от slave-устройства (SPI интерфейс)
Добрый день. Каким образом можно установить таймаут ожидания ответа от slave-устройства (SPI...

ответные ссылки
Часто встречаю такую тему у всяких сайтов. В списке ссылок на сайт (напр. с yahoo) куча ссылок, на...

Куда вставлять ответные ссылки?
Есть новый сайт. Поделитесь мнениями на счет каталога ответных ссылок. Может его сделать на сайте...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru