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

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Пт июн 09, 2023 14:54:10

Дайте ориг. код откуда взяли пример для:
Код:
dFi.w = F*167.77216; //частота передаваемая через SPI, какое-то фиксированное число 167.77216
PORTB &= ~_BV(PB0);
SPI_MasterTransmit(Cnt & 0x03);//0x03-маска
SPI_MasterTransmit(dFi.b[0]);//флаги передачи
SPI_MasterTransmit(dFi.b[1]);//флаги передачи
SPI_MasterTransmit(dFi.b[2]);//флаги передачи

Боюсь, что dFi.w не dFi.w, a &Fi.w (указатель, а [0], [1] ... - индекс для ячейки для double переменных.
Иначе я без побитового сдвига понятия не имею, как можно получить частоту в 3 байта, тем более со десет. знаком (F*167.77216).
А и какой double, в Вашем компиляторе для этого МК вероятно double -> float (32 bit).
Портировать код с другого МК на этот?
Последний раз редактировалось veso74 Пт июн 09, 2023 15:03:36, всего редактировалось 4 раз(а).

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Пт июн 09, 2023 15:01:25

Начал менять настройки мастера, изменил прескейлер в регистре SPI SPCR с 16 до 128, при частоте CK - 7813 Гц и заработал 3 кейс.MOHCTEP был прав, осталось разобраться с как настроить частоту, чтобы работали все 4 кейса USI_OVERFLOW. Но пока что ка как бы я не настраивал частоту мастера, 4 кейс оживить не удается.

Добавлено after 2 minutes 33 seconds:
veso74, это прошивка с рабочего прибора, прошивка с слейва не сохранилась и сгорела в результате КЗ.
Скинул архив, иницилизация SPI в USART.c. Слейв в данной ситуации выступает как регулируемый генератор меандра.
Вложения
KD8105.rar
(511.15 KiB) Скачиваний: 23

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Пт июн 09, 2023 15:41:54

warptred12, Попробуйте такой вариант сброса reqID.
Код:
switch(reqID) {
   ...
   ...
   case 3:
      dFi.b[2] = USIDR;
      USISR = 1<<USIOIF;  // Clear Overflow bit
      reqID++;   // !!
      flag_RT = 1;
   break;
    }
    reqID %=4;
    ...

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Пт июн 09, 2023 15:58:21

После некоторых изменений, таких как перенос из for функции инициилизации USI и изменения прескейлера частоты тактирующего сигнала мастера, МК в протеусе начал реагировать на измения номера ножки и частоты со стороны мастера. Теперь 1 байт(номер ножки, отправляемый со стороны мастера) определяется корректно и на заданной ножке генерируется частота, но частота не соответствует заданной и форма генерируемой частоты далека от меандра.
Я думаю, что это связано с тем что кейс 3 по прежнему не работает, также пробовал подавать 2-х байтные и 1-байтные числа по SPI со стороны мастера и все равно частота на выходе МК ATtiny2313 не корректна.
На данный момент присутствует 3 основные проблемы:
1) Неверная частота на выходе МК.
2) Неверная форма сигнала, должен быть меандр.
3) Хоть и частота генерируется на верной ножке, почему-то МК подает +5В на другие ножки, которые задействованы как выводы частоты nG, а этого быть не должно.
Вот актуальный код слейва:


Добавлено after 4 minutes 15 seconds:
MOHCTEP, этот вариант сброса не помогает, просто появляется +5В на ножках PB0 и PB1.

Добавлено after 5 minutes 5 seconds:
Вот форма генерируемого сигнала.
Вложения
Безымянный4.pdf
(601.27 KiB) Скачиваний: 29

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Пт июн 09, 2023 16:11:48

VFG_DDR тоже настройте один раз, при инициализации. Тогда set_out_pin (nG); будет не нужна. Вместо ее вызова, в бесконечном цикле достаточно будет строки nG=1<<ch_num;

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Пт июн 09, 2023 16:27:12

MOHCTEP, тогда при nG = 0 на мастере(0x00000000), частота генерируется на ножках PB0 и PB1.

Добавлено after 3 minutes 50 seconds:
При nG = 1(0x00000001), частота генерируется на ножке PB1, при nG = 2(0x00000002), частота генерируется на ножке PB2.
Вложения
Безымянный5.pdf
(620.77 KiB) Скачиваний: 23

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Пт июн 09, 2023 16:38:04

nG никогда не должно быть == 0. При ch_num ==0, nG ==1.
Код:
void main(void)
{
 static unsigned int fG_old = 0;
 unsigned long int tmp;
 Tim1Init();
 UpdateTim1A(fG);
 SpiSlaveInit();
 //DDRA=0b11111111;
 DDRB=0b11111111;
 DDRD=0b11110111;
#asm("sei")
for(;;) {
//delay_ms(1);


PORTD &= (~((1<<0)|(1<<1)|(1<<2)|(1<<4)|(1<<5)|(1<<6)));
//PORTB &= (~(1<<3)|(1<<4)|(1<<6));
//PORTA &= (~(1<<0)|(1<<1));

    if (fG_old != fG) {             //old value detction
        SetUpTim1A(fG);
        fG_old = fG;
    }
 
    nG=1<<ch_num;  //generator number                                         
    fG = dFi.b[1] << 8;
    tmp = dFi.b[2] << 16;
    fG |= tmp;
    tmp = dFi.b[2] << 24;
    fG |= tmp;   //generator frequency                   
    //set_out_pin (nG);
    SetUpTim1A(fG);
}
}
Как-то так...

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Пт июн 09, 2023 17:11:00

typedef union
{
unsigned long int w ; // w as WORD
unsigned int h[2]; // h as HALF-WORD
unsigned char b[4]; // b as BYTE
} Union32;
Union32 dFi;

объединение - каждый элемент (w,h,b) начинается с одной и тойже ячейки памяти,
т.е. dFi.b[0] - это младший байт из dFi.w


dFi.w = F*167.77216; - здесь неявное преобразование float->long int
(как компилятор это делает я не знаю, допустимо ли выбрасывать старший байт)

в передаче:
SPI_MasterTransmit(Cnt & 0x03); //1-й байт
SPI_MasterTransmit(dFi.b[0]); //2-байт - младший из dFi.w
SPI_MasterTransmit(dFi.b[1]); //3-байт - второй из dFi.w
SPI_MasterTransmit(dFi.b[2]); //4-байт - третий из dFi.w,
четвертый из dFi.w - проигнорирован, не передается,
т.е. целостность unsigned long int w нарушается

при приеме:
ch_num = USIDR;
dFi.b[1] = USIDR; - младший из dFi.w
dFi.b[2] = USIDR; - второй из dFi.w
dFi.b[3] = USIDR; - третий из dFi.w

fG = dFi.b[1] << 8;
tmp = dFi.b[2] << 16;
fG |= tmp;
tmp = dFi.b[2] << 24;
fG |= tmp;

т.е. в fG <b[1]><b[1]><b[0]>< 00 > (здесь b[] - из dFi.w передатчика)
а в dFi.w <b[3]><b[2]><b[1]><b[0]>

Добавлено after 11 minutes 45 seconds:
а между тем, если б передавать 5 байт (номер, float)
результат вычисления переправлялся бы целёхоньким
dFi.f = F*167.77216; - без преобразования типа

typedef union
{
float f;
unsigned long int w ; // w as WORD
unsigned int h[2]; // h as HALF-WORD
unsigned char b[4]; // b as BYTE
} Union32;

SPI_MasterTransmit(Cnt & 0x03); //1-й байт
SPI_MasterTransmit(dFi.b[0]); //2-байт - младший из dFi.f
SPI_MasterTransmit(dFi.b[1]); //3-байт - второй из dFi.f
SPI_MasterTransmit(dFi.b[2]); //4-байт - третий из dFi.f
SPI_MasterTransmit(dFi.b[3]); //5-байт - четвертый из dFi.f

и ничего не надо ручками склеивать в приемнике dFi.f = dFi.f передатчика, он же fG

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Пт июн 09, 2023 17:14:39

...
dFi.w = F*167.77216; - здесь неявное преобразование float->long int
...

Код:
dFi.w = (unsigned long int)((float)F * 167.77216);

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

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Пт июн 09, 2023 17:31:21

a797945, а вот как этот 3 байт ловить не понятно, в прерывании программа не доходит до case 3. Вероятно отправляются 4 байта вместо 5 - для экономии памяти attiny.
Частота SCK задана минимальной на мастере(прескейлер 128/7813Гц). Не понимаю как мне подогнать Attiny под частоту тактирования мастера.

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Пт июн 09, 2023 19:17:45

я не специалист, и тем паче не специалист по avr,
мне сложно Вам что-то советовать связанное со структурой МК или его перефирией.
если Вы предполагаете нехватку ресурсов на слейве, попробуйте
(для эксперимента) отправлять на слейв фиксированные "частоты", идея в том чтоб наладить передачу и генерацию, а математику со слейва пока убрать
эту:
for(i=0;i<=4;i++) {
TimDiv = (F_CPU/(2*(Foc/167.77216)*N[i])-1)+0.5;
if(TimDiv >= 0 && TimDiv<VFG_TIMER_MAX){
ClockSelect=i+1;
break;
}
}
т.е. посчитать несколько значений для таймера(ов) слейва, мастером эти значения (через паузу или по кнопке) отсылать на слейв, там принимать и без математики просто записывать в таймер(а).

Вы все еще в протеусе или пробовали на "железе"?

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Пт июн 09, 2023 19:20:45

a797945, ну ток с понедельника смогу в железе посмотреть, а пока в протеусе смотрю. Попробую этот вариант, отпишусь как будут результаты.

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Пт июн 09, 2023 19:25:51

если задача не решается - всегда приходится разбивать ее на части, местами на небольшие - и отлаживать по частям

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Вт июл 04, 2023 16:20:49

Проблема довольно сильно затянулась и до сих пор не удалось отладить в железе прошивку на attiny2313, так что я решил параллельно заниматься написанием прошивки на контроллер с полноценной поддержкой SPI ATMEGA8.
Код слейва:

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

Добавлено after 38 minutes 21 second:
Теперь работает только PC0 и на нем частота 32 Гц, хотя ничего не менял в коде.

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Вт июл 04, 2023 17:39:02

Непонятна суть цикла
Код:
for (i = 0; i < sizeof(master_arr); i++) {
    nG = master_arr[i]; //generator number
    fG = master_arr[i] << 8;
    tmp = master_arr[i] << 16;
    fG |= tmp;
    tmp = master_arr[i] << 24;
    fG |= tmp;     
    //generator frequency                   
    UpdateTim1A(fG);
    SetUpTim1A(fG);
    }         
Здесь вы всегда манипулируете последним байтом массива master_arr, назначая его обеим переменным nG и fG.

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Вт июл 04, 2023 17:51:48

MOHCTEP, первый полученный байт по SPI, я присваиваю значению массива master_arr[0], а это значение присваиваю переменной nG(номер выхода генератора), master_arr[1],master_arr[2],master_arr[3] я пытаюсь присвоить переменной fG(частота генератора, подставляемая в формулу расчета регистра OCR1A).
Идея такова, что каждое прерывание я записываю по байту информации в массив master_arr[i], а в основном цикле я пытаюсь присвоить эти значения переменным nG и fG. Ну такова была идея по крайней мере.

Добавлено after 3 minutes 21 second:
Функция for (i = 0; i < sizeof(master_arr); i++) нужна для того чтобы подставить эти значения в правильном порядке, но опят таки я не уверен что это работает правильно.

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Вт июл 04, 2023 18:05:06

Нет. Вы циклом всегда присваиваете каждый байт массива, по очереди, обеим переменным сразу. В итоге, после отработки этого странного цикла, обеим переменным будет присвоен последний байт массива.
Уберите этот цикл и модифицируйте переменные обращаясь к массиву по числовым индексам master_arr[0],master_arr[1]... и master_arr[3](четвертый байт) вам недоступен, так как длина массивов у вас = 3 байтам.

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Вт июл 04, 2023 18:44:17

MOHCTEP, я увеличил массив до 4, потому что по SPI передается 4 байта, так будет верно ?


Добавлено after 20 minutes 58 seconds:
Ну результат все тот же, в принципе.

Добавлено after 8 minutes 53 seconds:
Вопрос в том как это починить, чтобы оно работало или лучше писать заново.

Добавлено after 4 minutes 54 seconds:
Если что пример кода для реализации SPI slave'a брал тут: https://dzen.ru/media/esp32/spi-arduino ... adboard.ru

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Вт июл 04, 2023 19:54:15

Ну... сложно что то умное подсказать на расстоянии, да еще и для протеуса. В качестве версии: проблема возможна в том, что вы постоянно перестраиваете переменные nG и fG в главном цикле и вместе с ними таймер. Независимо от того - пришло там что-то по SPI или нет. Возможно ваш таймер, от постоянных перенастроек, просто не успевает нормально отрабатывать цикл. Вот у вас есть счетчик заполнения массива countSPIb. Можно, к примеру, в майн цикле проверять его на равенство длине массива (это значит, что пришли все 5 байт от мастера и данные подготовлены) и только в этом случае пересчитать переменные + таймер и сбросить счетчик countSPIb, подготовившись к следующему приему.
Как-то так примерно...
Код:
interrupt [SPI_STC] void spi_isr(void)              // Прерывание SPI1 - пришел байт
{
  if (countSPIb < 0) {                              // пришла "пустышка"
    countSPIb++;                                    // увеличивам счетчик
    SPDR = slave_arr [countSPIb];                   // подгружаем нулевой байт массива ведомого
    PORTC |= (1<<0);
    return;                                         // выходим из процедуры
  }

  master_arr [countSPIb] = SPDR1;                   // получаем байт от мастера
  countSPIb++;                                      // увеличиваем счетчик
  SPDR = slave_arr [countSPIb];                     // отдаем байт ведомого (+1 индекс)
  PORTC |= (1<<1);

  if (countSPIb >= sizeof(master_arr)) {            // если кончился массив
    PORTC |= (1<<2);
    //countSPIb = -1;                                 // обнуляем счетчик и ждем следующий обмен
  }
}
...

void main(void){
   ...
   for(;;){
      ...
      if (countSPIb >= sizeof(master_arr)){
         nG = master_arr[0];                         //generator number
         fG = (master_arr[1] << 8)|(master_arr[2] << 16)|(master_arr[3] << 24);
         UpdateTim1A(fG);
         SetUpTim1A(fG);
         countSPIb = -1;
      }
   }
}   

Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313

Ср июл 05, 2023 12:28:06

MOHCTEP, в протеусе мастер отправляет верные данные, в хексадермальном формате 02 5C 8F 02(первый байт номер генератора, остальные 3 значения частоты), а вот в ответ мастеру - слейв шлет 00 01 01 01 в ответ, это значит, что по какой-то причине, байты, полученные от мастера записываются в единицы. Если я правильно понимаю, как работает SPI, то при получении байта, слейв отправляет полученный байт мастеру, в неизмененном виде, а у меня не так получается. Это значит что скорее всего код в прерывании криво написан, но пока конкретно не ясно, что там не так.

Добавлено after 7 minutes 56 seconds:
А для хранения значения переменной fg, у меня есть такая функция, которая сравнивает старое и новое значение и не изменилось ли значение fG


Добавлено after 4 minutes 34 seconds:
Еще может быть проблема в том, чт переменная fG - 32-х битная(unsigned long int), а мы записываем в нее 24 бита. Но я даже не знаю как это проверить, просто предположение.
Ответить