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

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

Ср июл 05, 2023 12:31:46

Ну, у вас слейв отправляет неведомо что из массива slave_arr. Я не увидел в коде, где этот массив модифицируется, перед отправкой.
Код:
master_arr [countSPIb] = SPDR1;                   // получаем байт от мастера
SPDR = master_arr [countSPIb];                     // отдаем байт обратно
  countSPIb++;                                      // увеличиваем счетчик
  //SPDR = slave_arr [countSPIb];                     // отдаем байт ведомого (+1 индекс)
  PORTC |= (1<<1);
Попробуйте так...

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

Ср июл 05, 2023 12:52:51

MOHCTEP, теперь обратно к мастеру отправляются 00 00 00 00. Ну и на выходе тот же результат, на PORTC0 32 Гц.
Так же ругается на эту строчку:
Спойлер
Код:
fG = (master_arr[1] << 8)|(master_arr[2] << 16)|(master_arr[3] << 24);

Пишет: Warning: overflow is possible in 16 bit shift left, casting shifted operand to 'long' may be required и shift result will be 0.

Добавлено after 10 minutes 58 seconds:
А массив нигде не модифицируется, кроме прерывания по SPI, а значения из массива просто присваиваются переменным nG и fG(номер выхода и частота).

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

Ср июл 05, 2023 12:53:07

А это похоже, что master_arr у вас нулями заполняется. Возможно оттого и частота не меняется.
warptred12 писал(а):Так же ругается на эту строчку:
Это я для краткости так написал, видимо не хватает разрядности fG. Если так, то в результате fG всегда = 0 будет. Переделайте эту строку на ваш предыдущий код с темповой переменной.

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

Ср июл 05, 2023 13:43:06

MOHCTEP, после изменения типа массивов с unsigned char на unsigned long int - эта ошибка исчезла.
Спойлер
Код:
// Массив корторый приходит от мастера
volatile unsigned long int master_arr [4];
// Массив который отдаем от мастеру
volatile unsigned long int slave_arr  [4];

Но теперь генерации частоты на выходе нет, а данные отправляемые к мастеру: 00 81 01 01.

Добавлено after 37 minutes 11 seconds:
Решил изменить код обработчика прерываний SPI полностью, вернувшись к чему-то попроще и это дало результаты. Теперь программа записывает в массив верные значения, но почему-то сдвигает их влево и в 0 байт массива записывает 01. Входные данные с мастера 02 5C 8F 02, данные отправленные обратно: 01 02 5C 0F. Генерации частоты на выходе по прежнему нет.
Вот измененный код:
Спойлер
Код:
#include <mega8.h>
#include <math.h>
#include <io.h>
#include <delay.h>

#define  F_CPU (8000000)
#define  VFG_TIMER_MAX (65535)
#define  VFG_DDR DDRD
#define  VFG_PORT PORTD

volatile unsigned long int fG;
unsigned char nG;
unsigned int N[]={1,8,64,256,1024};

// Массив корторый приходит от мастера
volatile unsigned long int master_arr [4];
// Массив который отдаем от мастеру
volatile unsigned long int slave_arr  [4];
// счетчик входящих байт
volatile int countSPIb = -1;

volatile char reqID = 0;

void setup (void)
{
    #asm("cli")
    // Настройка SPI как SLAVE
    DDRB |= (1 << PORTB4);                            // Настроить вывод MISO на выход
    SPCR |= (1 << SPIE) | (1 << SPE) | (0 << MSTR);   // Прерывание включено и сам SPI как SLAVE
    #asm("sei")
}

interrupt [SPI_STC] void spi_isr(void)              // Прерывание SPI1 - пришел байт
{
  switch(reqID) {
   case 0:
        master_arr[0] = SPDR;
        SPDR = master_arr [reqID];
        reqID++;
   break;
   case 1:
      master_arr[1] = SPDR;
        SPDR = master_arr [reqID];
      reqID++;
   break;
   case 2:
      master_arr[2] = SPDR;
        SPDR = master_arr [reqID];
        reqID++;
   break;
   case 3:
      master_arr[3] = SPDR;
        SPDR = master_arr [reqID];
        reqID = 0;
       countSPIb = -1;
    break;
    }
}
//***********************************************timer1************************************************

void Tim1Init(void)
{
    #asm("cli")
    TCCR1A = (1<<COM1A0);                           //toggle on compare
    TCCR1B = (1<<WGM12)|(1<<CS12)|(1<<CS10);        // set timer CTC mode, prescaler 1024
    TIMSK = (1<<OCIE1A);
    #asm("sei")
}

void SetUpTim1A(unsigned long int Foc)              //calculate value OCR1A register
{
    unsigned long int TimDiv;
    unsigned char ClockSelect=0;
    unsigned char i=0;
    for(i=0;i<=4;i++) {
        TimDiv = 1*((F_CPU/(Foc*N[i])-1));
        if(TimDiv >= 0 && TimDiv<VFG_TIMER_MAX){
        ClockSelect=i+1;
        break;
        }
    }
    #asm("cli")
    OCR1A=TimDiv;
    TCCR1B = (1<<WGM12) | (ClockSelect<<CS10);
    #asm("sei")   
}


void UpdateTim1A(unsigned long int freq)             //old value storage
{
    static unsigned long int fG_old = 0;
    if (fG_old != freq)
    {
        SetUpTim1A(freq);
        fG_old = freq;
    }
}

interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
    VFG_PORT = (VFG_PORT^nG)&(nG);   
}

void main(void)
{
 static unsigned long int fG_old = 0;
 VFG_DDR = 0b00000111;
 DDRC = 0b11111111;
 setup();
 Tim1Init();
 #asm
    in   r30,spsr
    in   r30,spdr
 #endasm

#asm("sei")
for(;;) {
    if(PINB.2==0) {countSPIb = -1;}             //сброс в случае глюка связи

    if (fG_old != fG) {                         //old value detction
        SetUpTim1A(fG);
        fG_old = fG;
    }

 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

Чт июл 06, 2023 01:08:48

Не ну...
1 При чем тут countSPIb в условии if (countSPIb >= sizeof(master_arr))... если в прерывании вы его вообще не трогаете, кроме 3-его кейса? У вас это условие никогда не отработает, как по вышеназванной причине, так и из-за сброса его в прерывании.
2 Зачем оно вообще нужно, если вы "завели" новый счетчик - reqID?
И на всяк случай - еще раз: чтобы все отработало хоть приблизительно правильно - счетчик в прерывании не сбрасывать!

Код:
interrupt [SPI_STC] void spi_isr(void)              // Прерывание SPI1 - пришел байт
{
  switch(reqID) {
   case 0:
        master_arr[0] = SPDR;
        SPDR = master_arr [reqID];
        reqID++;
   break;
   case 1:
      master_arr[1] = SPDR;
        SPDR = master_arr [reqID];
      reqID++;
   break;
   case 2:
      master_arr[2] = SPDR;
        SPDR = master_arr [reqID];
        reqID++;
   break;
   case 3:
      master_arr[3] = SPDR;
        SPDR = master_arr [reqID];
        reqID++;
        //reqID = 0;
       //countSPIb = -1;
    break;
    }
}
...
...
void main(void)
{
 ...
for(;;) {
    ...
 if (reqID>= 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);
         reqID= 0;
      }                     
    }         
}

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

Чт июл 06, 2023 11:43:39

MOHCTEP, с этими правками мастер шлет все верно 02 5C 8F 02(номер пина и частота в хексадермальном формате), а обратно слейв отсылает 81 00 00 00, пробовал светодиодами тестировать кейсы, как в прошлый раз с attiny - все кейсы работают. Генерации частоты ни на одном пине нет.
Код слефва:
Спойлер
Код:
#include <mega8.h>
#include <math.h>
#include <io.h>
#include <delay.h>

#define  F_CPU (8000000)
#define  VFG_TIMER_MAX (65535)
#define  VFG_DDR DDRD
#define  VFG_PORT PORTD

volatile unsigned long int fG;
unsigned char nG;
unsigned int N[]={1,8,64,256,1024};
//BYTE STORAGE
volatile unsigned long int master_arr [4];
//BYTE COUNTER
volatile int reqID = 0;

void setup (void)
{
    #asm("cli")
    DDRB |= (1 << PORTB4);                            //configure MISO as output
    SPCR |= (1 << SPIE) | (1 << SPE) | (0 << MSTR);   //configure slave mod and interrupt
    #asm("sei")
}

interrupt [SPI_STC] void spi_isr(void)     
{
switch(reqID) {
   case 0:
        master_arr[0] = SPDR;
        SPDR = master_arr [reqID];
        PORTC |= (1<<0);
        reqID++;
   break;
   case 1:
        master_arr[1] = SPDR;
        SPDR = master_arr [reqID];
        PORTC |= (1<<1);
        reqID++;
   break;
   case 2:
        master_arr[2] = SPDR;
        SPDR = master_arr [reqID];
        PORTC |= (1<<2);
        reqID++;
   break;
   case 3:
        master_arr[3] = SPDR;
        SPDR = master_arr [reqID];
        reqID++;
    break;
    }
}
//***********************************************timer1************************************************

void Tim1Init(void)
{
    #asm("cli")
    TCCR1A = (1<<COM1A0);                           //toggle on compare
    TCCR1B = (1<<WGM12)|(1<<CS12)|(1<<CS10);        // set timer CTC mode, prescaler 1024
    TIMSK = (1<<OCIE1A);
    #asm("sei")
}

void SetUpTim1A(unsigned long int Foc)              //calculate value OCR1A register
{
    unsigned long int TimDiv;
    unsigned char ClockSelect=0;
    unsigned char i=0;
    for(i=0;i<=4;i++) {
        TimDiv = 1*((F_CPU/(Foc*N[i])-1));
        if(TimDiv >= 0 && TimDiv<VFG_TIMER_MAX){
        ClockSelect=i+1;
        break;
        }
    }
    #asm("cli")
    OCR1A=TimDiv;
    TCCR1B = (1<<WGM12) | (ClockSelect<<CS10);
    #asm("sei")   
}

void UpdateTim1A(unsigned long int freq)             //old value storage
{
    static unsigned long int fG_old = 0;
    if (fG_old != freq)
    {
        SetUpTim1A(freq);
        fG_old = freq;
    }
}

interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
    VFG_PORT = (VFG_PORT^nG)&(nG);   
}

void main(void)
{
static unsigned long int fG_old = 0;
VFG_DDR = 0b00000111;
DDRC = 0b11111111;
setup();
Tim1Init();
 
#asm("sei")
for(;;) {

    if (fG_old != fG) { //old value detction
        SetUpTim1A(fG);
        fG_old = fG;
    }

    if (reqID>= sizeof(master_arr)){
        nG = master_arr[0]; //generator number
        fG = (master_arr[1] << 8)|(master_arr[2] << 16)|(master_arr[3] << 24); //generator freqency
        UpdateTim1A(fG);
        SetUpTim1A(fG);
        reqID= 0;               
    }         
}
}

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

Чт июл 06, 2023 13:26:54

Уберите светодиоды из прерывания и попробуйте их тут, чтобы понять, этот участок кода вообще работает?
Код:
if (reqID>= sizeof(master_arr)){
        PORTC |= (1<<0);
        nG = master_arr[0]; //generator number
        fG = (master_arr[1] << 8)|(master_arr[2] << 16)|(master_arr[3] << 24); //generator freqency
        UpdateTim1A(fG);
        SetUpTim1A(fG);
        reqID= 0;
        _delay_ms(500);
        PORTC &= ~(1<<0);
    }     

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

Чт июл 06, 2023 13:28:42

MOHCTEP, не работает.

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

Чт июл 06, 2023 14:26:06

Ну вот и проблема. Опять с 3 кейсом наверное? reqID просто не "добирает" до 4.

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

Чт июл 06, 2023 14:44:08

MOHCTEP, нет, все 4 кейса работают, не работает именно if (reqID>= sizeof(master_arr)).

Добавлено after 4 minutes 50 seconds:
В прерывании я включаю порты PC0-PC3 PORTC |= (1<<x);, в оснвном цикле for(;;) - я их выключаю PORTC &= ~(1<<x);.
Значит ли это, что прерывания не работают или это значит, что прерывание срабатывает лишь раз ?

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

Чт июл 06, 2023 14:56:25

Обсуждалось в другой теме. Использование sizeof для определения размера массивов дает неправильный результат, поскольку параметры массива рассматриваются как указатели. Попробуйте:
Код:
if (reqID >= sizeof(arr) / sizeof(arr[0])) ...

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

Чт июл 06, 2023 15:05:11

Кстати veso74 прав. У вас же массив сейчас 16 байт весит...
только еще скобку добавьте
Код:
if (reqID >= (sizeof(arr) / sizeof(arr[0]))) ...
Последний раз редактировалось MOHCTEP Чт июл 06, 2023 15:08:57, всего редактировалось 2 раз(а).

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

Чт июл 06, 2023 15:10:10

veso74, ругается expression expected.

Добавлено after 3 minutes 36 seconds:
MOHCTEP, все равно ругается expression expected.
Спойлер
Код:
for(;;) {

    if (fG_old != fG) { //old value detction
        SetUpTim1A(fG);
        fG_old = fG;
    }
        PORTC &= ~(1<<0);
        PORTC &= ~(1<<1);
        PORTC &= ~(1<<2);
        PORTC &= ~(1<<3);
   if (reqID >= (sizeof(arr) / sizeof(arr[0]))){
        nG = master_arr[0]; //generator number
        fG = (master_arr[1] << 8)|(master_arr[2] << 16)|(master_arr[3] << 24); //generator freqency
        UpdateTim1A(fG);
        SetUpTim1A(fG);
        delay_ms(1);

        PORTC &= ~(1<<4);
        reqID= 0;
                       
    }         
}
Последний раз редактировалось warptred12 Чт июл 06, 2023 15:11:28, всего редактировалось 1 раз.

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

Чт июл 06, 2023 15:11:03

MOHCTEP, скобки не необходими :) :
Код:
C Operator Precedence:
...
3 : /
...
6 : >=
...

---
warptred12, компилятор какой? На два попробовал, ОК.
Последний раз редактировалось veso74 Чт июл 06, 2023 15:20:05, всего редактировалось 2 раз(а).

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

Чт июл 06, 2023 15:19:49

Именно компилятор пишет красным на эту строку: if (reqID >= (sizeof(arr) / sizeof(arr[0]))) - expression expected.

Добавлено after 1 minute 35 seconds:
А я понял, я не свой массив там написал. У моего массива другое имя.

Добавлено after 3 minutes 14 seconds:
veso74, теперь функция if (reqID >= (sizeof(master_arr) / sizeof(master_arr[0]))) - работает, загорается светодиод, как и все остальные кейсы. Но данные по прежнему идут неверные - 81 00 00 00(слейв почему-то это записывает, вместо 02 5C 8F 02). Ну и соответственно изза этого и генерации частоты нет никакой.

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

Чт июл 06, 2023 15:24:16

Для этого следуйте логике вашего примера. Если так сложно (карандаш и лист бумаги!), разбейте примерно на части и напр. распечатайте промежуточные результаты, или делайте реакцией к LED? ...

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

Чт июл 06, 2023 15:31:05

veso74, слейв постоянно отправляет в ответ на принятые данные 81 00 00 00 и такой результат был до изменения функции if (reqID >= (sizeof(arr) / sizeof(arr[0]))). Это значит, что где-то в коде полученные данные кораптятся или теряются и в итоге получаются неверные значения.

Добавлено after 57 seconds:
Даже в том случае, когда я меняю, отправляемые входные данные с мастера.

Добавлено after 1 minute 32 seconds:
Я пробовал комментировать функции расчета регистр таймера, хранения переменной и результат все равно все тот же.

Добавлено after 57 seconds:
Что-то не так конкретно в прерывании, где мы принимаем байты или в основной функции, где мы их подставляем в переменные fG и nG. Но как уже выяснилось: кейсы работают, функия if - тоже работает.
Последний раз редактировалось warptred12 Чт июл 06, 2023 15:34:04, всего редактировалось 1 раз.

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

Чт июл 06, 2023 15:31:53

warptred12, А частота меняется?

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

Чт июл 06, 2023 15:44:10

MOHCTEP, ее нет на выходе, потому что первый полученный байт от мастера 81 - он должен подставляется в переменную nG и уже в прерывании таймера 1 эта переменная обрабатывается и на основании ее значения выбирается ножка, значение 81 - некорректно, поэтому и нет генерации ни на одной ноге.

Добавлено after 56 seconds:
Неверно выразился, первый прочитанный байт.

Добавлено after 6 minutes 8 seconds:
Да и вот код актуальный на данный момент:
Спойлер
Код:
#include <mega8.h>
#include <math.h>
#include <io.h>
#include <delay.h>

#define  F_CPU (8000000)
#define  VFG_TIMER_MAX (65535)
#define  VFG_DDR DDRD
#define  VFG_PORT PORTD

volatile unsigned long int fG;
unsigned char nG;
unsigned int N[]={1,8,64,256,1024};
//BYTE STORAGE
volatile unsigned long int master_arr [4];
//BYTE COUNTER
volatile int reqID = 0;

void setup (void)
{
    #asm("cli")
    DDRB |= (1 << PORTB4);                            //configure MISO as output
    SPCR |= (1 << SPIE) | (1 << SPE) | (0 << MSTR);   //configure slave mod and interrupt
    #asm
in r30,spsr
in r30,spdr
    #endasm
    #asm("sei")
}

interrupt [SPI_STC] void spi_isr(void)     
{
switch(reqID) {
   case 0:
        master_arr[0] = SPDR;
        SPDR = master_arr [reqID];
        PORTC |= (1<<0);
        reqID++;
   break;
   case 1:
        master_arr[1] = SPDR;
        SPDR = master_arr [reqID];
        PORTC |= (1<<1);
        reqID++;
   break;
   case 2:
        master_arr[2] = SPDR;
        SPDR = master_arr [reqID];
        PORTC |= (1<<2);
        reqID++;
   break;
   case 3:
        master_arr[3] = SPDR;
        SPDR = master_arr [reqID];
        PORTC |= (1<<3);
        reqID++;
    break;
    }
}
//***********************************************timer1************************************************

void Tim1Init(void)
{
    #asm("cli")
    TCCR1A = (1<<COM1A0);                           //toggle on compare
    TCCR1B = (1<<WGM12)|(1<<CS12)|(1<<CS10);        // set timer CTC mode, prescaler 1024
    TIMSK = (1<<OCIE1A);
    #asm("sei")
}

void SetUpTim1A(unsigned long int Foc)              //calculate value OCR1A register
{
    unsigned long int TimDiv;
    unsigned char ClockSelect=0;
    unsigned char i=0;
    for(i=0;i<=4;i++) {
        TimDiv = 1*((F_CPU/(Foc*N[i])-1));
        if(TimDiv >= 0 && TimDiv<VFG_TIMER_MAX){
        ClockSelect=i+1;
        break;
        }
    }
    #asm("cli")
    OCR1A=TimDiv;
    TCCR1B = (1<<WGM12) | (ClockSelect<<CS10);
    #asm("sei")   
}

void UpdateTim1A(unsigned long int freq)             //old value storage
{
    static unsigned long int fG_old = 0;
    if (fG_old != freq)
    {
        SetUpTim1A(freq);
        fG_old = freq;
    }
}

interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
    VFG_PORT = (VFG_PORT^nG)&(nG);   
}

void main(void)
{
static unsigned long int fG_old = 0;
VFG_DDR = 0b00000111;
DDRC = 0b11111111;
setup();
Tim1Init();
    #asm
in r30,spsr
in r30,spdr
    #endasm
#asm("sei")
for(;;) {

    if (fG_old != fG) { //old value detction
        SetUpTim1A(fG);
        fG_old = fG;
    }
        PORTC &= ~(1<<0);
        PORTC &= ~(1<<1);
        PORTC &= ~(1<<2);
        PORTC &= ~(1<<3);
   if (reqID >= (sizeof(master_arr) / sizeof(master_arr[0])/ sizeof(master_arr[1])/ sizeof(master_arr[2])/ sizeof(master_arr[3])))
   {
        nG = master_arr[0]; //generator number
        fG = (master_arr[1] << 8)|(master_arr[2] << 16)|(master_arr[3] << 24); //generator freqency
        UpdateTim1A(fG);
        SetUpTim1A(fG);
        delay_ms(1);

        PORTC &= ~(1<<4);
        reqID= 0;
                       
    }         
}
}

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

Чт июл 06, 2023 15:47:52

Код:
if (reqID >= (sizeof(master_arr) / sizeof(master_arr[0])/ sizeof(master_arr[1])/ sizeof(master_arr[2])/ sizeof(master_arr[3]))

А что это?
Ответить