Bonjour a tous,
J'essaye de faire communiquer deux PIC16F1828 entre eux grâce à la communication SPI et je rencontre des problèmes.
Voici le code du master, sur Mblab X avec XC8:
Et le code du slave :Code:#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin) #pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled) #pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled) #pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR) #pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled) #pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled) #pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset disabled) #pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin) #pragma config IESO = OFF // Internal/External Switchover (Internal/External Switchover mode is disabled) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled) // CONFIG2 #pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off) #pragma config PLLEN = OFF // PLL Enable (4x PLL disabled) #pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset) #pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.) #pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming) #include <stdio.h> #include <stdlib.h> #include "fonctions.h" #define _XTAL_FREQ 16000000 int main(int argc, char** argv) { OSCCONbits.IRCF0 = 1; OSCCONbits.IRCF1 = 1; OSCCONbits.IRCF2 = 1; OSCCONbits.IRCF3 = 1; SPI_init(); TRISAbits.TRISA5 = 0; while (1){ __delay_ms(2000); SPI_write(101); } return (EXIT_SUCCESS); } //////////////////////////////// Et voici les fonctions : #include <xc.h> #include "fonctions.h" #define _XTAL_FREQ 16000000 void SPI_init(){ SSP1CON1bits.SSPM = 1; // selectionne le mode spi master avec fosc/16 SSP1CON1bits.CKP = 0; // définit l'état inactif de l'horloge a 0 SSP1STATbits.CKE = 0; // les données seront transmises au passage de l'horloge de l'état bas àl'état haut SSP1STATbits.SMP = 0; // les données sont échantillonnées (à la réception) à la moitié du temps de l'émission TRISCbits.TRISC6 = 0; // gère les I/O TRISCbits.TRISC7 = 0; TRISBbits.TRISB6 = 0; TRISBbits.TRISB4 = 1; SSP1CON1bits.SSPEN = 1; RC6 = 1; // met la pin ss à l'état haut désactive la communication } void SPI_write(unsigned char data){ RC6 = 1; // lance la communication SSP1BUF = data; while(!PIR1bits.SSP1IF){ RA5 = 1; // led d'indication : elle clignote quand l'envoi a lieu } PIR1bits.SSP1IF = 0; RA5 = 0; RC6 = 1; // finit la communication*/ }
Donc avec ça j'ai une communication qui se lance bien toutes les deux secondes (une led sur SCK me le prouve), et qui s'exécute aussi sur la pin SDO du master, mais seulement quand la valeur rentrée dans SPI_write() est ronde. Par exemple, avec SPI_write(50), je vois que la communication sur SDO se fait bien en même temps que SCK, mais avec SPI_write(51) la pin SDO se met à un état plus ou moins haut, indéfiniment.Code:#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin) #pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled) #pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled) #pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR) #pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled) #pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled) #pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset disabled) #pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin) #pragma config IESO = OFF // Internal/External Switchover (Internal/External Switchover mode is disabled) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled) // CONFIG2 #pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off) #pragma config PLLEN = OFF // PLL Enable (4x PLL disabled) #pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset) #pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.) #pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming) #include <stdio.h> #include <stdlib.h> #include "fonctions.h" #define _XTAL_FREQ 16000000 unsigned char data = 0; void main(void) { OSCCONbits.IRCF0 = 1; OSCCONbits.IRCF1 = 1; OSCCONbits.IRCF2 = 1; OSCCONbits.IRCF3 = 1; TRISBbits.TRISB7 = 0; SPI_init_slave(); // initialise le mssp1 RB7 = 1; while (1){ if (SPI_isready()){ /*if(SPI_read() == 0){ RB7 = 1; } else{ RB7 = 0; }*/ //RB7 = 1; data = SPI_read(); SPI_write_slave(127); SPI_init_slave(); } if (data != 0){ RB7 = 1; } else if (data == 0){ RB7 = 0; } } return; } /////////////////////////////et les fonctions : #include <xc.h> #include "fonctions.h" void SPI_init_slave(){ SSP1CON1bits.SSPM = 0b0100; // selectionne le mode spi avec contôle par ss SSP1CON1bits.CKP = 0; // définit l'état inactif de l'horloge a 0 SSP1STATbits.CKE = 0; // les données seront transmises au passage de l'horloge de l'état bas àl'état haut SSP1STATbits.SMP = 0; // les données sont échantillonnées (à la réception) à la moitié du temps de l'émission TRISCbits.TRISC6 = 1; // met la pin ss en entée TRISCbits.TRISC7 = 0; // met la pin SDO en sortie (serial data output pour ce module connecté à sdi du master) TRISBbits.TRISB6 = 1; // met la pin SCK en entrée TRISBbits.TRISB4 = 1; // met la pin SDI en entrée SSP1CON1bits.SSPEN = 1; // active la communication le module mssp } void SPI_write_slave(int data){ SSP1BUF = data; } unsigned char SPI_read(void){ unsigned char dat = SSP1BUF; return(dat); } unsigned SPI_isready(void){ if(PIR1bits.SSP1IF){ PIR1bits.SSP1IF = 0; return 1; } else{ return 0; } }
De plus, le slave ne reçoit jamais autre chose que 0, alors que celui ci est synchronisé. (SSP1IF, le flag qui indique que les 8 bits ont bien été transmis, se met bien à 1 toute les deux secondes).
Je ne sais donc pas ce qui échoue dans les fonctions de lecture et d'écriture et c'est pourquoi je sollicite votre aide.
Merci d'avance
-----