Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

SPI issues (problems, timing, etc)

Status
Not open for further replies.
Hello and thank you always for your help. Very much appreciated

I am now setting up a system that uses SPI. Now, as you can see in my past threads, I haven't been exactly successful at SPI. I couldnt solve a problem last time I tried to implement SPI.

Anyway, now, with a different system I am having a problem and I suspect it is the SPI part of it specifically the clock, although frankly it can be anything (you can read about it at the end of the post)

My main question here is: When connecting a micro with a device through SPI, I know you have to set the micro SPI parameters to what the device uses. SPI mode, datasize, etc. But do you also have to set the rate??? I thought the slave follows the clock that the master set through SCK so I can set the master at any rate but apparently not. Why??

My PIC (as a master) can set its speed at : Fosc/4 , Fosc/ 16, Fosc/64 and TMR2 output/2 .
My Fosc is now ummmm 16MHz I think... (I say I think because I am using PLL which sets the speed of the micro to 64MHz... so maybe this is the Fosc???)

Now, the device I want to use is the
https://www.waveshare.com/w/upload/9/98/XPT2046-EN.pdf

I am re-reading this datasheet and it says: that the A/D converter is a 12-bit 125KHz one. So maybe that is what I am doing wrong??

My head now is full of confusion so I would appreciate any help, advice or comment

Thanks
-----------------



The system I am doing is a PIC18F45K20 connected to a TFT LCD with touch panel. the touch panel uses the XPT2046 with a SPI interface. Right now the LCD is working fine but the touch panel is not. Apparently the micro detect that the panel has been touched (through a non-SPI pin) but can not find the correct X,Y position. I ve tried debugging it and reduce the problem to the SPI communication part. It seems the values returned are not correct or logical. Debugging is also not very useful, since it doesnt work very well.
 
The data sheet you linked to is not clear!
It is better to be slow. Set the SPI clock rate slow and try to talk.
I think the XPT2046 is slower than the LCD panel.
 
Agree with Ron, from the digital timing interface diagram (pg26), the max SPI clock frequency you can have is 2.5MHz. I wouldn't even try go near that.
 
FOUND the problem sorry! It was a bad cable!

I am sorry, I was refering to the problem of this post!

I still have the timing problem!:arghh:

---------------------------------------------------

I tried to write a very simple SPI program to communicate two 18F45K20. It doesnt work (I wrote that for 18F2550 some months ago and it used to work)
At first I thought the master was wrong but viewing it with a oscilloscope I can see the master is working. (Although I have no idea how come the clock is running at 125KHz)
lm13000.jpg
There you can see that the CLK (green) is working, the SDO (yellow) gives the correct data, the CS(blue) is being driven to 0 (although at first I wanted to do it every three transmissions) but the SDI (red) is not working at all.
I have read and reread the code and I cant find what is wrong. I would appreciate very much if someone can take a look please

Code:
#include <stdio.h>
#include <stdlib.h>
#include "configuration.h"

#define  _XTAL_FREQ 64000000      // 64MHz for the delay function

void CPU_Init()
{
  // first we select the appropriate preescaler
    OSCCON |= 0x70; //Select 16MHz as Internal Oscillator IRCF<2:0>=111
// Then use the PLL to multiply this by 4 (16x4= 64MHz)
    OSCTUNEbits.PLLEN=1; //PLL (x4) enabled

    TRISB=0x00;  // to enable the LEDs
}

void delay_ms(unsigned int ms)
{
   unsigned long int index=0;


   for(index=0;index<ms;index++)
       __delay_ms(1);


}
//------------Some LEDs for output
#define GREEN_LED LATBbits.LATB0
#define RED_LED   LATBbits.LATB1



//--------------SPI FUNCTIONS --------------------------
// These are the functions in charge of initializing and using the spi functions


#define CS_PIN     LATAbits.LATA5    //Chip Select

void spi_master_init ( void );
unsigned char spi_data ( unsigned char tx_data );
unsigned char spi_read_data;

#define DATA_A  0x90  //1001 0000
#define DATA_B  0xD0  // 1101 0000
#define DATA_C  0x00

int main(int argc, char** argv)
{
    CPU_Init();
    spi_master_init();

    RED_LED=0;
    GREEN_LED=0;

    while(1)
    {
       // CS_PIN=0;
        delay_ms(1);
        spi_read_data=spi_data(DATA_A);

        if(spi_read_data!=DATA_C)
              { RED_LED=1;
              GREEN_LED=0;
              }
        else  { RED_LED=0;
              GREEN_LED=1;
              }
        delay_ms(1);
        spi_read_data=spi_data(DATA_B);

        if(spi_read_data!=DATA_A)
              { RED_LED=1;
              GREEN_LED=0;
              }
        else  { RED_LED=0;
              GREEN_LED=1;
              }

        delay_ms(1);
        spi_read_data=spi_data(DATA_C);

        if(spi_read_data!=DATA_B)
              { RED_LED=1;
              GREEN_LED=0;
              }
        else  { RED_LED=0;
              GREEN_LED=1;
              }


//        CS_PIN=1;

        delay_ms(10);
    }//while 1

    return (EXIT_SUCCESS);
}


void spi_master_init ( void )
{
     SSPSTAT = 0x00;
     SSPCON1 = 0x22;

    TRISC &= 0xD7;   // 1101 0111  MO cleared CLK cleared
    TRISA &= 0xDF;      //  1101 1111  CS cleared
    //TRISB |= 0x01;        // 0000 0001   IRQ_PIN set

    //Disabling the chip
    CS_PIN=1;

    ADCON0 = 0x38;
     ADCON1= 0x00;


}
//WARNING: This function DOES NOT select the chip. This has to do from OUTSIDE<--- Not anymore
//actually it does now!!!
unsigned char spi_data ( unsigned char tx_data )
{
    char data_read;

    CS_PIN=0;

   //do{  SSPCON1bits.WCOL=0;
    SSPBUF=tx_data;  // put the data in the SSPBUF register which going to be send
    //}while(SSPCON1bits.WCOL);  //to check if the buffer is empty (not collisions)

   while( !SSPSTATbits.BF );  // wait until the all bits received

   CS_PIN=1;

   data_read=SSPBUF;
   return data_read;

}

the slave

Code:
#include <stdio.h>
#include <stdlib.h>
#include "configuration.h"



void CPU_Init()
{
  // first we select the appropriate preescaler
    OSCCON |= 0x70; //Select 16MHz as Internal Oscillator IRCF<2:0>=111
// Then use the PLL to multiply this by 4 (16x4= 64MHz)
    OSCTUNEbits.PLLEN=1; //PLL (x4) enabled

   // TRISB=0x00;  // to enable the LEDs
}

//--------------SPI FUNCTIONS --------------------------
// These are the functions in charge of initializing and using the spi functions
void spi_slave_init ( void );
unsigned char spi_data ( unsigned char tx_data );

unsigned char spi_read_data;

int main(int argc, char** argv) {

    CPU_Init();
    spi_slave_init (); // initialize the slave

    while(1)
      {
       while ( !SSPSTATbits.BF );           // wait until the all bits received
       spi_read_data = SSPBUF; // read the received data from the buffer
       SSPBUF = spi_read_data;   // put the data in the SSPBUF register which will get transmitted on master's clock
      }





    return (EXIT_SUCCESS);
}


void spi_slave_init ( void )
{
SSPSTAT = 0x00; // SMP=0(slave mode),CKE=0(transmission on Idle to active clock state),all other bits 0
SSPCON1 = 0x24; // SSPEN=1(Enable SPI),SSPM[3-0]=0100(SPI Slave mode,clock=SCKpin,SSpin control enabled)

TRISC &= 0xDF;   // 1101 1111  MO cleared
TRISC |= 0x08;   //  0000 1000  CLK set
TRISA |= 0x20;   //  0010 0000  CS set

ADCON0 = 0x38;
ADCON1= 0x00;
ANSEL= 0x00; //enable digital use of A
}
// this function is not used
unsigned char spi_data ( unsigned char tx_data )
{
char data_read;

while ( !SSPSTATbits.BF );        // wait until the all bits received
data_read = SSPBUF; // read the received data from the buffer
SSPBUF = tx_data;  // put the data in the SSPBUF register which will get transmitted on master's clock

return data_read;
}

the configuration.h file
Code:
#ifndef CONFIGURATION_H
#define    CONFIGURATION_H

#ifdef    __cplusplus
extern "C" {
#endif

#include <xc.h>
// PIC18F45K20 Configuration Bit Settings
// 'C' source line config statements

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG1H
#pragma config FOSC = INTIO67   // Oscillator Selection bits (Internal oscillator block, port function on RA6 and RA7)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = SBORDIS  // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 18        // Brown Out Reset Voltage bits (VBOR set to 1.8 V nominal)

// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer Enable bit (WDT is controlled by SWDTEN bit of the WDTCON register)
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = PORTC   // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config HFOFST = ON      // HFINTOSC Fast Start-up (HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize.)
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF             // Single-Supply ICSP Enable bit (Single-Supply ICSP Disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection Block 0 (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection Block 1 (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF        // Code Protection Block 2 (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF        // Code Protection Block 3 (Block 3 (006000-007FFFh) not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection Block 0 (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection Block 1 (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF       // Write Protection Block 2 (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF       // Write Protection Block 3 (Block 3 (006000-007FFFh) not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection Block 0 (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection Block 1 (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection Block 2 (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection Block 3 (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot Block (000000-0007FFh) not protected from table reads executed in other blocks)




#ifdef    __cplusplus
}
#endif

#endif    /* CONFIGURATION_H */

thanks again!
 
Last edited:
Status
Not open for further replies.

Latest threads

Back
Top