Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Связь mega8 -> t2313 по SPI
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
amost
здравствуйте.

пришлось связать два камня по SPI. передача данных в одну сторону Mega8 (master) --> tiny2313. инициализацию мастера и слейва сделал по ДШ.

mega8:

Код
void SPIinit(void)
{
    DDRB |= (1<<PIN_SPI_MOSI) | (1<<PIN_SPI_SCK) | (1<<PIN_SPI_SS);
    SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0);
}


t2313:
Код
void USIinit(void)
{
    DDRB = (1<<USI_PIN_DO);
    PORTB |=  (1<<USI_PIN_DI) | (1<<USI_PIN_SCK);
    USICR = (1<<USIOIE) | (1<<USIWM0) | (1<<USICS1);            
}


отправляю байт

Код
void SPI_send_byte(char data)
{
    SPDR = data;
    while( !(SPSR & (1<<SPIF)) )
    ;
}


принимаю на тиньке
Код
ISR (USI_OVERFLOW_vect)
{
    USISR |= (1<<USIOIF);

    usi_in_buf[gBuf_ind_in] = USIDR;
    gBuf_ind_in++;
}


после получения каждого нового символа передаю его слэйвом по UART.

так вот, один байт таким способом я принять могу, но если посылается несколько байт -- получается каша. правильно принимается только последний символ из всего потока. ставлю после передачи каждого символа задержку --
Код
    SPI_send_byte('b');
    _delay_loop_1(48);
    SPI_send_byte('a');
    _delay_loop_1(48);
    SPI_send_byte('d');
    _delay_loop_1(48);
    SPI_send_byte(' ');


-- слэйв принимает нормально. да, если нужно то mega запущена на 16МГц, tiny2313 -- 8МГц. клок на SPI на мастере делится на 16. если делить на 128 то нормально принимает при значении задержки между символами приблизительно 3мкс (начинает принимать нормально при _delay_loop_1(15)).

изначально, было две версии:
1. передача очередного байта начинается до завершения передачи предыдущего. думаю этот вариант исключается поллингом флага SPIF, и флага WCOL. (?)
2. тинька не успевает обрабатывать поток данных. этот вариант тоже вроде как исключил -- понизил частоту клока, сократил до минимума обработчик прерывания. пробовал даже после 4-5 принятых в ОЗУ символов запрещать прерывания на слэйве и спокойненько выдавать буфер в UART.

теоретически, могу оставить задержки между символами. но хочется же знать в чем соль. хотя бы на чьей стороне? мастер/слэйв?

да, мой первый проэкт именно на C. могу чего-то не знать.
DpInRock
При таком многословии надо бы соблюдать правила языка общения. Что будет, если придет один лишний клок на 2313?
amost
а откуда ему взяться, этому лишнему клоку? там же просто все должно быть -- байт отправил, дождался окончания передачи, отправил следующий.
_Pasha
Цитата(amost @ Sep 2 2009, 18:48) *
после получения каждого нового символа передаю его слэйвом по UART.

Приведите пож код, каким образом Вы его передаете по UART.
DpInRock
Цитата
а откуда ему взяться

Вариантов - очень много. Перечислять - неинтересно. Поставьте последовательно с клоками резистор 33 ома ближе к меге8.

А кроме того, такая ситуация должна быть предусмотрена все равно. Иначе все очень ненадежно и примитивно.
SasaVitebsk
Я что-то не увидел из текста - а вы SS-ом дёргаете?

Неоднократно связывал камни по SPI выходил на максимальную скорость. Никаких задержек не ставил. Но синхронизация должна быть. Либо апппаратная (SS), либо программная.
DpInRock
У 2313 нет никакого SS. Просто тупой сдвиговый регистр. Чуть что не так - пишите письма. Как мастер - нормально, как слэйв - не очень. Вернее, очень ненормально. Вот поменять местами мегу и тиньку - и будет нормально по-людски.
amost
Цитата(_Pasha @ Sep 3 2009, 08:59) *
Приведите пож код, каким образом Вы его передаете по UART.

код стандартный, вытянутый из ДШ

Код
void USART_transmit_char(char c)
{
    while ( !( UCSRA & (1 << UDRE)) )
    ;
    UDR = c;
}

...

int main(void)
{
    counter = 0;
    for(;;)
    {
        while (counter < gBuf_ind_in)
            USART_transmit_char(usi_in_buf[counter++]);
        if (counter == IN_BUF_LGTH)
            counter = 0;
    }
}


Цитата
Поставьте последовательно с клоками резистор 33 ома ближе к меге8.

поставил. картина та же.

Цитата
Я что-то не увидел из текста - а вы SS-ом дёргаете?

нет, SS-ом не дергаю. если честно, смысла в этом я не видел. насколько я понял из ДШ, передача каждого байта пакета не сопровождается дерганьем линии SS. SS сбрасывается вначале пакета данных и устанавливается снова по окончании передачи того-же пакета.
Цитата
After shifting one byte, the SPI clock gener-
ator stops, setting the end of Transmission Flag (SPIF). If the SPI interrupt enable bit
(SPIE) in the SPCR Register is set, an interrupt is requested. The Master may continue
to shift the next byte by writing it into SPDR, or signal the end of packet by pulling high
the Slave Select, SS line.
SasaVitebsk
Цитата(DpInRock @ Sep 3 2009, 14:26) *
У 2313 нет никакого SS. Просто тупой сдвиговый регистр. Чуть что не так - пишите письма. Как мастер - нормально, как слэйв - не очень. Вернее, очень ненормально. Вот поменять местами мегу и тиньку - и будет нормально по-людски.

Посмотрел - действительно. Посмотрел у себя - тоже угадали. У меня t2313 мастером. smile.gif Любопытна и дата последнего применения t2313. 10.02.2004. smile.gif Это последняя корректировка файлов. Реально наверное ещё раньше её забросили.

Мало в ней смысла. Цена таже что и у м8, размеры больше, переферии меньше, потребление тоже. smile.gif
_Pasha
Цитата(SasaVitebsk @ Sep 4 2009, 11:35) *
Посмотрел - действительно. Посмотрел у себя - тоже угадали.

Мда-с...
Вот здесь
обсуждали тиньку 261. Теперь получается, что она может быть только мастером.
Вкратце картина такая:
ATTINY261 без кварца будет генерить синус с хорошей долговременной стабильностью, а некий управляющий модуль в качестве слейва будет отдавать все, что надо для генерации, получая попутно все необходимое с АЦП для расчета. Режим передачи непрерывный, пакетами по 8-10 байт(еще не решил)
И вот тут немного ниасилю: как же все-таки синхронизировать таймеры такого "мастера"? Это при том, что нарушать работу ШИМ "низзя", а использовать phase & freq correct pwm не хватит ног у тиньки. Т.Е синхронизация все равно по каналу данных пойдет.
Есть ли у кого советы?
DpInRock
Ну, существует масса извращенных способов последовательной связи.
Если имеем битовый поток, клоки, то разбиение на байты или еще какие единицы - дело программы.

К примеру, самый простой способ - на меге (мастер) дергать SS (либо оно дергается автоматически), а на тиньке - это вход прерывания, по которому быстренько сбрасывается счетчик бит в SPI (это по спадающему фронту). Ну а по нарастающему - программе сообщается, что байт готов к употреблению.

Где-то так.

А у автора топика такая система отсутствует как класс. Он надеется исключительно на авось. И "авось" зачастую работает. На то она и "авось". Это кому какая степень надежности устраивает. Может кто-то любит микропроцессоры, программа которых максимально похожа на человеческий разум - работает по настроению.
_Pasha
Цитата(DpInRock @ Sep 4 2009, 14:51) *
А у автора топика такая система отсутствует как класс. Он надеется исключительно на авось.

Добавлю критики smile.gif
Код
ISR (USI_OVERFLOW_vect)
{
    USISR |= (1<<USIOIF);
    usi_in_buf[gBuf_ind_in] = USIDR;// отсутствует проверка индекса
    if (gBuf_ind_in < IN_BUF_LGTH) gBuf_ind_in++; //хотя бы так
}

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

ЗЫ
Цитата(DpInRock @ Sep 4 2009, 14:51) *
на тиньке - это вход прерывания, по которому быстренько сбрасывается счетчик бит в SPI (это по спадающему фронту). Ну а по нарастающему - программе сообщается, что байт готов к употреблению.

Имхо, такое у меня не прокатит.
Вот для случая кварцованного мастера и бескварцевого слейва синхронизацию обеспечит мастер, начиная передачу в строго определенные моменты времени. Тогда можно отследить с помощью PCINTxx начало передачи - и дело сделано. А для наоборот - вот так smile3046.gif
SasaVitebsk
Если честно, то настораживает то, что у автора топика, правильно передаётся именно последний байт. Если бы у него происходил срыв синхронизации, то у него правильно бы передавались первые несколько, а последнего он бы вообще не получил.

Исходя из того, что у автора правильно принимается последний байт, то смею предположить, что предыдущие портятся при передачи от SPI к USART. Это может происходить по причине сопоставимых скоростей и не верной логике передачи. При отсутствии промежуточного буфера с диагностикой заполнения, необходимо синхронизироваться по медленному потоку.

Ну а на грабли с SS, он похоже наступит несколько позднее.

Так, я делал bootloader на SPI с мастером на IBM по 3 проводам. Пришлось вводить несколько принципов синхронизации пакета, для обеспечения достоверности передачи информации.

При тестировании системы (проверял) запаянной на одной плате, с длиной проводников 10-20мм проблем не возникало. При тестировании в течении пары часов. Но, надо понимать, что один сбой - и всё. Система уже сама никогда не засинхронизируется вновь. Поэтому - не надо конечно каждый байт, но вначале пакета - синхронизация должна быть обязательно.

Автор топика в этом обязательно убедится при сколь-нибудь серьёзном тестировании устройства.
DpInRock
Цитата
Если честно, то настораживает то, что у автора топика, правильно передаётся именно последний байт.

Это как раз совершенно нормально.



Цитата
Вот для случая кварцованного мастера и бескварцевого слейва синхронизацию обеспечит мастер, начиная передачу в строго определенные моменты времени

А вот тут вы чего-то недопонимаете. "Строго определенные моменты времени" порождаются системой синхронизации. А не наоборот, как выражаетесь вы.
_Pasha
Цитата(DpInRock @ Sep 4 2009, 16:36) *
А вот тут вы чего-то недопонимаете. "Строго определенные моменты времени" порождаются системой синхронизации. А не наоборот, как выражаетесь вы.

Ниасилил. Система синхронизации обеспечивается программой кварцованного мастера, инициирующего передачу по прерыванию от таймера, джиттер убирается легко. В этом случае - непрерывного потока нет
Палыч
Цитата(amost @ Sep 2 2009, 18:48) *
...так вот, один байт таким способом я принять могу, но если посылается несколько байт -- получается каша. правильно принимается только последний символ из всего потока. ставлю после передачи каждого символа задержку --
-- слэйв принимает нормально.
Может я чего-то не доглядел в Вашей программе, но, имхо, у Вас проблемы со сбросом бита SPIF. При работе по прерываниям он сбрасывается автоматом при переходе по вектору. А вот, при работе по готовности - посмотрите внимательно в DS
amost
Цитата(DpInRock @ Sep 4 2009, 14:51) *
Ну, существует масса извращенных способов последовательной связи.
Если имеем битовый поток, клоки, то разбиение на байты или еще какие единицы - дело программы.

К примеру, самый простой способ - на меге (мастер) дергать SS (либо оно дергается автоматически), а на тиньке - это вход прерывания, по которому быстренько сбрасывается счетчик бит в SPI (это по спадающему фронту). Ну а по нарастающему - программе сообщается, что байт готов к употреблению.

А у автора топика такая система отсутствует как класс. Он надеется исключительно на авось. И "авось" зачастую работает. На то она и "авось". Это кому какая степень надежности устраивает. Может кто-то любит микропроцессоры, программа которых максимально похожа на человеческий разум - работает по настроению.

да нет, я не надеюсь на авось. Вы красиво критикуете надежность моей системы -- хорошо. я не мудренный опытом разработчик, я просто любитель, который делает для себя полные глюков "поделки". с этой позиции я и читал ДШ, где в упор не увидел и слова о необходимости синхронизации каждого байта по линии SS и сброса счетчика бит SPI. поймите, вопрос о выборе типа последовательной связи не стоит, это можно обойти.

Цитата(_Pasha @ Sep 4 2009, 15:07) *
Добавлю критики smile.gif
И, к тому же, где входной индекс обнуляться будет?
Вообще-то это делается пресловутой очередью, поминаемой в форуме с завидным постоянством.

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

Цитата(Палыч @ Sep 4 2009, 17:01) *
Может я чего-то не доглядел в Вашей программе, но, имхо, у Вас проблемы со сбросом бита SPIF. При работе по прерываниям он сбрасывается автоматом при переходе по вектору. А вот, при работе по готовности - посмотрите внимательно в DS

этот вариант я тоже рассматривал. в ДШ написано, что SPIF сбрасывается автоматически при первом чтении SPSR, т.е. он сбрасывается еще при выполнении поллинга. хотя, наверное, стоит попробовать сбрасывать самому.

спасибо всем за ответы. тема и правда бестолковая. можна закрывать.
DpInRock
Цитата
с этой позиции я и читал ДШ, где в упор не увидел и слова о необходимости синхронизации каждого байта

Так это кому как. Если ВАМ надо, то разделяйте БИТЫ на нужные вам байты.
А я, к примеру, не собираюсь принимать байты, а использую данную периферию для детектирования некой заданной последовательности бит.
Мало ли для чего. А ДШ за вас думать не будет.
SasaVitebsk
Цитата(amost @ Sep 5 2009, 17:05) *
с этой позиции я и читал ДШ, где в упор не увидел и слова о необходимости синхронизации каждого байта по линии SS и сброса счетчика бит SPI.


Открываем любой даташит. Я открыл, к примеру, даташит на atmega88. На странице 153 перед рисунком 67 читаем:

Код
After each data packet, the Master will synchronize the Slave by pulling high the Slave Select,
SS, line.


О синхронизации каждого байта речи не идёт. Но если у вас нет более высокого уровня (деление на пакеты и контроль целостности), то как вы узнаете о том, что синхронизация сбилась? В этом случае проще осуществлять побайтную синхронизацию.

Из рисунка видно, что сам SPI одно из самых примитивных переферийных устройств. По сути, сдвиговый регистр. Совершенно очевидно, что при сбое по линии SCK (например проскочил помеховый дополнительный импульс по SCK), будет искажатся вся последующая информация. Из опыта применения сообщаю вам, что это действительно так и есть. При работе без сигнала SS приходится городить спец процедуру ресинхронизации между пакетами данных. Либо, как, по видимому применял DpInRock, использовать битстаффинг и выделять информацию прямо из битового потока.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.