Страница 4 из 7
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Ср июл 05, 2023 12:31:46
MOHCTEP
Ну, у вас слейв отправляет неведомо что из массива 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
warptred12
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
MOHCTEP
А это похоже, что master_arr у вас нулями заполняется. Возможно оттого и частота не меняется.
warptred12 писал(а):Так же ругается на эту строчку:
Это я для краткости так написал, видимо не хватает разрядности fG. Если так, то в результате fG всегда = 0 будет. Переделайте эту строку на ваш предыдущий код с темповой переменной.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Ср июл 05, 2023 13:43:06
warptred12
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
MOHCTEP
Не ну...
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
warptred12
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
MOHCTEP
Уберите светодиоды из прерывания и попробуйте их тут, чтобы понять, этот участок кода вообще работает?
Код: Выделить всё
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
warptred12
MOHCTEP, не работает.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 14:26:06
MOHCTEP
Ну вот и проблема. Опять с 3 кейсом наверное? reqID просто не "добирает" до 4.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 14:44:08
warptred12
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
veso74
Обсуждалось в другой теме. Использование sizeof для определения размера массивов дает неправильный результат, поскольку параметры массива рассматриваются как указатели. Попробуйте:
Код: Выделить всё
if (reqID >= sizeof(arr) / sizeof(arr[0])) ...
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 15:05:11
MOHCTEP
Кстати
veso74 прав. У вас же массив сейчас 16 байт весит...
только еще скобку добавьте
Код: Выделить всё
if (reqID >= (sizeof(arr) / sizeof(arr[0]))) ...
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 15:10:10
warptred12
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;
}
}
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 15:11:03
veso74
MOHCTEP, скобки не необходими

:
Код: Выделить всё
C Operator Precedence:
...
3 : /
...
6 : >=
...
---
warptred12, компилятор какой? На два попробовал, ОК.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 15:19:49
warptred12
Именно компилятор пишет красным на эту строку: 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
veso74
Для этого следуйте логике вашего примера. Если так сложно (карандаш и лист бумаги!), разбейте примерно на части и напр. распечатайте промежуточные результаты, или делайте реакцией к LED? ...
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 15:31:05
warptred12
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 - тоже работает.
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 15:31:53
MOHCTEP
warptred12, А частота меняется?
Re: Проблема при связи SPI и USI AT90CAN128 и Attiny2313
Добавлено: Чт июл 06, 2023 15:44:10
warptred12
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
veso74
Код: Выделить всё
if (reqID >= (sizeof(master_arr) / sizeof(master_arr[0])/ sizeof(master_arr[1])/ sizeof(master_arr[2])/ sizeof(master_arr[3]))
А что это?