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

Не корректно работает передача Slave-to-Master по SPI

Ср сен 26, 2018 22:18:24

От мастера к слейву данные передаются правильно. В обратном направлении теряются байты (в Протеусе). Где ошибка ?

Master:
Код:
  ms_data_out=0xAA; 
 while (1)
      {   
       PORTB.2=0; //SS to 0
       ms_data_out++;
       SPDR=ms_data_out;
       while(!(SPSR & (1<<SPIF)));
        ms_data_in=SPDR;
       PORTD= ms_data_in; //LED
       PORTB.2=1; //SS to 1
       delay_ms(50); 
      }


Slave:
Код:
    sl_data_out=0x04;
while (1)
      {
      SPDR=sl_data_out;
      while(!(SPSR & (1<<SPIF))); 
      sl_data_in=SPDR;
      }

Полный проект с протеусом:
SPI.7z
(27.31 KiB) Скачиваний: 213

Re: Не корректно работает передача Slave-to-Master по SPI

Пт сен 28, 2018 20:53:24

Кое-что удалось выяснить. Прием идет со сдвигом на один бит вправо. Почему не понимаю. До невозможности упростил код.

Master:
Код:
char SPI_ChangeByte(char byte)
{
  PORTB.2=0;      //CS to 0
  SPDR = byte;    //байт для передачи
  while(!(SPSR & (1<<SPIF)));
  PORTB.2=1;       //CS to 1 
  return SPDR;
}
....
....
while (1)
      { 
      n++ ;
      m = SPI_ChangeByte(n);   
      delay_ms(100);
      }

Slave:
Код:
// SPI interrupt service routine
interrupt [SPI_STC] void spi_isr(void)
{
volatile unsigned char data;

data=SPDR;
SPDR=data;
}



Первая итерация:от мастера к слейву пошло 0b0000.0001, от слейва к мастеру должен вернуться 0b0000.0000, но происходит сдвиг в право и возвращается 0b1000.0000.
n - передаваемое от мастера к слейву
m - полученое от слейва мастером
data - полученое слейвом от мастера
Изображение
Третья итерация: от мастера к слейву пошло 0b0000.0011, от слейва к мастеру должно вернуться 0b0000.0010, но со сдвигом получаем 0b0000.0001.
Изображение
Что за шайтан такой?
Вложения
SPI2_test.zip
(139.65 KiB) Скачиваний: 214
2.png
(74.63 KiB) Скачиваний: 1159
1.png
(63.38 KiB) Скачиваний: 1176

Re: Не корректно работает передача Slave-to-Master по SPI

Пт сен 28, 2018 22:56:17

Попробуй перевести spi в mode3
// SPI Clock Phase: Cycle END
// SPI Clock Polarity: HIGH

Re: Не корректно работает передача Slave-to-Master по SPI

Пн окт 15, 2018 13:37:18

проблема только при приеме первого байта. Если не отключать передачу (SS остается в 0), то передача последующих байт проходит без искажений. Именно первьій байт после включения передачи (переводим SS в 0) искажается. На осциллограме видно, что линия MISO (синяя) в перед началом передачи висит в 1, и после передачи первого байта переходит в 0 и пока не вьіключить передачу будет (в неактивной фазе) в 0. Думаю что где-то сдесь собака порьілась.

Re: Не корректно работает передача Slave-to-Master по SPI

Пн окт 15, 2018 15:17:49

Код:
PORTB.2=0; //SS to 0

В Си такое не разрешено. Постарайтесь не использовать нестандартных расширений.
Код:
void main(void)

В Си такое не разрешено. Функция main должна возвращать int.
Код:
volatile unsigned char n=0x00,m=0x00;

Для локальных переменных это не нужно. Вы же не передаете указатели на них в прерывания.
Форматируйте код и удаляйте автогенерированный мусор, это поможет легче находить ошибки.
По существу пока помочь не могу, но попробую разобраться.

Re: Не корректно работает передача Slave-to-Master по SPI

Пн окт 15, 2018 19:51:42

Код:
PORTB.2=0; //SS to 0

В Си такое не разрешено. Постарайтесь не использовать нестандартных расширений.
В CVAVR отлично работает. Интерпретатор пропускает, адекватно воспринимает. Почему бьі не использовать ?
Код:
void main(void)

В Си такое не разрешено. Функция main должна возвращать int.
А если функция ничего не возвращает? В бесконечном цикле крутит одно и тоже ?
Код:
volatile unsigned char n=0x00,m=0x00;

Для локальных переменных это не нужно. Вы же не передаете указатели на них в прерывания.
Форматируйте код и удаляйте автогенерированный мусор, это поможет легче находить ошибки.
Использовал для контроля значения переменньіх в Протеусе. Без volatile не показьівает.
По существу пока помочь не могу, но попробую разобраться.
Спасибо, жду.

Re: Не корректно работает передача Slave-to-Master по SPI

Вт окт 16, 2018 10:47:39

В CVAVR отлично работает. Интерпретатор пропускает, адекватно воспринимает. Почему бьі не использовать ?

Потому что это противоречит стандарту. В cvavr разрешены даже конструкции вида PORTD.2, но это же не значит что ими надо пользоваться! Всю эту ересь приходится исправлять каждый раз для проверки работоспособности на обычном avr-gcc, который лучше следит за стандартом.
А если функция ничего не возвращает? В бесконечном цикле крутит одно и тоже ?

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

В общем-то, ничего толкового не получилось. AVR просто игнорирует первый такт SCK. Единственное что мне удалось - добавить костыль чтобы передавать нужный фронт без помех для других устройств:
Код:
char SPI_Send(char byte){
  PORT_OFF( SPI_CS ); //отключаем CS, если был включен (мало ли)
  SPCR &=~(1<<SPE); //отключаем модель SPI чтобы получить доступ к выводам
  PORT_1(SPI_SCK); //выдаем лог.1 на SCK чтобы при включении SPI сформировался нужный фронт
  PORT_ON( SPI_CS ); //включаем CS перед началом передачи
  SPCR |= (1<<SPE); //включаем сам SPI
 
  SPDR = byte;
  while(!(SPSR & (1<<SPIF))){}
  PORT_OFF( SPI_CS );
 
  return SPDR;
}

Как ни странно, анализатору из Протеуса это извращение не мешает и он читает именно то что было послано. Впрочем, хорошо бы проверить на реальном железе.

Re: Не корректно работает передача Slave-to-Master по SPI

Вт окт 16, 2018 11:00:05

Спасибо! На днях попробую. На вьіходньіх в железе гляну. Дам знать.

Re: Не корректно работает передача Slave-to-Master по SPI

Вт окт 16, 2018 17:50:09

COKPOWEHEU писал(а):PORTB.2=0; //SS to 0
В Си такое не разрешено. Постарайтесь не использовать нестандартных расширений.

Чёй то?)) А что будет если всё же использовать ? ))

Re: Не корректно работает передача Slave-to-Master по SPI

Ср окт 17, 2018 05:44:23

А что будет если всё же использовать ? ))

Вам же сказали, что будет. При попытке компиляции кода в нормальном компиляторе будут ошибки и придется текст править.
Си ведь как раз (почему-то) позиционируется как почти что "кроссплатформенный" язык. Мол, один и тот же код можно компилировать для разных семейств МК. А значит, и в разных компиляторах в том числе.

Re: Не корректно работает передача Slave-to-Master по SPI

Ср окт 17, 2018 11:12:09

В нормальном компиляторе будут ошибки ?

Написал на Си:
DDRB.0=0;
PORTB.0=1;
... и т.д.

Мой компилятор скомпилировал так:
CBI 0x17,0
SBI 0x18,0
... и т.д.

Всё работает. Ошибок нет. http://av-assembler.ru/mc/avr/avr-command.htm#sbi

А если например написать такую конструкцию:
SPCR |= (1<<SPE); //включаем сам SPI
... и т.д.
То мой компилятор выдает ошибки...

А если явно прописывать все биты в регистрах, то ошибок нет:
SPCR=0b01000000; // .1.. .... бит SPE - разрешается работа SPI.
... и т.д.

Или так:
SPCR=0x40; // .1.. .... бит SPE - разрешается работа SPI.
... и т.д.

Так нормально, ошибок нет))

Странно... видимо мой компилятор какой то не нормальный)) :)))

Re: Не корректно работает передача Slave-to-Master по SPI

Ср окт 17, 2018 11:38:50

roman.com писал(а):видимо мой компилятор какой то не нормальный
об этом вам ранее и сообщили

Re: Не корректно работает передача Slave-to-Master по SPI

Ср окт 17, 2018 12:28:49

вообще это был сарказм)) :)))

У меня к SPI подключено куча устройств... и в процессе работы SPI постоянно меняет режим работы. Прописывать регистры явно - проще и надёжней))
А вообще... каждый пишет кому как удобней )) Главное чтобы сам понимал что пишешь))

Re: Не корректно работает передача Slave-to-Master по SPI

Пт окт 19, 2018 13:03:55

Чёй то?)) А что будет если всё же использовать ? ))

Ошибка компиляции, очевидно же.
Код:
$ avr-gcc main.c -mmcu=atmega8
main.c: In function ‘main’:
main.c:4:8: error: expected ‘;’ before numeric constant
   PORTB.2=1;

А если например написать такую конструкцию:
SPCR |= (1<<SPE); //включаем сам SPI

Посмотрите как эта константа называется в вашем компиляторе и используйте ее.
Прописывать регистры явно - проще и надёжней))
Надеюсь, под "прописывать явно" вы понимали не магические константы, а сдвиги и сложения?
Код:
ADCSRA = 0b11001100; //неправильно
ADCSRA = 0xCC; //неправильно
ADCSRA = 204; //неправильно
ADCSRA = (1<<ADEN | 1<<ADSC | 1<<ADIE | 0b100<<ADPS0); //правильно

Из последнего варианта очевидно, что АЦП включается (ADEN), запускается преобразование (ADSC) и разрешается прерывание (ADIE). Настройка частоты менее очевидна, но и слабее влияет на поведение.
А вот первые 3 варианта ошибочны, поскольку это просто ничего не значащие числа, для их расшифровки необходимо лезть в даташит.

Re: Не корректно работает передача Slave-to-Master по SPI

Пт окт 19, 2018 14:55:56

COKPOWEHEU писал(а):Из последнего варианта очевидно, что АЦП включается (ADEN), запускается преобразование (ADSC) и разрешается прерывание (ADIE).

Для кого очевидно? ))
COKPOWEHEU писал(а):А вот первые 3 варианта ошибочны, поскольку это просто ничего не значащие числа, для их расшифровки необходимо лезть в даташит.

Ничего не значащие числа:
ADC.jpg
(51.06 KiB) Скачиваний: 494

//ADCSRA
//1... .... ADEN - 1- вкл ADC.
//.1.. .... ADSC - 1- Старт преобразования.
//..1. .... ADFR - 1- режим Непрерывного Преобразования.
//...1 .... ADIF - 1- флаг завершения преобразования
-сброс программно.
-для прерывания очищается аппаратно.
//.... 1... ADIE - 1- Разрешение прерывания
//.... .1.. ADPS2 - предделетель
//.... ..1. ADPS1 - предделетель
//.... ...1 ADPS0 - предделетель
...
и т.д. и т.п.))

Re: Не корректно работает передача Slave-to-Master по SPI

Пт окт 19, 2018 15:10:27

roman.com писал(а):Ничего не значащие числа
вы вот так слету сможете мне сказать, что делается вот этой командой ADCSRA = 0x27?
вам потребуется не меньше 5 минут, чтобы дать ответ. 99,9% любителей ни за что не обнаружат проблему, если я случайно напишу ADCSRA = 0x28;

вот это и означает "ничего не значащие числа".

Re: Не корректно работает передача Slave-to-Master по SPI

Пт окт 19, 2018 18:59:56

вот так слету сможете мне сказать, что делается вот этой командой ADCSRA = 0x27?

Конечно))

команда ADCSRA = 0x27

// где:
//0... .... ADEN - 0- выкл ADC.
//.0.. .... ADSC - 0- Старт преобразования.
//..1. .... ADFR - 1- режим Непрерывного Преобразования.
//...0 .... ADIF - 0- флаг завершения преобразования
-сброс программно.
-для прерывания очищается аппаратно.
//.... 0... ADIE - 0- Разрешение прерывания
//.... .1.. ADPS2 - предделитель
//.... ..1. ADPS1 - предделитель
//.... ...1 ADPS0 - предделитель

предделитель ADC:
ADPS2 -ADPS1 -ADPS0
/////////////////////////////////////
// 000: 1 МГц/2=500.000 Hz
// 001: 1 МГц/2=500.000 Hz
// 010: 1 МГц/4=200.000 Hz
// 011: 1 МГц/8=125.000 Hz
// 100: 1 МГц/16=62.500 Hz
// 101: 1 МГц/32=31.250 Hz
// 110: 1 МГц/64=15.625 Hz
// 111: 1 МГц/128=7.812,5 Hz
/////////////////////////////////////

Ответ: ADC выключен. Бит ADEN - сброшен))

Ответ на ваш вопрос занял ~2 секунды (больше времени ушло чтоб писать ответ)... )) :)))
если я случайно напишу ADCSRA = 0x28

У меня таки хпроблем нет)) Я чётко прописываю все регистры. Может это и занимает больше времени, зато всё работает без "глюков".
ARV писал(а):99,9% любителей ни за что не обнаружат проблему

Ну значит я в числе 0,1 % (по версии ARV)...))
И в даташит я обычно не смотрю... у меня готовые куски кода на все блоки AVR (с комментариями).
Не стесняйтесь писать подробные комментарии в программе... это сильно облегчает жизнь!))

Re: Не корректно работает передача Slave-to-Master по SPI

Пт окт 19, 2018 19:57:12

вот так слету сможете мне сказать, что делается вот этой командой ADCSRA = 0x27?

Конечно))
Ответ на ваш вопрос занял ~2 секунды (больше времени ушло чтоб писать ответ)... )) :)))

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

И в даташит я обычно не смотрю... у меня готовые куски кода на все блоки AVR

Вы рекомендуете новичкам очень плохой стиль программирования.
Для каких именно "блоков" AVR у вас готовы куски кода?
Например, у ATtiny2313 регистр данных USART называется UDR, а у ATmega168 тот же регистр называется UDR0. Как об этом узнать, если в даташит не заглядывать? При компиляции будет ошибка выдаваться.
Что касается чисел, то правильнее писать
ADCSRA=(1<<ADEN)|(1<<ADIE)|(1<<ADSC);
Из этой записи сразу понятно, что она делает. В отличие от "магических чисел"

Не стесняйтесь писать подробные комментарии в программе... это сильно облегчает жизнь!))

С этим согласен

Re: Не корректно работает передача Slave-to-Master по SPI

Пт окт 19, 2018 20:27:45

Alkul писал(а):С этим согласен
я бы тоже согласился, да боюсь, у товарища коментарии в программе из следующего разряда
Код:
а = b * c; // вычисляем произведение b и с и запоминаем его в а
за такие комментарии надо коленями на горох в угол ставить :)))

Re: Не корректно работает передача Slave-to-Master по SPI

Пт окт 19, 2018 21:08:35

ARV, на счет засиранием комментами я с тобой полностью согласен.
Но ты еще не видел корабельников_стайл , там в обязательном порядке надо было комментировать каждую строчку на асме.
Причем это было просто описание команды , а не алгоритма.
Ответить