Страница 5 из 7
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 15:51:28
warptred12
Так стоп, я соврал, я ошибся и мне показалось что светодиодик с ножки PCINT4 - горит, но это не так.
Получается функция if (reqID >= (sizeof(master_arr) / sizeof(master_arr[0]))) по прежнему не работает.
Добавлено after 46 seconds:
veso74, это я уже заметил и исправил, результат тот же.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 15:58:53
veso74
Повторю вопрос: компилятор и IDE какой?
(Проверял на два прежде чем привел пример здесь).
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 16:02:53
warptred12
veso74, CodeVisionAvr версии 2.05.0, а компилятор gcc по идее, не нашел в кодевижне, где это написано.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 16:04:46
veso74
не знаю логики построения, но
Код: Выделить всё
fG = (master_arr[1] << 8)|(master_arr[2] << 16)|(master_arr[3] << 24); //generator freqency
случайно не
Код: Выделить всё
fG = (master_arr[1])|(master_arr[2] << 8)|(master_arr[3] << 16); //generator freqency
? Что первые 8 бит "пустые" мне кажутся странными.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 16:08:21
warptred12
veso74, fg - 4-х байтная переменная, но подставляем в нее только 3 последних значения master_arr[]. 0 значение массива мы подставляем в переменную nG.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 16:15:46
veso74
А что у младших 8 бита fg?
Если они нулевые, установите их явно.
А так сначала нет неустановленного значения fg, затем дополняете 3 по 8 бит ...
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 16:20:37
warptred12
veso74, fG = 0|(master_arr[1] <<

|(master_arr[2] << 16)|(master_arr[3] << 24); //generator freqency. Так?
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 16:22:58
veso74
грубо: да (а может быть, и еше "красивее"

). Ничего, так и быть.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 18:13:49
warptred12
Осталось теперь разобраться почему это не работает: if (reqID >= (sizeof(master_arr) / sizeof(master_arr[0]))).
Добавлено after 1 hour 6 minutes 58 seconds:
Поковырявшись в протеусе увидел, что все это время он ругался: Data is overrun - received data is lost. Это значит, что слейв не успевает записывать данные за мастером. Снизил частоту SCK, проблема осталась, но в SPI анализаторе - увидел, что стал записываться 2 байт массива master_arr, хоть и неверно. Значит нужно как-то синхронизировать 2 контроллера.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 19:13:26
a797945
"Это значит, что слейв не успевает записывать данные за мастером..."
НЕТ. это означает, что у вас нет намерения забирать данные вовремя.
но с этим вам пока рано.
расскажите, лучше, это означает:
volatile unsigned long int master_arr [4];
а теперь, что означает вот это:
master_arr[0] = SPDR;
а какой разрядности SPDR? напишите что будет в master_arr[0], если SPDR=01, только напишите все разряды.
пишете:
UpdateTim1A(fG);
SetUpTim1A(fG);
а ничего, что второе уже есть в первом? и такой вызов лишает смысла UpdateTim1A(fG)
а ничего, что вы умножаете частоту в 2^8 раз :
fG = (master_arr[1] << 8 )|(master_arr[2] << 16)|(master_arr[3] << 24);
т.е. делая из нее просто мусор.
предлагал ведь решать задачу по-этапно, но не - все в кучу, ошибка наслаивается на ошибку, а воз и ныне там.
я понимаю "лень - двигатель процесса", но иногда лень - это тот рог которым, упрутся в пень и ни с места.
пишите слейв с нуля, не копипастом, ручками; пытайтесь понимать зачем оно так, а не иначе.
в слейве сделайте прием 4-х байт, потом отсылку этих байт назад. и все никаких таймеров.
в мастере сделайте отсылку 4-х байт, следом байта "пустышку", и прием 4-х байт от слейва, дальше пауза и снова. когда получится - поймете зачем пустышка, без нее можно, но щас пока так.
не будете пытаться понять, что пишите - вы безнадежны, так что включайте голову. удачи.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 19:30:34
warptred12
a797945, volatile unsigned long int master_arr [4] - это массив для хранения принятых байт.
master_arr[0] = SPDR - я присваиваю 0 элементу массива значение, хранящееся в 8-битном регистре данных.
а ничего, что второе уже есть в первом? и такой вызов лишает смысла UpdateTim1A(fG) - что значит второе уже есть в первом ? Функция UpdateTim1A(fG) нужна для хранения значения fG, для того чтобы высчитывать ее только при изменении входных значений.
fG = (master_arr[1] << 8 )|(master_arr[2] << 16)|(master_arr[3] << 24) - в этой строке побитовым сдвигом подставляются элементы массива, это сделано так, потому что полученные данные по SPI - 3 байтовые, а в стандарте си нет 3-х байтовых типов данных. Поэтому я подставляю в 4-х байтовый unsigned long int побитовым сдвигом эти 3 байта.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 19:41:46
a797945
увы, вы не поняли ни одного моего слова. пробую последнюю попытку:
1.напишите ПОБИТНО содержание ячейки master_arr[0] (с любым значением, но все разряды)
2.напишите значение fg, если master_arr[1]=01 master_arr[2]=02 master_arr[3]=03, при такой сборке:
fG = (master_arr[1] << 8 )|(master_arr[2] << 16)|(master_arr[3] << 24)
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 19:54:28
warptred12
a797945, 1. 00000000
2. У меня другое равенство fG = 0|(master_arr[1] << 8 )|(master_arr[2] << 16)|(master_arr[3] << 24)
00 01 02 03- значение fG
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 20:01:07
a797945
1. нет, например 3 будет:
00000000000000000000000000000011
long int - однако.
2. нет, будет
0x03020100
младший байт = 0
(master_arr[1] << 8 ) - взять из ячейки [1] 4 байта (там ведь у вас long int), сдвинуть их содержимое влево (на увеличение), ....
понимаете?
первый байт вы уже проскачили - ничего туда не положили, там остались 00
так я и говорю - не торопитесь, пытайтесь осмысливать.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 20:06:58
warptred12
a797945, да вы правы, глупая ошибка.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Пт июл 07, 2023 09:37:16
warptred12
Подправил код, добавил в прерывание проверку 1-го входящего байта, добавил еще 1 счётчик flagRT, чтобы попытаться соблюсти в точности последовательность входящих байт, изменил формулу расчёта fG, но все равно слейв считывает мусор. Вот измененный код:
Спойлер
Код: Выделить всё
#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;
volatile unsigned char nG;
unsigned int N[]={1,8,64,256,1024};
//BYTE STORAGE
volatile unsigned char master_arr [4];
//BYTE COUNTER
volatile int reqID = 0;
volatile int flagRT = 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:
if (SPDR == 0b00000001 || SPDR == 0b00000010 || SPDR == 0b00000011) {
master_arr[0] = SPDR;
SPDR = master_arr [0];
PORTC |= (1<<0);
reqID++;
flagRT++;
break;
}
case 1:
if (flagRT = 1) {
master_arr[1] = SPDR;
SPDR = master_arr [1];
PORTC |= (1<<1);
reqID++;
flagRT++;
break;
}
case 2:
if (flagRT = 2) {
master_arr[2] = SPDR;
SPDR = master_arr [2];
PORTC |= (1<<2);
reqID++;
break;
}
case 3:
if (flagRT = 3) {
master_arr[3] = SPDR;
SPDR = master_arr [3];
PORTC |= (1<<3);
reqID++;
flagRT = 0;
break;
}
}
}
//***********************************************timer1************************************************
void main(void)
{
VFG_DDR = 0b00000111;
DDRC = 0b11111111;
setup();
#asm("sei")
for(;;) {
PORTC &= ~(1<<0);
PORTC &= ~(1<<1);
PORTC &= ~(1<<2);
PORTC &= ~(1<<3);
if (reqID >= (sizeof(master_arr) / sizeof(master_arr[0])))
{
if (flagRT == 1) {nG = master_arr[0];} //generator number
fG = 0|(master_arr[1] >> 8)|(master_arr[2] >> 16)|(master_arr[3] >> 24); //generator freqency
delay_ms(1);
PORTC &= ~(1<<4);
reqID= 0;
}
}
}
Добавлено after 21 minute 4 seconds:
Причем мусор пишет всегда в 0 байт, остальные иногда проскакивают и совпадают с реальными значениями.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Пт июл 07, 2023 09:37:16
veso74
Мне кажется, что с побитовыми операциями у вас пробел

. (Надеюсь, я ошибаюсь).
Бумага и карандаш в помощь!
Это невозможно (и неправильно):
Код: Выделить всё
volatile unsigned char master_arr [4];
...
... (master_arr[2] >> 16)|(master_arr[3] >> 24);
привожу пример:
master_arr[3] = 123 (случайное значение) = 0x7B = 0b01111011. Переместите 24 раза вправо и посмотрите, что произойдет?
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Пт июл 07, 2023 09:59:14
a797945
в помощь вам. давайте порасуждаем
сочиняем прошивку для слейва, подошли к разрешению прерываний, стоп, а какие нас тут ждут грабли
г1 флаг уже взведен,
г2 а мы не знаем, что сейчас делает мастер.
мусор же мы принимать не хотим, вместо 1-го байта принять 3-й - то же не хотим.
нужна подсказка от мастера. да, смотрим на линию SS. соответственно требования к мастеру:
1 чтоб случалась 1 на линии SS
2 чтоб была относительно продолжительной, 1 пикосек. 1 наносек - не годятся.
т.е. мастер должен опускать линию на все время передачи пачки, а подняв SS идти поделать какие делишки или потупить на задержке, перед тем как начинать следующий пакет.
да, SPI достаточно быстрый интерфейс, потому, пока, замедлим тактирование. кстати, не плохо бы знать время между байтами.
на слейве перед тем как принимать пакет (разрешить прерывание) ставим в ожидание 0 на SS, дождались обнуляем SR идем ждать счетчик байт перед отключением прерываний.
я бы не использовал прерывания на каждый байт, и массив master_arr, ну да ладно, пока так.
П.С. вам нравится писать случайные символы? зачем сдвиг вправо? (master_arr[2] >> 16)
писал же вам veso74 :
"...
Код:
fG = (master_arr[1])|(master_arr[2] <<

|(master_arr[3] << 16); //generator freqency
..."
и в обработчике прерываний нужно как можно меньше действий.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Пт июл 07, 2023 15:13:06
warptred12
Изменил код, теперь время получения посылки и отправки ее обратно мастеру - совпадают. Но почему-то нулевой байт посылки, отправляемой обратно мастеру всегда неверен. Например, мастер отправляет посылку: 02 89 41 00, а вот слейв отправляет обратно мастеру: 00 02 89 41 - это значит, что прочитанное значение сдвинуто вправо на 8 бит. Так же первая посылка, отправляемая мастером 00 00 00 00, а вот слейв читает ее как 80 00 00 00. Скриншот прикреплю ниже.
Код мастера:
Спойлер
Код: Выделить всё
#include <mega128.h>
#include <io.h>
#include <delay.h>
volatile unsigned char reqTr,reqTm;
struct Tmr_t {
unsigned char n;
double F;
};
struct Tmr_t T;
unsigned char chrT;
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;
void SPI_MasterTransmit(unsigned char cData);
void IOInit(void) {
PORTA = 0b00000000;
DDRA = 0b11111111;
PORTB = 0b00001001;
DDRB = 0b11110111;
PORTC = 0b00010000;
DDRC = 0b11111111;
PORTD = 0b01101100;
DDRD = 0b10111011;
PORTE = 0b00000011;
DDRE = 0b11111110;
PORTF = 0b00000000;
DDRF = 0b11111110;
PORTG = 0b00000000;
DDRG = 0b11111111;
reqTr=0;
reqTm=0;
}
void SPI_MasterInit(void) {
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1); /* Enable SPI, Master, set clock rate fck/16 */
}
void SPI_MasterTransmit(unsigned char cData) {
SPDR = cData; /* Start transmission */
while(!(SPSR & (1<<SPIF))); /* Wait for transmission complete */
}
void SPITransmitFreq(unsigned char Cnt, double F) { //F- значение частоты
dFi.w = F*167.77216; //частота передаваемая через SPI, какое-то фиксированное число 167.77216
PORTB &= ~(1<<PORTB0);
SPI_MasterTransmit(Cnt & 0x03);
SPI_MasterTransmit(dFi.b[0]);
SPI_MasterTransmit(dFi.b[1]);
SPI_MasterTransmit(dFi.b[2]);
PORTB |= (1<<PORTB0);
}
void main(void)
{
chrT=0x01;
T.n=0;
T.F=0;
SPI_MasterInit();
IOInit();
while (1)
{
unsigned char nG=2;
double fG=100;
SPITransmitFreq(T.n, T.F);//T.F-значение частоты, T.n-номер генератора
switch(nG) {
case 0: {T.n=0; T.F=fG; reqTm=1;}; break;
case 1: {T.n=1; T.F=fG; reqTm=1;}; break;
case 2: {T.n=2; T.F=fG; reqTm=1;}; break;
}
}
}
Изменил функцию прерывания по SPI, убрал switch, добавил for. Так же в основном цикле добавил проверку логического уровня на входе SS, там же включаю и выключаю прерывания.
Код слейва:
Спойлер
Код: Выделить всё
#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;
volatile unsigned char nG;
unsigned int N[]={1,8,64,256,1024};
//BYTE STORAGE
volatile unsigned char master_arr [4];
//BYTE COUNTER
volatile int reqID;
volatile int flagRT=0;
void setup (void)
{
#asm("cli")
DDRB |= (1 << PORTB4); //configure MISO as output
SPCR |= (1 << SPE) | (0 << MSTR); //configure slave mod and interrupt
#asm("sei")
}
interrupt [SPI_STC] void spi_isr(void)
{
unsigned char i=0;
for(i=0;i<5;i++) {
master_arr[i] = SPDR;
SPDR = master_arr [i];
}
}
//***********************************************timer1************************************************
void main(void)
{
VFG_DDR = 0b00000111;
DDRC = 0b11111111;
setup();
#asm("sei")
for(;;) {
if(PINB.2==0) {SPCR |= (1 << SPIE);} //ожидание 0 на SS для включения прерываний SPI
if(PINB.2==1) {SPCR |= (0 << SPIE);} //ожидание 1 на SS для отключения прерываний SPI
PORTC &= ~(1<<0);
PORTC &= ~(1<<1);
PORTC &= ~(1<<2);
PORTC &= ~(1<<3);
if (reqID >= (sizeof(master_arr) / sizeof(master_arr[0])))
{
nG = master_arr[0] & 0x03; //generator number
fG = 0|(master_arr[1] << 8)|(master_arr[2] << 16)|(master_arr[3] << 24); //generator freqency
PORTC &= ~(1<<4);
}
}
}
Добавлено after 6 minutes 9 seconds:
Не могу понять, почему 0 байт посылки искажается. Ведь код работает так: мастер отправляет данные из регистра SPDR, ждет ответ, когда получает ответ - шлет следующий байт и так по кругу. А слейв просто записывает полученные данные и отправляет их обратно. Без каких либо сдвигов, может быть я неправильно присваиваю значение нулевому элементу массива master_array[0] регистра данных SPDR.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Пт июл 07, 2023 16:06:44
a797945
"мастер ..., ждет ответ, ..."
мастер ждет не ответ, а когда закончится передача байта - она же прием байта.
SPI соединение это кольцо из двух сдвиговых регистров, и сдвиг в обоих тактируется мастером.
так что, первый принятый мастером байт это случайные данные из слейва, если потактируете 5-й байт увидите возвращение 4-го.
в информации никакого сдвига нет - не переживайте, здесь все в порядке. помните про байт-пустышку говорил.
по прежнему сдвигаем 1-й байт на место 2-го ?
fG = 0|(master_arr[1] << 8 )|(master_arr[2] << 16)|(master_arr[3] << 24);
вы не понимаете, что при сдвиге " fG = 0|(master_arr[1] << 8 )|... " изначально 1-й байт накладывается на место где должен быть 2-й ?