• AVR Freaks

Hot!PIC18F47K42 SPI Issues

Author
davez
Starting Member
  • Total Posts : 44
  • Reward points : 0
  • Joined: 2015/12/11 01:04:29
  • Location: 0
  • Status: offline
2020/11/11 14:16:06 (permalink)
0

PIC18F47K42 SPI Issues

Hello All,
I have been strugling with the SPI on an 18F47K42. I need to comunicate with an ILI9341 Display, and a Maxim 31856 Thermocouple converter. I currently have the project running perfectly on a 18F46K22, with the exception that I would prefer the 12 bit ADC of the K42 over the 10 bit ADC of the K22.
With the combination of the Maxim chip, and the ILI9341, I found (on the 46K22) I needed to set CKP to Idle High, CKE to transmit on Idle to Active, and SDI Data sampled at the end of Output data.
 
I have set the registers for my SPI as I believe to be correct, but, the SPI in the 47K42 seems to be a fair bit more configurable than the K22 family. I have tried many, many, different settings, but, cannot seem to get the display to do anything other than light the backlight.
 
I am fairly confident the issue is with the SPI initialization setting, but, it is so different from the K22 family, I seem unable to wrap my little brain around all the differences.
 
 
I am using thie following code for 8 bit data exchanges. (using multiple exchanges when I read the thermocouple converter)

 
#include    "system.h"
#include    "spi1.h"

#define SPI_RX_IN_PROGRESS 0x0

void SPI1_Init(void)
{
    SPI1CON0    = 0x00;        // disable SPI

    SPI1BAUD    = 0x07;        // FOSC/(2*(SP1BAUD +1)=4 MHz with FOSC=64 MHz
    SPI1CLK     = 0x00;        // CLKSEL FOSC;

    SPI1CON1    = 0x80;         // SMP - End, CKE - Idle to active, CKP - Idle High, FST - disabled set at 0, SS - active high, SDIP - active high, SDOP - active high;
    SPI1CON2    = 0x01;

    SPI1TWIDTH  = 0x00;         //8 bit transfer WIDTH
    SPI1CON0    = 0x82;         // EN - enabled, LSBF - MSb first, MST - bus master, BMODE - last byte
}


uint8_t SPI1_Transfer(uint8_t data)
{
    SPI1TCNTL = 1;
    SPI1TXB = data;

    while(PIR2bits.SPI1RXIF == SPI_RX_IN_PROGRESS)
    {
    }

    return (SPI1RXB);
}

 
and my Pin settings
 

 
 
 
void pinManagerInitialize(void)
{
    TRISA  = 0x07;                  // RA0,1,2, as Inputs
    PORTA  = 0;
    ANSELA = 0x0F;                  // AN0,1,& 2 as Analog inputs
    
    TRISB  = 0x02;                  // RB1 as input
    PORTB  = 0;
    ANSELB = 0;
    
    TRISC  = 0x10;
    PORTC  = 0;
    ANSELC = 0;
    
    TRISD  = 0xC0;                  // D6 & D7 as Input for DataReady & Fault on Maxim 31856
    PORTD  = 0xC0;
    ANSELD = 0;
    
    TRISE  = 0;
    PORTE  = 0;
    ANSELE = 0;
    
    //WPUx registers
    WPUD = 0x00;
    WPUE = 0x00;
    WPUB = 0x00;
    WPUA = 0x00;
    WPUC = 0x00;

//    ODx registers

    ODCONE = 0x00;
    ODCONA = 0x00;
    ODCONB = 0x00;
    ODCONC = 0x00;
    ODCOND = 0x00;

//    SLRCONx registers

    SLRCONA = 0x00;                     //disable Slew Rate Control
    SLRCONB = 0x00;
    SLRCONC = 0x00;
    SLRCOND = 0x00;
    SLRCONE = 0x00;

    SPI1SCKPPS = 0x13;                  //RC3->SPI1:SCK1;    
    RC3PPS = 0x1E;                      //RC3->SPI1:SCK1;    
    RC5PPS = 0x1F;                      //RC5->SPI1:SDO1;    
    SPI1SDIPPS = 0x14;                  //RC4->SPI1:SDI1;    
}
 
 
 

 
And my config file
 

 
#pragma config FEXTOSC = OFF    // External Oscillator Selection (EC (external clock) above 8 MHz; PFM set to high power)
#pragma config RSTOSC = HFINTOSC_64MHZ// Reset Oscillator Selection (HFINTOSC with HFFRQ = 64 MHz and CDIV = 1:1)

// CONFIG1H
#pragma config CLKOUTEN = OFF   // Clock out Enable bit (CLKOUT function is disabled)
#pragma config PR1WAY = ON      // PRLOCKED One-Way Set Enable bit (PRLOCK bit can be cleared and set only once)
#pragma config CSWEN = OFF      // Clock Switch Enable bit (The NOSC and NDIV bits cannot be changed by user software)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)

// CONFIG2L
#pragma config MCLRE = EXTMCLR  // MCLR Enable bit (If LVP = 0, MCLR pin function is port defined function; If LVP =1, RE3 pin fuction is MCLR)
#pragma config PWRTS = PWRT_OFF // Power-up timer selection bits (PWRT is disabled)
#pragma config MVECEN = ON      // Multi-vector enable bit (Multi-vector enabled, Vector table used for interrupts)
#pragma config IVT1WAY = ON     // IVTLOCK bit One-way set enable bit (IVTLOCK bit can be cleared and set only once)
#pragma config LPBOREN = OFF    // Low Power BOR Enable bit (ULPBOR enabled)
#pragma config BOREN = SBORDIS  // Brown-out Reset Enable bits (Brown-out Reset enabled , SBOREN bit is ignored)

// CONFIG2H
#pragma config BORV = VBOR_2P45 // Brown-out Reset Voltage Selection bits (Brown-out Reset Voltage (VBOR) set to 2.45V)
#pragma config ZCD = OFF        // ZCD Disable bit (ZCD disabled. ZCD can be enabled by setting the ZCDSEN bit of ZCDCON)
#pragma config PPS1WAY = ON     // PPSLOCK bit One-Way Set Enable bit (PPSLOCK bit can be cleared and set only once; PPS registers remain locked after one clear/set cycle)
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config DEBUG = OFF      // Debugger Enable bit (Background debugger disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Extended Instruction Set and Indexed Addressing Mode disabled)

// CONFIG3L
#pragma config WDTCPS = WDTCPS_31// WDT Period selection bits (Divider ratio 1:65536; software control of WDTPS)
#pragma config WDTE = OFF        // WDT operating mode (WDT enabled regardless of sleep)

// CONFIG3H
#pragma config WDTCWS = WDTCWS_7// WDT Window Select bits (window always open (100%); software control; keyed access not required)
#pragma config WDTCCS = LFINTOSC// WDT input clock selector (WDT reference clock is the 31.0 kHz LFINTOSC)

// CONFIG4L
#pragma config BBSIZE = BBSIZE_512// Boot Block Size selection bits (Boot Block size is 512 words)
#pragma config BBEN = OFF       // Boot Block enable bit (Boot block disabled)
#pragma config SAFEN = OFF      // Storage Area Flash enable bit (SAF disabled)
#pragma config WRTAPP = OFF     // Application Block write protection bit (Application Block not write protected)

// CONFIG4H
#pragma config WRTB = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-30000Bh) not write-protected)
#pragma config WRTC = 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)
#pragma config WRTSAF = OFF     // SAF Write protection bit (SAF not Write Protected)
#pragma config LVP = ON         // Low Voltage Programming Enable bit (Low voltage programming enabled. MCLR/VPP pin function is MCLR. MCLRE configuration bit is ignored)

// CONFIG5L
#pragma config CP = OFF         // PFM and Data EEPROM Code Protection bit (PFM and Data EEPROM code protection disabled)

// CONFIG5H
 
 
 
#include    "system.h"

void systemInitialize(void)
{
    OSCILLATOR_Initialize();
    pinManagerInitialize();
    SPI1_Init();
    TFT_Init(TFT_VERTICAL);
    ADC_Initialize();
    TFT_SetFont(Ariel_Narrow_12,0);
    TMR0_Initialize();
    TMR2_Initialize();
    PWM1_Initialize();
    PWM3_Initialize();
    PWM5_Initialize();
    maxim_31856_init();
}

void OSCILLATOR_Initialize(void)
{
    // NOSC HFINTOSC; NDIV 1;
    OSCCON1 = 0x60;
    // CSWHOLD may proceed; SOSCPWR Low power;
    OSCCON3 = 0x00;
    // MFOEN disabled; LFOEN disabled; ADOEN disabled; SOSCEN disabled; EXTOEN disabled; HFOEN disabled;
    OSCEN = 0x00;
    // HFFRQ 64_MHz;
    OSCFRQ = 0x08;
    // TUN 0;
    OSCTUNE = 0x00;
}


 
 
 

 
Any help would be appreciated
TIA
Dave
post edited by davez - 2020/11/11 15:04:43
#1

10 Replies Related Threads

    Aussie Susan
    Super Member
    • Total Posts : 3808
    • Reward points : 0
    • Joined: 2008/08/18 22:20:40
    • Location: Melbourne, Australia
    • Status: offline
    Re: PIC18F47K42 SPI Issues 2020/11/11 18:53:48 (permalink)
    -1 (1)
    Firstly, do you really need those extra 2 ADC bits? I suspect that they could mostly be noise. 10 bits is already measuring to about 1000th of the ADC range.
    Also, you need to look at the SPI slave to see what it is expecting in terms of the CKP, CKE and SMP settings - you can't guess these things. However if you say you have the previous chip working perfectly, then you only need to copy those settings.
    To get things working, can you try a slower clock speed? Also can you check the waveforms with a 'scope to make sure they look OK?
    I assume that you are using the 4-wire 8-bit SPI interface for the display as you are only sending 8 bits - but you don't show us how the 'SPI1_Transfer()' function is called with the manipulation of the CSX and the D/CX pins.
    Not your issue at this time but I recommend that you do NOT set the DEBUG config value - leave that to the IDE depending on the type of build you use.
    Susan
    #2
    oliverb
    Super Member
    • Total Posts : 369
    • Reward points : 0
    • Joined: 2009/02/16 13:12:38
    • Location: 0
    • Status: offline
    Re: PIC18F47K42 SPI Issues 2020/11/12 03:07:37 (permalink)
    0
    FWIW I presume you are actually measuring something else apart from the thermocouple?
     
    Given that the MAX31856 has a digital output its resolution will be independant of the PIC's ADC resolution.
     
    Also there are plenty of good reasons for wanting 12 bits of resolution. I have an application that is measuring a parameter with several spans up to 0-1000, and currently the span is set in analogue. If I do the scaling in math with a 10 bit ADC the scaling will be uneven due to rounding, favoring some values. If I use 12 bit then the conversion will look much more smooth.
    #3
    davez
    Starting Member
    • Total Posts : 44
    • Reward points : 0
    • Joined: 2015/12/11 01:04:29
    • Location: 0
    • Status: offline
    Re: PIC18F47K42 SPI Issues 2020/11/12 10:41:38 (permalink)
    +1 (1)
    Aussie Susan
    Firstly, do you really need those extra 2 ADC bits? I suspect that they could mostly be noise. 10 bits is already measuring to about 1000th of the ADC range.

    Do I need the extra bits of resolution, not desperately with the current project, but they would give more meaningful numbers. This project doesn't really need them, but a different project may in the future. I would like to move from the 46K22 to the 47K42 for this, and future projects, but, cannot without the ability to make the SPI work.
     
    Aussie Susan
    Also, you need to look at the SPI slave to see what it is expecting in terms of the CKP, CKE and SMP settings - you can't guess these things. However if you say you have the previous chip working perfectly, then you only need to copy those settings.

     
    I did look for a combination of parameters  (for SMP, CKE, and CKP) that were required to get both the display and TC converter to function correctly on the 46K22. I set the same parameters  (but, in different registers) on the 47K42, (without "guessing"), but with so many additional setting to be made in the 47K42, I am having difficulty determining what will work.
     
    Aussie Susan
    To get things working, can you try a slower clock speed? Also can you check the waveforms with a 'scope to make sure they look OK?

     
    I did put a scope on a few weeks ago, the Clock was outputting correctly, but, the data on the SDO was always the same value. I do not remember what that value was, but, I can recheck, and post the results. ( I had the clock at 2 MHz, it still didn't function, I can try slower yet)
     
    Aussie Susan
    I assume that you are using the 4-wire 8-bit SPI interface for the display as you are only sending 8 bits - but you don't show us how the 'SPI1_Transfer()' function is called with the manipulation of the CSX and the D/CX pins.

     
    //==============================================================================
    // Write a command.
    //==============================================================================
    void TFT_WriteCommand(uint8_t command)
    {   
        TFT_CS=0;
        TFT_DC=0; // When DCX = ’0’, command is selected.
        junk=SPI1_Transfer(command);
        TFT_CS=1;
    }

    //==============================================================================
    // Write a Parameter.
    //==============================================================================
    void TFT_WriteParameter(uint8_t parameter)
    {   
        TFT_CS=0;
        TFT_DC=1; // When DCX = ’1’, data is selected.
        junk=SPI1_Transfer(parameter);
        TFT_CS=1;
    }



    Not your issue at this time but I recommend that you do NOT set the DEBUG config value - leave that to the IDE depending on the type of build you use.
    Susan

     
    I assume you are referencing the Line:
    #pragma config DEBUG = OFF      // Debugger Enable bit (Background debugger disabled)
     
    I do not have it set, that line was created by generating config bits in the IDE, just didn't bother deleting the line.
     
     
    #4
    davez
    Starting Member
    • Total Posts : 44
    • Reward points : 0
    • Joined: 2015/12/11 01:04:29
    • Location: 0
    • Status: offline
    Re: PIC18F47K42 SPI Issues 2020/11/12 11:13:08 (permalink)
    0
    oliverb
    FWIW I presume you are actually measuring something else apart from the thermocouple?
     
    Given that the MAX31856 has a digital output its resolution will be independant of the PIC's ADC resolution.
     
    Also there are plenty of good reasons for wanting 12 bits of resolution. I have an application that is measuring a parameter with several spans up to 0-1000, and currently the span is set in analogue. If I do the scaling in math with a 10 bit ADC the scaling will be uneven due to rounding, favoring some values. If I use 12 bit then the conversion will look much more smooth.


    Yes, I do a median select on the temperature measurements from 3 thermister inputs.  I only have a span of 300, but, like you say, with rounding and truncating, the resultant values sometimes look a little suspect. (The floating point result from the Steinhart Hart equation was multiplied by 10, before being cast as a signed 16 bit int, then a "fake" decimal point inserted into the output to the display, to make an int read to 1/10 of a degree.)
     
    This resulted in an obvious sort of pattern when the temperature was stable, where you could see the result of the  "steps" of ADC resolution as the display sometimes flickered back and forth between 2 fractional values that were more than 1/10th degree apart.
     
    For now, I just dropped the extra digit, and display temperature to the nearest degree.
    The extra digit may seem extraneous, but it is a very slow moving process (a pit temperature controller in a charcoal smoker, using 10K thermister Food probes. Nearing the end of a cook, it can take a half hour or more to come up 1 degree in food temperature, and knowing whether you are at 202.1 degrees, or 202.9 degrees can be important when you are aiming for 203 degrees.)
    post edited by davez - 2020/11/12 11:14:48
    #5
    davez
    Starting Member
    • Total Posts : 44
    • Reward points : 0
    • Joined: 2015/12/11 01:04:29
    • Location: 0
    • Status: offline
    Re: PIC18F47K42 SPI Issues 2020/11/12 16:18:14 (permalink)
    0


    To get things working, can you try a slower clock speed? Also can you check the waveforms with a 'scope to make sure they look OK?
    Aussie Susan



    I tried slowing things waaay down, using a Baud rate of 255, giving me a SPI clock of 125KHz, no change.
     
    Put a scope on the SCK pin and the SDO pin, all I get is a repeating Value of 11001011, see attached picture of Scope sweep. Blue trace is SCK, Red is SDO.
    post edited by davez - 2020/11/12 16:20:08

    Attached Image(s)

    #6
    davea
    Super Member
    • Total Posts : 586
    • Reward points : 0
    • Joined: 2016/01/28 13:12:13
    • Location: Tampa Bay FL USA
    • Status: offline
    Re: PIC18F47K42 SPI Issues 2020/11/12 17:38:50 (permalink)
    0
    I would try sending 2 8bit counters 
    junk=SPI1_Transfer(cnt1--);
    junk=SPI1_Transfer(cnt2++);
    to find if it's before or after the function call
    #7
    davez
    Starting Member
    • Total Posts : 44
    • Reward points : 0
    • Joined: 2015/12/11 01:04:29
    • Location: 0
    • Status: offline
    Re: PIC18F47K42 SPI Issues 2020/11/12 19:23:32 (permalink)
    0
    davea
    I would try sending 2 8bit counters 
    junk=SPI1_Transfer(cnt1--);
    junk=SPI1_Transfer(cnt2++);
    to find if it's before or after the function call


    So, if I understand, modify my code from this

    void TFT_WriteParameter(uint8_t parameter)
    {   
        TFT_CS=0;
        TFT_DC=1; // When DCX = ’1’, data is selected.
        junk=SPI1_Transfer(parameter);
        TFT_CS=1;
    }

     
    to this?

    void TFT_WriteParameter(uint8_t parameter)
    {   
        TFT_CS=0;
        TFT_DC=1; // When DCX = ’1’, data is selected.
        junk=SPI1_Transfer(cnt1--);
        junk=SPI1_Transfer(parameter);
        junk=SPI1_Transfer(cnt2++);
        TFT_CS=1;
    }

     
    Then look you cnt1 and cnt2 on the scope?
    Or check the variables to see if they are counting up and down?
    #8
    davea
    Super Member
    • Total Posts : 586
    • Reward points : 0
    • Joined: 2016/01/28 13:12:13
    • Location: Tampa Bay FL USA
    • Status: offline
    Re: PIC18F47K42 SPI Issues 2020/11/12 21:21:12 (permalink)
    0
    on the scope to see if data is changing  
    might as well do both...
    post edited by davea - 2020/11/12 21:44:56
    #9
    davez
    Starting Member
    • Total Posts : 44
    • Reward points : 0
    • Joined: 2015/12/11 01:04:29
    • Location: 0
    • Status: offline
    Re: PIC18F47K42 SPI Issues 2020/12/01 10:47:57 (permalink)
    +1 (3)
    So, turned out to be a simple problem, I soldered up another board, with a new processor, loaded my code in, & it works. Turns out the SPI peripheral in the first processor was faulty. Putting a scope on it, it seemed to kind of work, but, just kept spitting out the same byte, over and over. (No matter the byte I sent, the scope always showed the same byte pattern)
    #10
    RISC
    Super Member
    • Total Posts : 5907
    • Reward points : 0
    • Status: offline
    Re: PIC18F47K42 SPI Issues 2020/12/01 17:05:52 (permalink)
    +1 (1)
    Hi,
    Could it be that you had 2 different silicon versions of the PIC18F47K42 ?
    When you connect to your board using a programming tool some information is displayed in the output window from MPLAB X : "Device Revision Id = xxxxxxxxxxxxx"
    Is it the same for both PIC18F47K42 ?
    Regards

    For support make sure to check first here : http://microchipdeveloper.com
    There are hundreds of PIC, AVR, SAM...which one do YOU use ?
    #11
    Jump to:
    © 2021 APG vNext Commercial Version 4.5