Hot!SPI ISSUE

Author
lamieristoff
New Member
  • Total Posts : 14
  • Reward points : 0
  • Joined: 2018/10/05 00:31:56
  • Location: 0
  • Status: offline
2018/10/11 14:33:03 (permalink)
0

SPI ISSUE

Hi Everybody,
 
I am a newbie in PIC program and I have an issue on a simple project with a SPI communication.
The µcontroler is the master and send information to LEDs APA102.
The issue is the following, the clock of the SPI never starts on my PIC16F1779.
I have read a lot of websites, application notes,... to solve my problem but nothing works so I come here to find new ideas.
 
I use some generic function to init and send data but every time nothing happens when the data must be sent.
I used RB0 as a marker to check if the software was alive and to check when I start the communication.
The state of RB0 is changing but nothing on the SLK line.
 

 
 
//in the main program
// Init SPI communication
    spiInit(SPI_MASTER_OSC_DIV4,SPI_DATA_SAMPLE_MIDDLE,SPI_CLOCK_IDLE_LOW,SPI_ACTIVE_2_IDLE);
    SSP1CON3bits.BOEN = 0;               //allows to write a byte before it has been read
    PIE1bits.SSP1IE = 1;                 //Activate SPI flag interrupt
 
// part of the ISR function
 if (PIR1bits.TMR1IF)                                         //send color to the leds
    {
        TMR1ON = 0;
        RB0=1;
        global = 0b11100000 | brightness ;
        SetRGB (led , global , blue_color , green_color , red_color);
        
        //send start frame
        spi(0x00);
        spi(0x00);
        spi(0x00);
        spi(0x00);
        //data transmission
        for (j=0;j < (led+1)*4 ;j++)
            spi(ledData[j]);
        
        //send end frame
        spi(0xFF);
        spi(0xFF);
        spi(0xFF);
        spi(0xFF);
            
        PIR1bits.TMR1IF = 0;// reset TMR1
        transfert = 1;
        RB0=0;
    }//if TMR1IF
 
 
 
// in function declaration
 
void spiInit(Spi_Type sType, Spi_Data_Sample sDataSample, Spi_Clock_Idle sClockIdle, Spi_Transmit_Edge sTransmitEdge)
{
    TRISCbits.TRISC5 = 0;
    if(sType & 0b00000100) //If Slave Mode
    {
        SSP1STAT = sTransmitEdge;
        TRISCbits.TRISC3 = 1;
    }
    else //If Master Mode
    {
        SSP1STAT = sDataSample | sTransmitEdge;
        TRISCbits.TRISC3 = 0;
    }
    
    SSP1CON1 = sType | sClockIdle;
    
    SSPDATPPS = 0b010101; //SDI on RC4
    RC3PPS = 0b100011; //SCK on RC3
    RC5PPS = 0b100001; //SDO on RC5
}

unsigned char spi( unsigned char data_out )
{
    SSP1BUF = data_out; // write byte to SSPBUF register
    while( !SSP1STATbits.BF ); // wait until bus cycle complete
    return ( SSP1BUF ); // return data and clear BF
}

 
Could you give me some point to check because I don't know what I can do to solve this issue?
 
Thank you in advance for your help
 
 
#1

13 Replies Related Threads

    jack@kksound
    code tags!
    • Total Posts : 2842
    • Reward points : 0
    • Joined: 2014/05/14 10:03:19
    • Location: 0
    • Status: offline
    Re: SPI ISSUE 2018/10/11 14:39:26 (permalink)
    +1 (1)
    You should post all your code, small snippets often do NOT contain the code in error leading to wasted time looking in the wrong places.
    #2
    qhb
    Superb Member
    • Total Posts : 7538
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: SPI ISSUE 2018/10/11 14:41:40 (permalink)
    +1 (1)
    You are enabling SSP interrupts
        PIE1bits.SSP1IE = 1;                 //Activate SPI flag interrupt


    but the ISR code you posted only handles TMR1 interrupts.
    If your ISR is not handling SSP1 interrupts, then it will never get out of the ISR.
    Do NOT set SSP1IE if your code is just polling the SSP1IF flag.
     
    Personally, I'd get your code going WITHOUT interrupts to start with.
    What test tools do you have? An oscilloscope? A logic probe?
     
     
    #3
    lamieristoff
    New Member
    • Total Posts : 14
    • Reward points : 0
    • Joined: 2018/10/05 00:31:56
    • Location: 0
    • Status: offline
    Re: SPI ISSUE 2018/10/11 14:50:00 (permalink)
    0
    // main header 
    #ifndef GAZON_H
    #define GAZON_H


    // CONFIG1
    #pragma config FOSC = INTOSC // Oscillator Selection Bits (Internal Oscilator)
    #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 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 Mode (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 PPS1WAY = OFF // Peripheral Pin Select one-way control (The PPSLOCK bit cannot be cleared once it is set by software)
    #pragma config ZCD = OFF // Zero-cross detect disable (Zero-cross detect circuit is disabled at POR)
    #pragma config PLLEN = OFF // Phase Lock Loop enable (4x PLL is enabled when software sets the SPLLEN bit)
    #pragma config STVREN = OFF // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
    #pragma config BORV = HI // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), high trip point selected.)
    #pragma config LPBOR = OFF // Low-Power Brown Out Reset (Low-Power BOR is disabled)
    #pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)

    #include <xc.h> // include processor files - each processor file is guarded.

    // TODO Insert appropriate #include <>
    #include <math.h>
    #include "spi.h"
    //#include <delay.h>

    // TODO Insert C++ class definitions if appropriate

    // TODO Insert declarations
    #define _XTAL_FREQ 16000000

    // number of leds (5 x 4 for GLOBAL red, blue, green)
    #define NUMBER_OF_LEDS 5
    #define LED_ARRAY_SIZE 20

    // Comment a function and leverage automatic documentation with slash star star
    /**
        <p><b>Function prototype:</b></p>
      
        <p><b>Summary:</b></p>

        <p><b>Description:</b></p>

        <p><b>Precondition:</b></p>

        <p><b>Parameters:</b></p>

        <p><b>Returns:</b></p>

        <p><b>Example:</b></p>
        <code>
     
        </code>

        <p><b>Remarks:</b></p>
     */
    // TODO Insert declarations or function prototypes (right here) to leverage
    // live documentation

    unsigned char ledData[LED_ARRAY_SIZE];

    // set the RGB value (0-255) of a single led.
    void SetRGB(unsigned char,unsigned char, unsigned char, unsigned char, unsigned char);



    #ifdef __cplusplus
    extern "C" {
    #endif /* __cplusplus */

        // TODO If C++ is being used, regular C code needs function names to have C
        // linkage so the functions can be used by the c code.

    #ifdef __cplusplus
    }
    #endif /* __cplusplus */

    #endif /* XC_HEADER_TEMPLATE_H */



    // spi header
    #ifndef SPI_H
    #define SPI_H

    #include <xc.h>

    typedef enum
    {
        SPI_MASTER_OSC_DIV4 = 0b00100000,
        SPI_MASTER_OSC_DIV16 = 0b00100001,
        SPI_MASTER_OSC_DIV64 = 0b00100010,
        SPI_MASTER_TMR2 = 0b00100011,
        SPI_SLAVE_SS_EN = 0b00100100,
        SPI_SLAVE_SS_DIS = 0b00100101
    }Spi_Type;

    typedef enum
    {
        SPI_DATA_SAMPLE_MIDDLE = 0b00000000,
        SPI_DATA_SAMPLE_END = 0b10000000
    }Spi_Data_Sample;

    typedef enum
    {
        SPI_CLOCK_IDLE_HIGH = 0b00010000,
        SPI_CLOCK_IDLE_LOW = 0b00000000
    }Spi_Clock_Idle;

    typedef enum
    {
        SPI_IDLE_2_ACTIVE = 0b00000000,
        SPI_ACTIVE_2_IDLE = 0b01000000
    }Spi_Transmit_Edge;


    void spiInit(Spi_Type, Spi_Data_Sample, Spi_Clock_Idle, Spi_Transmit_Edge);
    unsigned char spi( unsigned char data_out );

    #endif /* SPI_H */

    // main function

    #include "Gazon.h"


    unsigned char red_color = 0;
    unsigned char green_color = 0;
    unsigned char blue_color =0;
    char led_count = 0;
    char bit_count = 0;
    unsigned int i = 0;
    unsigned int j = 0;
    unsigned long int color_led;
    unsigned long int data;
    unsigned long int matrice[9];
    unsigned long int essai;
    unsigned char mask;
    unsigned char led;
    unsigned char brightness;
    unsigned char global;
    bit transfert=0;
    char test;

    //------------------------------------------------------------------------------

    void interrupt isr(void) // Here be interrupt function
    {
         if (ADIF)
        {
            if (ADCON0bits.CHS == 0) //red pot measurement on RA0
            {
                red_color = ADRESH;
            }
            else if (ADCON0bits.CHS == 1) //green pot measurement on RA1
            {
                green_color = ADRESH;
            }
            else if (ADCON0bits.CHS == 2) //blue pot measurement on RA2
            {
                blue_color = ADRESH;
            }

            ADIF = 0;
        }//if (ADIF)
        
        if(IOCIF)
        {
            if (IOCBF5) // add one led
            {
                led++;
                if (led >= NUMBER_OF_LEDS)
                    led = NUMBER_OF_LEDS - 1;
                IOCBF5 = 0;
            }
            
            if (IOCBF4) // RAZ screen
            {
                for(led=0; led < LED_ARRAY_SIZE;led++)
                {
                    ledData[led] = 0;
                }
                led = 0;
                
                //send start frame
                spi(0x00);
                spi(0x00);
                spi(0x00);
                spi(0x00);
                //data transmission
                for (i=0;i < LED_ARRAY_SIZE;i++)
                    spi(0x00);
                
                //send end frame
                spi(255);
                spi(255);
                spi(255);
                spi(255);
                        
                IOCBF4 = 0;
            }// end IOCBF4
           
            IOCIF = 0;
        }// End IOCBIF
         
         
    // if (TMR0IF)
    // {
    // TMR0IF = 0;
    // }
         
        if (PIR1bits.TMR1IF) //send color to the lums
        {
            TMR1ON = 0;
            RB0=1;
            global = 0b11100000 | brightness ;
            SetRGB (led , global , blue_color , green_color , red_color);
            
            //send start frame
            spi(0x00);
            spi(0x00);
            spi(0x00);
            spi(0x00);
            //data transmission
            for (j=0;j < (led+1)*4 ;j++)
                spi(ledData[j]);
            
            //send end frame
            spi(0xFF);
            spi(0xFF);
            spi(0xFF);
            spi(0xFF);
                
            PIR1bits.TMR1IF = 0;// reset TMR1
            transfert = 1;
            RB0=0;
        }//if TMR1IF
        
        if (SSP1IF)
            SSP1IF=0;
         
         
    }//interrupt


    //------------------------------------------------------------------------------
    //
    //------------------------------------------------------------------------------
    void main(void)
    {
    // oscillator configuration
        OSCCONbits.SCS = 0b00; //OSC Clock defined by FOSC (config word)
        OSCCONbits.IRCF = 0b1111; //OSC set to 16Mhz
        OSCCONbits.SPLLEN = 0; // 4XPLL deactivated
        
        while(!HFIOFS); // waiting for stable oscilator
       
        INTCON=0x00; //GIE =0 | PEIE = 0|

    //variables init
        brightness = 0b00010000; // brightness on the 5 Lsb
        led = 0;
        red_color = 0;
        blue_color = 0;
        green_color = 0;
    // color_led [] = { 0};
        

    //IO initilization
        PORTA = 0x00;
        PORTB = 0x00;
        PORTC = 0x00;
        // RA0 RA1 RA2 Potentiometer to control color
        TRISA = 0b00000111; // RA0 RA1 RA2 input
        ANSELA = 0b00000111; // RA0 RA1 RA2 Analog input
        // RB4 RB5 switch
        TRISB = 0b00011000; // RB5 RB4 Input
        ANSELB = 0b00000000; //
        //RC3(SCK) RC4(SDI) RC5(SDO) SPI line
        TRISC = 0b00010000; //RC4 input
        ANSELC = 0b00000000; //
        
    ////initialisation of timer 0
    // OPTION_REG = 0b10010111; //WPUEN disable :1 | INTEDG off : 0 | Timer0 CLK 1cycle : 0 | 1 | prescaler on : 0 | prescaler 256 : 111|
    // TMR0IE = 1; //TMR1 Interrupt activation

    //initialisation of timer 1
    //Timer1 Registers Prescaler= 8 - TMR1 Preset = 0 - Freq = 9.54 Hz - Period = 0.104858 seconds
        T1CON = 0b00110000;
        TMR1H = 0; // preset for timer1 MSB register
        TMR1L = 0; // preset for timer1 LSB register
        TMR1IE = 1;


    //init ADC on RA0
        ADCON1 = 0b01100000; //left justify :1|Fosc/64 (tad = 4µ) : 110|x|Vref-=VSS| Vref+ = VDD
        ADCON0bits.CHS = 0; //ADC on AN0
        PIR1bits.ADIF = 0; //Clear ADC flag
           
    //init interrupt on change
        IOCBP5 = 1; //rising edge on RB5
        IOCBP4 = 1; //rising edge on RB4
            
    // Init SPI communicaation
        spiInit(SPI_MASTER_OSC_DIV4,SPI_DATA_SAMPLE_MIDDLE,SPI_CLOCK_IDLE_LOW,SPI_ACTIVE_2_IDLE);
        SSP1CON3bits.BOEN = 0; //allows to write a byte before it has been read
        PIE1bits.SSP1IE = 1; //Activate SPI flag interrupt
        
        ///init interrupt ADC
        IOCIE = 1; //interrupt on change activation
        ADIE = 1; //ADC interrupt activation
        
        GIE = 1; // general interrupt activation
        PEIE = 1; //Peripheric interrupt activation
           
        while(1)
        {
        //potentiometer measurement
            RB1=1;
            
            
            ADCON0 = 0b00000001; //X|AN0(RA0):00000|go :0 |ADC on : 1
            ADCON0bits.GO = 1; //red color measurement
            while (ADCON0bits.GO);
            
            ADCON0 = 0b00000101; //X|AN1(RA1):00001|go :0 |ADC on : 1
            ADCON0bits.GO = 1; //green color measurement
            while (ADCON0bits.GO);

            ADCON0 = 0b00001001; //X|AN2(RA2):00010|go :0 |ADC on : 1
            ADCON0bits.GO = 1; //blue color measurement
            while (ADCON0bits.GO);

            
            TMR1ON = 1; //TMR1 ON
            while (!transfert)
                RB1=0;
            
            transfert = 0;
            
        } // end while(1))
    }// end main
     

    #4
    qhb
    Superb Member
    • Total Posts : 7538
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: SPI ISSUE 2018/10/11 14:54:19 (permalink)
    +1 (1)
    Now I have seen your full code, I still suggest you should delete this line
        PIE1bits.SSP1IE = 1; //Activate SPI flag interrupt


     
    #5
    lamieristoff
    New Member
    • Total Posts : 14
    • Reward points : 0
    • Joined: 2018/10/05 00:31:56
    • Location: 0
    • Status: offline
    Re: SPI ISSUE 2018/10/11 14:56:03 (permalink)
    0
    qhb
     
    What test tools do you have? An oscilloscope? A logic probe?
     




    I used an oscilloscope to catch the RB0 changes, so I can know that the pic is still alive and not stuck in a loop.
    I don't see anything on the SCK line from the PIC so I suppose that the SPI is not well enabled
    #6
    lamieristoff
    New Member
    • Total Posts : 14
    • Reward points : 0
    • Joined: 2018/10/05 00:31:56
    • Location: 0
    • Status: offline
    Re: SPI ISSUE 2018/10/11 14:57:48 (permalink)
    0
    qhb
    Now I have seen your full code, I still suggest you should delete this line
        PIE1bits.SSP1IE = 1; //Activate SPI flag interrupt


     




     ok done I can't test it know but I will keep you updated if there is a change
    #7
    qhb
    Superb Member
    • Total Posts : 7538
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: SPI ISSUE 2018/10/11 15:04:57 (permalink)
    +1 (1)
    lamieristoff
    I used an oscilloscope to catch the RB0 changes, so I can know that the pic is still alive and not stuck in a loop.

    You're toggling RB0 inside the ISR, so that doesn't prove your non-interrupt code is running.
    You should check RB1 for that.
     
    (I agree that if your non-interrupt code was not running, then TMR1 should be off, so you shouldn't be getting RB0 toggling, but when things are going wrong, it's best to test things directly, not make too many assumptions.)
     
    #8
    qhb
    Superb Member
    • Total Posts : 7538
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: SPI ISSUE 2018/10/11 15:10:16 (permalink)
    +2 (2)

        RC3PPS = 0b100011; //SCK on RC3
        RC5PPS = 0b100001; //SDO on RC5

    You have the PPS values for SDO and SCK swapped.
     
     
    #9
    lamieristoff
    New Member
    • Total Posts : 14
    • Reward points : 0
    • Joined: 2018/10/05 00:31:56
    • Location: 0
    • Status: offline
    Re: SPI ISSUE 2018/10/12 03:54:57 (permalink)
    0
    Hi
     
    I have tested what you told me, now the SPI line seems to be enabled but the clock seems to crash on the first front (see picture scope1).
    The scope 2 is the clock line with a bigger timeline.
     
    For information RB0 and RB1 are OK

    Attached Image(s)

    #10
    Nikolay_Po
    Super Member
    • Total Posts : 1702
    • Reward points : 0
    • Joined: 2012/04/01 13:49:27
    • Location: Russia, Novorossiysk
    • Status: offline
    Re: SPI ISSUE 2018/10/12 05:32:14 (permalink)
    +4 (4)
    Your scope probing is incorrect. SPI frequency is way too high for your scope sampling speed. You need at least 16Msps oscilloscope sampling speed. Even being used 1:64 SPI prescaller you need faster than 1Msps scope sampling. As I see on the screenshots, your scope sampling speed is 0.1Msps which is unallowable small.
    If I'm understanding your PIC correctly, the SPI bitrate is 16MHz/4=4MHz. With 100ksps scope sampling up to 40 bits of SPI transmission may pass between samples unnoticed at all!
    #11
    lamieristoff
    New Member
    • Total Posts : 14
    • Reward points : 0
    • Joined: 2018/10/05 00:31:56
    • Location: 0
    • Status: offline
    Re: SPI ISSUE 2018/10/19 05:53:12 (permalink)
    0
    Nikolay_Po
    Your scope probing is incorrect. SPI frequency is way too high for your scope sampling speed. You need at least 16Msps oscilloscope sampling speed. Even being used 1:64 SPI prescaller you need faster than 1Msps scope sampling. As I see on the screenshots, your scope sampling speed is 0.1Msps which is unallowable small.
    If I'm understanding your PIC correctly, the SPI bitrate is 16MHz/4=4MHz. With 100ksps scope sampling up to 40 bits of SPI transmission may pass between samples unnoticed at all!




    #12
    lamieristoff
    New Member
    • Total Posts : 14
    • Reward points : 0
    • Joined: 2018/10/05 00:31:56
    • Location: 0
    • Status: offline
    Re: SPI ISSUE 2018/10/21 23:37:12 (permalink)
    0
    thanks to all for your comments, the problem is solved.
     
    #13
    Aussie Susan
    Super Member
    • Total Posts : 3357
    • Reward points : 0
    • Joined: 2008/08/18 22:20:40
    • Location: Melbourne, Australia
    • Status: offline
    Re: SPI ISSUE 2018/10/22 18:11:53 (permalink)
    +1 (1)
    Care to tell us what the underlying problem was and what your solution is?
    This will help others who come across this thread while searching for the same or similar issues.
    Susan
    #14
    Jump to:
    © 2018 APG vNext Commercial Version 4.5