Pic32MX SPI wil niet werken

hallo

Ik probeer SPI aan de gang te krijgen op een Pic32MX220f023b aan de hand van een code example van microchip. Maar hij wil niet werken.

De spi klok werkt wel, en hij probeert wel wat op de datalijn, maar het lijkt nergens op. Die krijg ik te zien op de usb logic analyzer (samplerate 200MHz):
https://dl.dropboxusercontent.com/u/3264324/Schermafdruk%202015-03-04%2014.26.21.png

ik ben uitgegaan van de spi code example op deze pagina. Die is gemaakt voor op de -d variant van mijn controller.

Na wat snoeien heb ik de code teruggebracht tot dit:

c code:


#include <plib.h>
#include <p32xxxx.h>
#include <proc/p32mx220f032b.h>
#include <peripheral/pps.h>
#include <peripheral/ports.h>
#include <p32xxxx.h>
#include <peripheral/spi.h>


#if defined (__32MX220F032D__) || defined (__32MX220F032B__) || (__32MX250F128D__)
// Configuration Bit settings
// SYSCLK = 48 MHz (8MHz Crystal / FPLLIDIV * FPLLMUL / FPLLODIV)
// PBCLK = 48 MHz (SYSCLK / FPBDIV)
// Primary Osc w/PLL (XT+,HS+,EC+PLL)
// WDT OFF
// Other options are don't care
#pragma config FPLLMUL = MUL_24, FPLLIDIV = DIV_2, FPLLODIV = DIV_2, FWDTEN = OFF
#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_1
#define SYS_FREQ (48000000L)
#endif

int main(void)
{
    int n;

    PPSInput(2,SDI1, RPA1);  //Assign SDI1 to pin RA1
    PPSOutput(3,RPA2,SDO1); // Set RA2 pin as output for SDO1

    SpiChannel spiChn=SPI_CHANNEL1;

    SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);

    SpiOpenFlags oFlags=SPI_OPEN_MODE8|SPI_OPEN_SMP_END;

   oFlags|=SPI_OPEN_MSTEN; // Set as Master mode in this example
   SpiChnOpen(spiChn, oFlags, 4);	

    while(1)
    {
        SpiChnPutC(spiChn, 0xAA);
        for(n=0; n<100; n++)
        {
            n++;
            n--;
        }
    }
    return 1;
}

Het enige dat dit zou moeten doen is de SPI bus openen in master mode en aan een stuk door 0xAA gaan sturen met wat delay ertussen.

Waar gaat dit fout?

alvast bedankt
timberleek

edit:
De pic is een DIP28 versie op een breadboard met alle VCC en GND lijnen aangesloten, een 100nF cap tussen VCap en gnd en een 100nF cap tussen de vcc en ground. De MCLR heeft een 10k pullup

[Bericht gewijzigd door Henry S. op woensdag 4 maart 2015 19:32:01 (0%)

Wil natuurlijk niet de spelbreker uithangen, maar aan Vcap hoort toch iets van 10uF te hangen volgens de datasheet (figuur 26-2).

Voor de rest kun je eens controleren of die RA pinnen misschien als analoge ingang staan geconfigureerd.

Als je een ICD3 gebruikt kun je beter een 1K pullup weerstand aan de MCLR pin zetten dan 10K.

Wellicht totaal niet aan de orde, maar ik schakel ook altijd de JTAG functionaliteit uit op de PIC.

Als je begint vanaf 0 met een PIC32, misschien toch leuk om een blink led project aan te maken: (in mijn geval een PIC32MX250F128B)

https://ackspace.nl/wiki/DSP_experiments

1 electron per seconde = 16 atto ampere!

Daar heb je inderdaad gelijk in, maar dat lost het probleem niet op.

Ik ben het nu aan het proberen zonder de library, maar gewoon door de registers te vullen. Oa naar de voorbeelden achter die link die je plaatste.

De knipperende led in jouw code werkt bij mij ook gelukkig.

Nu was ik aan de hand van jouw code en een print van de spi application note aan de gang gegaan om een SPI master bus te starten.

Bij elkaar kom ik dan op dit:

code:


#include <plib.h>
#include <p32xxxx.h>
#include <proc/p32mx220f032b.h>
#include <peripheral/pps.h>
#include <peripheral/ports.h>
#include <p32xxxx.h>
#include <peripheral/spi.h>

// Configuration Bit settings
// SYSCLK = 48 MHz (8MHz Crystal / FPLLIDIV * FPLLMUL / FPLLODIV)
// PBCLK = 48 MHz (SYSCLK / FPBDIV)
// Primary Osc w/PLL (XT+,HS+,EC+PLL)
// WDT OFF
// Other options are don't care
#pragma config FPLLMUL = MUL_24, FPLLIDIV = DIV_2, FPLLODIV = DIV_2, FWDTEN = OFF
#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_1
#define SYS_FREQ (48000000L)

int main(void)
{
    int i;
    char data;

    // Configure the device for maximum performance but do not change the PBDIV
    // Given the options, this function will change the flash wait states, RAM
    // wait state and enable prefetch cache but will not change the PBDIV.
    // The PBDIV value is already set via the pragma FPBDIV option above.
    SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);

    // JTAG port must be disabled.
    DDPCONbits.JTAGEN = 0;

    TRISAbits.TRISA1 = 1;           // make Ra1 pin input (SDI)
    TRISAbits.TRISA2 = 0;            // make Ra2 pin output (SDO)
    TRISBbits.TRISB14 = 0;            //make RB14 output (SCK)
   
    ANSELA = 0;           // all ports digital
    ANSELB = 0;            // all ports digital

    SYSKEY = 0x00000000;
    SYSKEY = 0xAA996655;
    SYSKEY = 0x556699AA;
    CFGCONbits.IOLOCK=0;            // unlock configuration
    CFGCONbits.PMDLOCK=0;
    
  
    SDI1R = 0b0000;            // SDI on pin RA1
    RPA2R = 0b0011;            // SDO on pin RA2
    // SCLK is connected to pin RB14 (SCK) by default
    
    CFGCONbits.IOLOCK=1;            // relock configuration
    CFGCONbits.PMDLOCK=1;
    SYSKEY = 0x00000000;

    IEC0CLR=0x03800000;            // disable all interrupts
    SPI1CON = 0;            // Stops and resets the SPI1.
    data=SPI1BUF;            // clears the receive buffer
    IFS0CLR=0x03800000;            // clear any existing event
    IPC5CLR=0x1f000000;            // clear the priority
    //interrupts aren't enabled anymore
  
    SPI1BRG=85;            //slow clock for testing
    SPI1STATCLR=0x40;              //clear status

    SPI1CON2 = 0x00000000;
    SPI1CON = 0x00008020;              //spi on, master mode

    
    while (1)
    {
        SPI1BUF = 0xAA;                //write 0xAA

        for(i = 0; i<100; i++ )            //delay loop
        {
            i++;
            i--;
        }
    }
}

Ik heb bij het commentaar telkens gezet wat er volgens mij moet gebeuren.

Het doel is weer om telkens 0xAA te versturen met een kleine delay ertussen.

Weer krijg ik de klok wel te zien, maar niks nuttigs op de datalijn. Daarmee zou ik denken dat het misschien te maken heeft met de pin mapping. Maar ik kan niet vinden waar de fout dan moet zitten.

Een bijzondere eigenschap die hij nu heeft is ook dat de spi klok veranderd als ik wat doe met de SDO lijn. Als hij enkel aan de logic analyzer hangt is hij ca 2.75kHz (ja het is traag), maar als ik een 10kOhm pullup eraan hang (ik wilde testen of hij niet toevallig als open collector geschakeld was) doet de spi unit niks meer. Maar als ik de voeding even herstart doet hij het wel weer. Enkel staat de spi clock dan op ca 47kHz. Als ik de weerstand er dan weer uittrek schiet hij direct weer terug naar ca 2.75kHz.

zonder pullup:
https://dl.dropboxusercontent.com/u/3264324/Schermafdruk%202015-03-09%2013.52.05.png
met pullup:
https://dl.dropboxusercontent.com/u/3264324/Schermafdruk%202015-03-09%2013.56.06.png

Het kan bijna niet anders dan dat ik iets heel basaals fout doe en daar steeds overheen lees. Zo moeilijk is het allemaal niet...

Mocht het uitmaken. Ik gebruik een pickit 3. Maar die koppel ik steeds af aangezien hij helemaal niet werkt zolang de pickit aangesloten is

Wat ook nog aan de hand kan wezen:

Iedere keer wanneer je iets schrijft naar je SPIxBUF, begint de SPI module een transactie. Echter, je controleert niet of deze ook afgelopen is. De volgende loop zal je SPI module dus nog steeds bezig zijn met het verzenden van je 8 bits, en dan kiep jij vrolijk de buffer weer vol.

De oplossing is om de module te vragen of hij klaar is door middel van de SPIxSTATbits.SPIBUSY te pollen. In code:

c code:


SPI1BUF = 0xaa;

while (SPI1STATbits.SPIBUSY){}; // Hier gebeurd de check of de transactie klaar is

for(i=0; i<100; i++){
 i++;
 i--;
}

In mijn code op de ACKspace link heb ik dus ondervangen door middel van interrupts te gebruiken: De SPI module genereerd een interrupt op het moment dat de module klaar is voor een nieuwe transactie.

1 electron per seconde = 16 atto ampere!

Maar die koppel ik steeds af aangezien hij helemaal niet werkt zolang de pickit aangesloten is

Ben zelf nog maar net begonnen met PIC32MX en een pickit 3 maar bovenstaande herken ik niet, ik kan de pickit3 gewoon aangesloten laten en het programma runnen, zolang ik die twee ICSP pennen niet als I/O gebruik. Lijkt toch of je in debug mode staat o.i.d. Mischien heel basic maar als je een led laat knipperen in de main loop, werkt dat dan wel goed ?

<Edit> Ik heb mijn breadboard pic32 er eens bij gepakt, dat is een PIC32MX150F128B, zelfde familie lijkt mij. Als ik mijn eigen Pragma's gebruik waarvan ik weet dat ze met een knipperled werken en jouw main code krijg ik wel een clock en data output. Zie scoop plaatje, geel is clock, blauw is data. En de PICKIT3 blijft gewoon aangesloten. De chip werkt hier op de interne 8 Mhz clock die via PLL multiply naar 48Mhz system clock gaat.

Dit is mijn initialisatie sectie, mischien heb je er wat aan als vergelijk.

c code:

// Suppress the warnings from plib.h
#define _SUPPRESS_PLIB_WARNING 1
#define _DISABLE_OPENADC10_CONFIGPORT_WARNING 1

// Include Libraries
#include <p32xxxx.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <xc.h>
#include <plib.h>
#include <GenericTypeDefs.h>
#include <string.h>

// PIC32MX150F128B Configuration Bit Settings

//* Oscillator Settings

// Use this for internal 8 Mhz FRC Oscillator
    #pragma config FNOSC    = FRCPLL        // Internal Oscillator
    #pragma config POSCMOD  = OFF           // Internal Oscillator

    #pragma config FPLLIDIV = DIV_2         // PLL input divider
    #pragma config FPLLMUL  = MUL_24        // PLL multiplier
    #pragma config FPLLODIV = DIV_2         // PLL output divider
    #pragma config FPBDIV   = DIV_1         // Peripheral bus clock divider
    #pragma config FSOSCEN  = OFF           // Secondary oscillator enable

    //* Clock control settings
    #pragma config IESO     = OFF           // Internal/external clock switchover
    #pragma config FCKSM    = CSECME        // Clock switching (CSx)/Clock monitor (CMx)
    #pragma config OSCIOFNC = OFF           // Clock output on OSCO pin enable

    //* Other Peripheral Device settings
    #pragma config FWDTEN   = OFF           // Watchdog timer enable
    #pragma config WDTPS    = PS1024        // Watchdog timer postscaler
    #pragma config WINDIS   = OFF
    #pragma config JTAGEN   = OFF           // JTAG port disabled

    //* Code Protection settings
    #pragma config CP       = OFF           // Code protection
    #pragma config BWP      = OFF           // Boot flash write protect
    #pragma config PWP      = OFF           // Program flash write protect

//*    Debug settings
    #pragma config ICESEL   = ICS_PGx1      // ICE/ICD Comm Channel Select
    //#pragma config DEBUG    = ON          // DO NOT SET THIS CONFIG BIT, it will break debugging

    #pragma config PMDL1WAY = OFF           // Allow multiple reconfigurations
    #pragma config IOL1WAY  = OFF           // Allow multiple reconfigurations

[Bericht gewijzigd door Rolo op maandag 9 maart 2015 19:43:07 (74%)

timberleek meldt dat de blink led demo wel werkt. Hoewel ik het ook raar vind dat de MCU niets doet zolang de programmer is aangesloten.

1 electron per seconde = 16 atto ampere!
Arco

Special Member

Staat de reset optie van de Pickit soms aan? (target blijft dan na programmeren in reset state)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Op 9 maart 2015 17:34:21 schreef Dweil:
Wat ook nog aan de hand kan wezen:

Iedere keer wanneer je iets schrijft naar je SPIxBUF, begint de SPI module een transactie. Echter, je controleert niet of deze ook afgelopen is. De volgende loop zal je SPI module dus nog steeds bezig zijn met het verzenden van je 8 bits, en dan kiep jij vrolijk de buffer weer vol.

Vandaar ook de delay loop. In de screenshot zie je mooi wat ruimte zitten tussen de transmissies. Dat leek me voor de eerste test wel even voldoende. Maar ik zal die test even toevoegen. Dat is natuurlijk wel hoe het hoort.

Interrupts wil ik uiteindelijk ook wel gaan gebruiken, maar ik wou het stapje voor stapje gaan doen.

Op 9 maart 2015 17:41:04 schreef Rolo:
[...]

Ben zelf nog maar net begonnen met PIC32MX en een pickit 3 maar bovenstaande herken ik niet, ik kan de pickit3 gewoon aangesloten laten en het programma runnen, zolang ik die twee ICSP pennen niet als I/O gebruik. Lijkt toch of je in debug mode staat o.i.d. Mischien heel basic maar als je een led laat knipperen in de main loop, werkt dat dan wel goed ?

Tja ik ken het ook niet. De ICSP pennen worden verder niet gebruikt. Het enige wat ik me net nog bedacht is dat het misschien te maken zou hebben met een groundloop oid. De pickit hing aan een vaste pc en de logic analyzer aan mijn laptop.

Ik zal de pickit instellingen nog eens goed doorlopen (ook voor de reset lijn die genoemd was)

<Edit> Ik heb mijn breadboard pic32 er eens bij gepakt, dat is een PIC32MX150F128B, zelfde familie lijkt mij. Als ik mijn eigen Pragma's gebruik waarvan ik weet dat ze met een knipperled werken en jouw main code krijg ik wel een clock en data output.

Kijk daar kan ik wat mee. Dan ga ik eens hetzelfde proberen.

Het euvel is verholpen.

Het probleem lag hem inderdaad in de config bits. Met de configuratie van Rolo werkt hij direct. En dan werkt hij ook gewoon met de pickit eraan.

Grappig om te zien hoe zo'n fout zich manifesteert. Je zou denken dat de chip dan gewoon niet werkt, maar hij werkt dan dus gewoon half.

Maar heel erg bedankt voor de hulp