Обмен по SPI: получение от слейва массива
- Войдите на сайт для отправки комментариев
Втр, 30/03/2021 - 15:16
День добрый, Уважаемые.
Воткнулся вот в какой камешек: мастер по SPI пакетом отправляет int-массив и ждёт такого же массива от слейва. Отправка проходит отлично, слейв всё обрабатывает, но вот обратно отослать получается только байт. Отправку делаю по SPI.transfer(), в официальном доке ардуины даже не стоит возвращаемый тип (a стоит там лаконичное: Returns - the received data).
Попытался разобрать int[] на байты - тоже ничего обнадёживающего не происходит.
int sendToMaster[] = {10,12000,-801, 4321}; byte inBytes[sizeof(sendToMaster)*2]; unsigned int ii=0; for (unsigned int i=0; i<sizeof(sendToMaster);i++) { inBytes[ii] = highByte(sendToMaster[i]); ii++; inBytes[ii] = lowByte(sendToMaster[i]); ii++; } SPDR = inBytes;
не подскажете, куда копать?
А где код мастера и код слейва? Почему Вы их не привели? Как Вам помогать-то? Говорить, что у Вас ошибка в строке №ХЗ? Или как? Давайте код мастера и код слейва (только без лишней муры, если Вы туда ещё напихаете LCD, датчики и передачу на сервер, то сами всё и разгребайте). Компактные коды и пояснения что не так.
Кстати, в Вашем куске кода написан полный бред. Если и остальное такое же :-( Регистр SPRD - один байт. Чего Вы в него массив пихаете? Думаете, влезет?
код слейва я выше привёл
Вы не привели ни кода слейва, ни кода мастера. Под кодом я понимаю то, что я могу запустить у себя - т.е. полный код, а не огрызки.
Так, правильно, весь процесс обмена по SPI заключается в том, что Вы посылаете байт и в ответ тут же принимаете байт. Затем посылаете второй байт и в ответ тут же принимаете байт. И так столько, сколько нужно. Количество переданных байтов всегда равно количсетву принятых. Если надо только принять (слейв ничего не ждёт), то ему посылается какой-нибудь ноль.
Т.е. Вы обмениваетесь по одному байту! Вы же даже попытки не делаете читать ответ после отправки.
Вот полный пример двустороннего обмена.
В даташите Вашего контроллера и в любом описании SPI (не знаю, что Вы называете родным, но про то, что это по сути сдвиговый регистр, написано везде)
Вы никому ничего не должны. Делайте так, как Вам удобнее.
Должен ли я на стороне слейва разбирать массив (например - int[]) на байты и пересылать их по одному по нескольким единичным запросам от мастера, чтобы потом на стороне мастера опять эти байты собрать в интеджеры, а те, соответственно, - в массив?
налицо непонимание структур данных. Любой массив в Си - не важно, инт-ы это, или лонги, или флоаты... или даже какой-то навороченный класс - это всегда массив байт. Поэтому ничего "разбивать на байты" не надо. Берете ссылку на ваш массив, приводите к типу байт и начинаете посылать байты один за другим в цикле:
// отсылаем
SPI.write(*(arr_ptr + i));
"отсылаем" - это здорово! Как принимаем? Конкретно: как master принимает от slave МАССИВ за один запрос?
"отсылаем" - это здорово! Как принимаем? Конкретно: как master принимает от slave МАССИВ за один запрос?
принимает тоже побайтно, смотрите пример выше. что вам дал ЕвгенийП - вы же вроде написали, что "все понятно"
Dimanoss - не пытайтесь принять массив целиком. За раз можно принять только один байт.
Алгоритм простой. я бы даже сказал - ПРОСТЕЙШИЙ. Приняли один байт - сохраните в массив. Приняли следующий - сохраните его в следующую ячейку массива. И так до тех пор, пока не примете столько байт. сколько надо.
Вы ничего не поняли. Никакой строки я не посылаю. Я посылают бай и получаю в ответ байт. Посылаю ещё байт и получаю в ответ ещё байт. И так пока не уйдёт вся строка. И никак по-другому. Я уже писал Вам об этом. Процитирую, а Вы читайте много раз до полного просветления
Т.е. Вы обмениваетесь по одному байту!
Ещё раз: посылаете байт, в ответ получаете байт. Посылаете ещё байт, в ответ получаете ещё байт. И так пока не пошлёте/получите весь Ваш массив.
Конкретно: никак!
Если бы и вправду поняли мой пост и пример, этого вопроса бы не было.
блин, вы правда такой тупой или придуриваетесь? А может вообще не читаете, что вам пишут? Ну ведь на каждый ваш вопрос уже был ранее дан ответ:
Количество переданных байтов всегда равно количсетву принятых. Если надо только принять (слейв ничего не ждёт), то ему посылается какой-нибудь ноль.
Ситуация, когда у мастера есть для отправки, например, пять байт, а ожидает он от слейва - двести, тут не рассматривается? Нет, правда, спасибо, я понял Ваш код, я думал - есть варианты, когда по одному запросу приходит некоторый объём данных (желательно не-фиксированной длины).
Первым байтом отправляете количество байт для приёма. Дальше принимаете сколько сказано - чего сложного?
Первым байтом отправляете количество байт для приёма. Дальше принимаете сколько сказано - чего сложного?
для этого нужно, чтоб на обратной стороне тебя поняли - что означает твой "первый байт"
для этого нужно, чтоб на обратной стороне тебя поняли - что означает твой "первый байт"
А на принимающей стороне программу пишет неизвестный человек? Так нахера ему данные отдавать?
А на принимающей стороне программу пишет неизвестный человек?
как раз известный - это ТС. Поэтому я и сомневаюсь...
как раз известный - это ТС. Поэтому я и сомневаюсь...
А, ну если так, то да - скорее всего неосилит...
Но только байт на байт - по другому никак! Не работает по-другому - забудьте!
На всякий случай:
Если надо принять 201 байт - передаете 201 ноль,
если надо принять 202 байта - передаете 202 нуля,
если надо принять 203 байта - передаете 203 нуля.
Короче: напишите точно, сколько байт Вам надо передать, и я Вам подскажу, сколько надо передать нулей.
да, я примерно так и сделал, спасибо. Сейчас бьюсь с какой-то непоняткой (почему-то первый байт приходит не тот), а так всё уже более-менее в пределах ожидаемого.
Сейчас бьюсь с какой-то непоняткой (почему-то первый байт приходит не тот)
если это вопрос - показывайте код
Слейв:
вот итог:
байты
уходят от слейва
приходят к мастеру
0
0
116
1
48
48
2
248
248
3
47
47
4
0
0
5
99
99
6
0
0
7
21
21
8
8
опять какая-то жуть наворочена. В мастере в строчках 74-78 - что происходит? Вы берете массив из 4х элементов, а отсылаете восемь? -- опять путаете int и byte
В приемнике как увидел работу со String в прерывании и потом вывод этого в Сериал - дальше смотреть не стал. Оно у вас не виснет???
Запомните, вывод в Сериал сам использует прерывания. поэтому пользоваться им внутри другого прерывания нельзя.
вывод в сериал - исключительно для наглядности. В рабочем коде всё это убирается.
В мастере в строчках 74-78 - что происходит? Вы берете массив из 4х элементов, а отсылаете восемь? -- опять путаете int и byte
а как я должен int'ы отсылать, как не побайтно? Один int = два bytes, 4*2=8, не так разве?
ах, да, я докомпримировался (чтобы здесь выложить) до того, что убрал перевод пересылаемых int'ов в байты, сорри. Этот кусок (74-78) вообще тут не нужен.
ах, да, я докомпримировался (чтобы здесь выложить) до того, что убрал перевод пересылаемых int'ов в байты, сорри. Этот кусок (74-78) вообще тут не нужен.
Или вы опять что-то в коде потеряли? Выложите ПРАВИЛЬНЫЙ код, пожалуйста, чтобы не тратить время на обсуждения, что тут верно, а что нет
выходит, вся заковыка в названии функции? :-)
обмен между мастером и слейвом задуман так: иногда мастер отсылает массив слейву и ожидает массив в ответ, иногда ничего не посылает, кроме запроса, ожидая массив, иногда отсылает одну переменную, ожидая только подтверждение получения слейвом этой переменной.
выходит, вся заковыка в названии функции? :-)
заковыка в том, что вы не можете обьяснить. что хотите... Пишете, что что-то отсылаете слейву - а в коде этого нет. А когда не понятно. что же человек хочет добиться - помогать сложно.
В приемнике как увидел работу со String в прерывании и потом вывод этого в Сериал - дальше смотреть не стал. Оно у вас не виснет???
Запомните, вывод в Сериал сам использует прерывания. поэтому пользоваться им внутри другого прерывания нельзя.
Согласен, что без четкого понимания лучше в прерывании лишнего не использовать, но
Сериал на отправку может работать внутри прерываний (По крайней мере на Arduino UNO). Пока есть место в буфере, он просто пишет в буфер. Если в буфере место кончилось, ждет когда освободится место и пока место не освободится блокирует весь остальной код.