Bonjour,
Le SPI à l'air en vogue en ce moment ^^.
Je réalise une liaison SPI entre les deux pics, le 18f est en maitre et le 30f en esclave.
J'ai des problèmes d'envoie de message du coté de l'esclave.
Je me retrouve face au problème suivant. lorsque j'active la liaison (lorsque j'appuie sur le bouton), SCK, SS et SDO du 18f sont correctement envoyées (je les lis à l'oscilloscope). J'arrive aussi à allumer une led : RD9, ce qui semble vouloir dire d'après mon test que le 30f interprète correctement la valeur envoyé par le maitre (18f).
Lorsque je lis la valeur envoyé par l'esclave (dspic30f), je ne reçois soit rien, soit un signal créneaux, sauf que je ne comprends pas ( certain retour se fond en dessous de la valeur de 0, certain entre 0 et 1).
J'ai essayé de mettre un dspic30f4013, puisque les broches sont identiques, et la je lis la valeur 5 volt (donc bits à 1 ) en permanence. Même lorsque je n'active pas la liaison ( lorsque je n'appuie pas sur le bouton).
j'ai parfois d'autre souci, comme lorsque je rajoute de l'allumage de led, certaine fonction ne fonction plus correctement, mais je ne comprends pas ces problèmes de synchronisation puisque je travaille avec des interruptions et que lorsque les interruptions sont activées ( comme BF, IF etc... ) c'est logiquement que j'ai obtenu ce que je veux.
Je joins mon code, si je pouvais avoir des conseils, je ne vois pas trop ce que je n'ai pas compris. (mes readspi et write spi sont inspiré ou la copie de spi.h, je les rajoute pour que vous puissiez les voir).
Code du maitre
[code]
****************************** ****************************** ****************************** ****************************** ************/
// déclaration :
#include <p18f4550.h>
short dataRecuSPI = 0;
unsigned char WriteSPI( unsigned char data_out );
// short dataEnvoiSPI = 0;
/*
void initclk(void) // Fosc = Fin*M/(N1*N2), Fcy=Fosc/2
{
// ici Fosc = 20Mhz*10/( )
CONFIG1L = 0b00000101;
}*/
void initSPI18f(void) // initialise SPI sur pic18f4550
{
PIR1bits.SSPIF = 0; // flag d'interruption à 0.
PIE1bits.SSPIE = 0; // désactiver le module d'interruption.
SSPSTAT = 0; // reset module SPI.
SSPBUF = 0; // Clear SPI buffer.
/* Mode Maître, FOSC 1:64. */
SSPCON1bits.SSPM3 = 0;
SSPCON1bits.SSPM2 = 0;
SSPCON1bits.SSPM1 = 1;
SSPCON1bits.SSPM0 = 0;
SSPCON1bits.WCOL = 0; // Pas de gestion des collisions.
SSPSTATbits.SMP = 0; // Input data sampled at end of data output time
SSPSTATbits.CKE = 0; // Serial output data changes on transition from Idle clock state to active clock state
SSPCON1bits.CKP = 0; // Idle state for clock is a high level; active state is a low level
SSPCON1bits.SSPEN = 1; // activer SS, SDO, SDI, SCK
PIR1bits.SSPIF = 0; // flag d'interruption à 0.
PIE1bits.SSPIE = 1; // active le module d'interruption.
}
int reception_SPI ()
{
// Flag de fin de transmission :
PORTAbits.RA5 = 0; // SS à 0.
//while(SSPSTATbits.BF != 1) {}
//dataRecuSPI = SSPBUF; //Lecture du buffer.
if (SSPSTATbits.BF)
{
SSPCON1bits.SSPOV = 0;
return (SSPBUF); /* return byte read */
}
else return -1;
}
int envoi_SPI(char dataEnvoiSPI)
{
PORTAbits.RA5 = 0; // SS à 0
//while(SSPSTATbits.BF!=1){} // Flag de fin de transmission.
WriteSPI(dataEnvoiSPI);
PORTAbits.RA5 = 1; // SS à 1 : esclave sélectionné : envoie.
}
void interruptionSPI(void);
#pragma code high_vector=0x08
void interrupt_at_high_vector(void)
{
_asm GOTO interruptionSPI _endasm
}
#pragma code
void interruptionSPI(void)
{
short val = 0;
if (PIR1bits.SSPIF)
val = (short)reception_SPI();
PIR1bits.SSPIF = 0; // Clear Flag SPI
return val;
}
void main (void)
{
int led = 0;
TRISBbits.TRISB0 = 1; // SDI en entrée
TRISBbits.TRISB1 = 0; // SCK en sortie
TRISCbits.TRISC7 = 0; // SDO en sortie
TRISCbits.TRISC2 = 1; // bouton en entrée
TRISAbits.TRISA5 = 0; // SS en sortie
initSPI18f();
while(1)
{
// PORTCbits.RC2 = 0;
short val = 0;
if(PORTCbits.RC2 == 1)
{
envoi_SPI(0x0e);
// val = (short)reception_SPI();
}
// if(PORTAbits.RA0)
// envoi_SPI(0x0f);
// else if(PORTAbits.RA2)
// envoi_SPI(0x01);
}
}
[\code]
liaison esclave
[code]
/* liaison spi pour un dsPic30f3014. A part l'init, la plupart des fonctions sont inspirées de la librairies spi fournit par microC */
#include <p30f4013.h>
#include <spi.h>
/* initialisation de l'SPI en mode esclave :
1 en paramètre pour activer les interruptions, 0 sinon. */
void initSpi_S()
{
/*
TRISFbits.TRISF2 = 1; // SDI en entrée.
TRISFbits.TRISF3 = 0; // SDO en sortie.
TRISFbits.TRISF6 = 1; // SCK en entrée.
TRISBbits.TRISB2 = 1; // SS en entrée.
SPI1BUF = 0;
if(interrupt != 0)
{
IFS0bits.SPI1IF = 0; // désactive le flag d'interruption.
IEC0bits.SPI1IE = 1; // active l'interruption du mode SPI.
IPC2bits.SPI1IP = 5; // priorité de niveau 5 ( les priorités s'échelonnant de 0 à 7, 7 étant la plus élevée).
}
SPI1CONbits.MSTEN = 0; // passage en mode esclave.
SPI1CONbits.SMP = 0; // clear en mode esclave.
SPI1CONbits.CKE = 0; // comme pour le pic18f4550.
SPI1STATbits.SPIROV = 0; // Pas d'overflow.
SPI1CONbits.MODE16 = 0; // mode 8 bits.
SPI1CONbits.SPRE = 8; // prescaler secondaire à 1.
SPI1CONbits.PPRE = 0; // prescaler primaire à 64:1.
SPI1STATbits.SPIEN = 1; // active le module SPI.
*/
SPI1STATbits.SPIEN = 0; // active le module SPI.
SPI1STATbits.SPISIDL = 0; // opération du module continue en Idle mode
IFS0bits.SPI1IF = 0; // Clear the Interrupt Flag
IEC0bits.SPI1IE = 0; // Disable the Interrupt
SPI1STAT = 0; // reset module SPI
SPI1BUF = 0; // Clear SPI buffer
SPI1CONbits.DISSDO=0; // SDO1 pin is controlled by the module
SPI1CONbits.MODE16 = 0; // mode 8 bits.
SPI1CONbits.MSTEN = 0; // passage en mode esclave.
SPI1CONbits.SMP = 0; // clear en mode esclave.
SPI1CONbits.CKE = 0; // Serial output data changes on transition from Idle clock state to active clock state
SPI1CONbits.CKP = 0; // Idle state for clock is a high level; active state is a low level
// SPI1CONbits.SPRE = 0b111; // Secondary prescale 1:1
// SPI1CONbits.PPRE = 0b00; // Primary prescale 64:1
SPI1CONbits.SSEN = 1; // SSx pin is used for Slave mode
// SPI1CONbits.FRMEN = 0;
SPI1STATbits.SPIROV = 0;
IFS0bits.SPI1IF = 0; // Clear the Interrupt Flag
IEC0bits.SPI1IE = 1; // Enable the Interrupt
// IPC2bits.SPI1IP = 5; // priorité de niveau 5 ( les priorités s'échelonnant de 0 à 7, 7 étant la plus élevée).
SPI1STATbits.SPIEN=1; // active le module SPI.
}
/* retourne */
char DataRdySPI1()
{
return SPI1STATbits.SPIRBF; /* retourne la valeur du bit RBF */
}
void finSPI1()
{
IEC0bits.SPI1IE = 0;
SPI1STATbits.SPIEN = 0;
IFS0bits.SPI1IF = 0;
}
unsigned int ReadSPI1()
{
/* Check for Receive buffer full status bit of status register*/
if (SPI1STATbits.SPIRBF)
{
SPI1STATbits.SPIROV = 0;
if (SPI1CONbits.MODE16)
return (SPI1BUF); /* return word read */
else
return (SPI1BUF & 0xff); /* return byte read */
}
return -1; /* RBF bit is not set return error*/
}
/* écrit une donnée sur le bus SPI, fonction prévue pour les deux cas 8 bits ou 16 bits */
void writeSPI1(unsigned int data_envoie)
{
if (SPI1CONbits.MODE16) /* word write */
SPI1BUF = data_envoie;
else
SPI1BUF = data_envoie & 0xff; /* byte write */
}
void __attribute__((__interrupt__,n o_auto_psv)) _SPI1Interrupt(void)
{
PORTDbits.RD0 = 0;
int dataRecu = 0;
writeSPI1(0xfe);
if (IFS0bits.SPI1IF) {
// if(SPI1STATbits.SPIRBF)
dataRecu = ReadSPI1();
if(dataRecu==0x0e) PORTDbits.RD9 = ~PORTDbits.RD9;
}
IFS0bits.SPI1IF = 0;
PORTDbits.RD0 = 1;
}
void main(void)
{
TRISD = 0;
TRISFbits.TRISF2 = 1; // SDI en entrée.
TRISFbits.TRISF3 = 0; // SDO en sortie.
TRISFbits.TRISF6 = 1; // SCK en entrée.
TRISBbits.TRISB2 = 1; // SS en entrée.
initSpi_S();
while(1)
{
// PORTDbits.RD9 = 0;
}
}
[\code]
Merci
-----