[RISOLTO] SPI si ferma se SS LOW

Non mi sarei mai aspettato che questo codice stampasse sulla seriale fino a 11670 e poi si fermasse :astonished: :astonished:

#include "AD9833.c"
void setup() 
{
  Serial.begin(115200);
  SPI_init();
  AD9833_init();
}
unsigned long i = 100;
void loop() 
{  
  Freq_change(i, 0);
  Serial.println(i);
  i+=1;
}

In teoria sarebbe dovuto andare fino a (2^32 - 1) ovvero il massimo permesso dal tipo unsigned long ma così non è..

Qualcuno ha avuto misteri simili?

Allego il codice completo per poterlo provare..

dds.zip (2.98 KB)

In che senso non va? Si blocca la stampa o cos'altro?
Poi mi pare che tu stia pilotando un generatore d'onde. Quell'integrato continua a modificare la frequenza d'uscita oppure no? Hai visto nella lib che la frequenza è max 2^14 come dimensione?

Si blocca il micro e di conseguenza il generatore d'onde che si ferma sull'ultima frequenza. Il problema non è il generatore d'onde, il problema persiste anche lanciando Arduino senza nulla collegato quindi è nel software.

Da ulteriori prove che ho fatto il problema sembra nella funzione SPI_write16 (file AD9833.cpp) che contiene l'istruzione

while (!(SPSR & (1<<SPIF)));			//	while busy

che blocca il tutto. Il while è dopo l'invio tramite SPI di una word di 8 bit per aspettare che sia effettivamente completato.
Non so come mai dopo un pò (SPSR & (1<<SPIF)) restituisce sempre 0 e quindi il codice rimane bloccato.. lo fa anche a voi?
Qualcuno che ha un debugger hw può dare qualche info in più?

SPSR -> Status Register SPI
SPIF -> registro per informare operazione completata

O i miei dubbi che centri qualcosa con gli interrupt..

Ciao e grazie

Quel while serve a rimanere in attesa del completamento dell'operazione di trasmissione.
Purtroppo non ho un AD9833 per poter provare quindi non posso aiutarti.

Tu che Arduino stai usando? Che versione dell'IDE?
Hai provato a togliere la stampa sulla seriale per vedere se funziona?

Come detto non serve un AD9833 per provare, carica lo sketch su Arduino senza nessun pin collegato e vedrai che si blocca lo stesso..

Arduino Uno, IDE 1.0.1, senza stampa si impalla lo stesso..

Non è che te debba mettere un delay ? in modo da lasciare il tempo al micro di svuotare il buffer della seriale, forse si impalla per questo motivo...

Ho provato ad inserire Serial.flush() dopo il Serial.println(i) ma niente da fare.. qualcuno di voi a provato a lanciare lo sketch e vedere a che ciclo si blocca?

Hai provato mettendo

unsigned long i = 11600;

per vedere se è un numero magico oppure se sono tot cicli che non sopporta.

Ho provato, non è una frequenza in particolare ma il ciclo che dopo un pò si ferma..
Se si cambia il valore iniziale di "i" il ciclo si ferma in un altro punto..

PS: Per fare delle prove NON vi serve nulla, basta che caricate lo sketch

Ho provato a mettere un delay(10) nel loop principale, intendi invece proprio in: while (!(SPSR & (1<<SPIF))); ?

A me il tuo sketch non compila. Da errori sul riconoscimento di PB0 dentro al file AD9833.c.
Provando lo sketch semplice, senza chiamate a SPI, funziona:

void setup() 
{
  Serial.begin(115200);
}
unsigned long i = 100;
void loop() 
{  
  Freq_change(i, 0);
  Serial.println(i);
  i+=1;
}

leo72:
A me il tuo sketch non compila. Da errori sul riconoscimento di PB0 dentro al file AD9833.c.
Provando lo sketch semplice, senza chiamate a SPI, funziona:

In che senso non riconosce PB0? e' il nome vero del pin 8 di Arduino, dentro al file AD9833.c c'è
#include <avr/io.h>
Quindi non dovresti avere problemi.. prova a postare l'errore che ricevi, che versione stai utilizzando? Hai messo come board "Arduino Uno"?

clone:
Al posto di quel while, ovunque compare nel codice, mettici un delay(time) scegliendo bene time.

Il while servirebbe proprio per attendere la trasmissione avvenuta, non saprei che valore di time mettere in un delay(time).. per curiosità, a te compila? Leo72 dice di avere problemi..

quindi se cambi il valore iniziale di I, cambia anche il valore a cui si impalla? e per caso sono sempre 11670 loop?

io farei un check della ram libera in fase di esecuzione.

flz47655:
In che senso non riconosce PB0? e' il nome vero del pin 8 di Arduino, dentro al file AD9833.c c'è
#include <avr/io.h>
Quindi non dovresti avere problemi.. prova a postare l'errore che ricevi, che versione stai utilizzando? Hai messo come board "Arduino Uno"?

Sì, lo so perfettamente che PB0 è una costante che indica un pin di Arduino. :wink:
Il problema è proprio quello, mi da errore sul riconoscimento delle costanti di Arduino all'interno del file AD8933.c, come se non caricasse i file del core. Io sto usando l'IDE 1.0.1 su Linux.

uhmm dai il log del compilatore? non vorrei che l'errore fosse dato da una DOPPIA inclusione o qualcosa del genere

lesto:
quindi se cambi il valore iniziale di I, cambia anche il valore a cui si impalla? e per caso sono sempre 11670 loop?

io farei un check della ram libera in fase di esecuzione.

Si, cambia il valore a cui si ferma e non sono sempre 11670 loop.

Non penso sia un problema di RAM, ne uso pochissima. Quando dico si ferma è perché il programma rimane dentro il while while (!(SPSR & (1<<SPIF))); quindi deve essere un problema coi registri/flag.. non vorrei che l'ide di arduino facesse qualche casino con gli interrupt che mi scasina qualcosa..

@leo72: su Windows a me non da questo errore.. magari puoi provare a mettere tutto in un file unico..

Ciao e grazie

hai già provato con la spi non bloccante?
oppure a stampare la ram libera nel ciclo precedente a quello in cui si blocca?

Ciao,
La libreria (che non ho scritto io, non conosco al momento i dettagli di SPI) scrive solamente per inviare i comandi e non legge mai dal device.

Ha questa funzione che scrive due word da 8 bit di seguito:

/*************************************************************************
Function: SPI_write16()
Purpose:  send a 16bit word to the AD9833 
Input:    unsigned short data = 16bits
Comment:  uses 8bit filter and two consecutive writes while fsync stays low
**************************************************************************/
void SPI_write16 (unsigned int data)    	// 	send a 16bit word and use fsync
{
  unsigned char MSdata = ((data>>8) & 0x00FF);  //filter out MS
  unsigned char LSdata = (data & 0x00FF);	//filter out LS

  PORTB &= ~_BV(PB0);				// 	Fsync Low --> begin frame
	
  SPDR = MSdata;				// 	send First 8 MS of data
  while (!(SPSR & (1<<SPIF)));        //	while busy

  SPDR = LSdata;				// 	send Last 8 LS of data
  while (!(SPSR & (1<<SPIF)));        //	while busy

  PORTB |= _BV(PB0);				// 	Fsync High --> End of frame
}

Quindi mi suggerisci di inserire l'istruzione:
SPDR;
Dopo ogni while (non ho ben capito cosa fa, serve quindi per leggere il registro ed evitare hazard conditions?)

Ciao e grazie

Niente da fare.. anche con l'istruzione SPDR; dopo il while si blocca..
Se al posto del while metto un delay(5) il codice sembra andare.. come supposto il problema è in

while (!(SPSR & (1<<SPIF)));

Ma non so come risolverlo..