This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

I/O Ports & SPI bus on c8051f120

Hello,
I've configured SPI bus on P0.2 (SCLK), P0.3(MISO), P0.4 (MOSI) and P0.5 (NSS) but on these ports: no signal. Normaly, I should have SPI clock at least but I have nothing.

I've configured :

1) Pins:

sbit SPI_SCLK=P0^2;     // SPI clock on P0.2
sbit SPI_MISO=P0^3;     // Master In/Slave Out on P0.3
sbit SPI_MOSI=P0^4;     // Master Out/Slave In on P0.4
sbit SPI_NSS=P0^5;      // Slave Select on P0.5

2) Ports:

void port_init (void)
{
         char sfrpage_save = SFRPAGE;     // Save current page of SFR

     SFRPAGE = CONFIG_PAGE;           // Load config_page

         WDTCN = 0xde;
         WDTCN = 0xad;                    // Disable watchdog timer

     XBR0 = 0x02;          // Enable SPI bus
     XBR1 = 0x00;          // Enable /INT0 and /INT1
     XBR2 = 0x40;          // Enable Crossbar and weak pull-up

         P0MDOUT |= 0x3C;          // P0.5, P0.4, P0.3 and P0.2 are outputs (for SPI datas)
         P0 = 0x3C;

     SFRPAGE = sfrpage_save;          // Restore SFR page
}

3) SPI bus:

void config_SPI (void)
{
     char sfrpage_save = SFRPAGE;     // Save current SFR page

     SFRPAGE = SPI0_PAGE;             // Load SPI page

     SPI0CFG |= 0x40;                 // Master Mode Enable
     SPI0CN  |= 0x8D;                 // Slave select and enable SPI
     SPI0CKR  = 0x01;                 // SYSCLK/2

     SFRPAGE = sfrpage_save;          // Restore SFR page

}

I have tried many times to resolve the problem but without satisfaction for the moment.

If you can help me, make it please.
Thanks.

Manu

Parents
  • Just to make sure, we're talking the C8051F120 here:

    SPI0CN  |= 0x8D;
    

    Looks just plain wrong.
    8D would be 1000 1101 So you're setting the SPI0 interrupt flag high? You should let the hardware set that.

    XBR1 = 0x00;          // Enable /INT0 and /INT1
    

    Nothing is enabled from this set.
    You want XBR1 to be 0x14 for /INT0 and /INT1 to be enabled and available at external port pins.

    So you're current set just has the SPI0 peripheral enabled (and NOT /INT0 or /INT1)

    Ahhhh, but here's your port mappings:

    SCK  -> P0.0
    MISO -> P0.1
    MOSI -> P0.2
    NSS  -> P0.3
    

    If you consider the Port pins in order, P0.0 to P3.7, the crossbar takes them in a priority order, and assigns the pins P0.0 to P3.7. Hard for me to actually list the order here, but UART0 comes in at the highest priority, and SPI0 at 2. Without UART0 in there, SPI0 will get assigned to P0.0 through P0.3. See figure 18.2 in the datasheet (as of Rev 1.3 of the datasheet) for priority order.

    If you really want SPI0 on P0.2, you'll have to enable UART0 on the crossbar (which means you will loose P0.0 and P0.1 for general purpose I/O)

    UART0 and SPI0 on the crossbar is

    XBR0 = 0x06;
    

    This you may already know, but SCK will be low when the SPI0 peripheral is idle. So you won't "see" it high with an oscilloscope if you aren't actively using the bus.

Reply
  • Just to make sure, we're talking the C8051F120 here:

    SPI0CN  |= 0x8D;
    

    Looks just plain wrong.
    8D would be 1000 1101 So you're setting the SPI0 interrupt flag high? You should let the hardware set that.

    XBR1 = 0x00;          // Enable /INT0 and /INT1
    

    Nothing is enabled from this set.
    You want XBR1 to be 0x14 for /INT0 and /INT1 to be enabled and available at external port pins.

    So you're current set just has the SPI0 peripheral enabled (and NOT /INT0 or /INT1)

    Ahhhh, but here's your port mappings:

    SCK  -> P0.0
    MISO -> P0.1
    MOSI -> P0.2
    NSS  -> P0.3
    

    If you consider the Port pins in order, P0.0 to P3.7, the crossbar takes them in a priority order, and assigns the pins P0.0 to P3.7. Hard for me to actually list the order here, but UART0 comes in at the highest priority, and SPI0 at 2. Without UART0 in there, SPI0 will get assigned to P0.0 through P0.3. See figure 18.2 in the datasheet (as of Rev 1.3 of the datasheet) for priority order.

    If you really want SPI0 on P0.2, you'll have to enable UART0 on the crossbar (which means you will loose P0.0 and P0.1 for general purpose I/O)

    UART0 and SPI0 on the crossbar is

    XBR0 = 0x06;
    

    This you may already know, but SCK will be low when the SPI0 peripheral is idle. So you won't "see" it high with an oscilloscope if you aren't actively using the bus.

Children
  • Thanks!

    For the interrupts, it's due to the fact that I put off this to test my program only with SPI bus.
    For the rest, thank you very much. I'll test my program with your explanations and I keep you informed.

  • Ormond,

    I tried it but I have again the same problem : I have nothing on the pins of the c8051f120. For me, all is configured.. Ormon, erik or someone can help me? Please!

    Manu

  • I have nothing on the pins of the c8051f120
    the f12x/f13x datasheet chapter 18 and the comments in the code generated by config2.

    Erik

  • Yeah I've already configured the ports, activate the digital crossbar, initialized SPI bus and Clock. I don't find the solution...
    I don't use the SPI interrupt, is it important? For what is used it?
    Manu

  • I put off this to test my program only with SPI bus
    excellent, however for the SILabs f12x do not change the crossbar when you 'reduce' the code for test

    I don't use the SPI interrupt, is it important? For what is used it?
    Do you need to?, no, is it important? yes. If you do not use the interrupt your program will either be totally tied up during SPI action or you may lose SPI info.

    The worst affliction any uC programmer can have is interruptifobia.

    Erik

  • I've tested the port 0 pins, I've made a program : TEST = P0.2;
    and in this program I made : while(1){TEST = ~TEST};
    Does that mean that this port 0 is not damaged?

  • The worst affliction any uC programmer can have is interruptifobia.

    Even worse than largememorymodeleuforia?

  • sticktolanguagephilia

    "It must ALL be in C" or "It must ALL be in assembler"

    Erik

  • Are you actually trying to USE the SPI when testing it?
    Can you post your current code?

    If P0_2 = 1 works, that doesn't mean much. The system is laid out such that one of the last things is the port latches. The crossbar and the SPI controller are behind the port latches. In fact, attempting to directly set output pins that are being used for peripherals is probably not a good idea, no matter the chip.

  • If P0_2 = 1 works
    for the SILabs chips (at least for the f12x) it is clearly stated in the datasheet that when the crossbar assigns a pin to a 'device' (the SPI driver in this case) the port pin does not react to contents of the pprt latch.

    Erik

  • Here is my source code:

    NB: In the main routine, I always send data to observe the SPI clock to the oscilloscope.

    //-----------------------------------------------------------------------
    //       Includes
    //-----------------------------------------------------------------------
    
    #include <stdio.h>
    #include <c8051f120.h>     // SFR declarations
    
    
    //-----------------------------------------------------------------------
    //       Global constants
    //-----------------------------------------------------------------------
    
    
    sbit SPI_SCLK=P0^2;     // SPI clock on P0.2
    sbit SPI_MISO=P0^3;     // Master In/Slave Out on P0.3
    sbit SPI_MOSI=P0^4;     // Master Out/Slave In on P0.4
    sbit SPI_NSS=P0^5;      // Slave Select on P0.5
    
    
    
    //-----------------------------------------------------------------------
    //       Functions prototypes
    //-----------------------------------------------------------------------
    
    void SYSCLK_Init (void);
    void port_init (void);
    void config_SPI (void);
    void transfert_donnees (int donnee);
    
    //-----------------------------------------------------------------------
    //       Main
    //-----------------------------------------------------------------------
    
    void main (void)
    {
    int i;
            SYSCLK_Init ();
        port_init ();
        config_SPI ();
    
        SFRPAGE = SPI0_PAGE;             // Load SPI page
         while (1)
         {
                    transfert_donnees (0xAA);
                    for (i = 0; i<256; i++);
    
         }
    }
    
    //----------------------------------------------------------------------
    // SYSCLK_Init
    //----------------------------------------------------------------------
    //
    // This routine initializes the system clock to use the internal oscillator
    // at 24.5 MHz multiplied by four using the PLL.
    //
    void SYSCLK_Init (void)
    {
       int i;                              // delay counter
    
       OSCXCN = 0x67;                      // start external oscillator with
                                           // 22.1184 MHz crystal
    
       for (i=0; i < 256; i++) ;           // Wait for osc. to start up
    
    
       OSCICN = 0x88;                      // select external oscillator as SYSCLK
                                           // source and enable missing clock
                                           // detector
    }
    //-----------------------------------------------------------------------
    //     Ports I/O initialisation
    //-----------------------------------------------------------------------
    
    void port_init (void)
    {
             char sfrpage_save = SFRPAGE;     // Save current page of SFR
    
         SFRPAGE = CONFIG_PAGE;           // Load config_page
    
             WDTCN = 0xde;
             WDTCN = 0xad;                    // Disable watchdog timer
    
         XBR0            = 0x06;          // Enable SPI bus
         XBR1            = 0x14;          // Enable /INT0 and /INT1
         XBR2            = 0x40;          // Enable Crossbar and weak pull-up
         P0MDOUT             = 0x38;          // P0.5, P0.4, P0.3 and P0.2 are outputs (for SPI datas)
    
         SFRPAGE = sfrpage_save;          // Restore SFR page
    }
    
    //-----------------------------------------------------------------------
    //     SPI bus configuration
    //-----------------------------------------------------------------------
    
    void config_SPI (void)
    {
         char sfrpage_save = SFRPAGE;     // Save current SFR page
    
         SFRPAGE = SPI0_PAGE;             // Load SPI page
    
         SPI0CFG   |= 0x60;               // Master Mode Enable
             SPI0CN         = 0x0D;               // Master mode; SPI enabled;
             SPI0CKR        = 0x01;
    
         SFRPAGE = sfrpage_save;          // Restore SFR page
    
    }
    
    //-----------------------------------------------------------------------
    //     Data transfert
    //-----------------------------------------------------------------------
    
    void transfert_donnees (int donnee)
    {
         unsigned char donnee_1;
         unsigned char donnee_2;
    
    
         donnee_1 = ( donnee & 0xFF00) >> 8;     // MSB in data_1
         donnee_2 = ( donnee & 0x00FF);          // LSB in data_2
    
             while (TXBMT == 0);
         SPI0DAT = donnee_1;                     // data_1 transmission
         SPIF    = 0;
             while (TXBMT == 0);
             SPI0DAT = donnee_2;                     // data_2 transmission
             SPIF    = 0;
    
    
    
    }
    

    Manu

  •      XBR0            = 0x06;          // Enable SPI bus
         XBR1            = 0x14;          // Enable /INT0 and /INT1
         XBR2            = 0x40;          // Enable Crossbar and weak pull-up
         P0MDOUT         = 0x38;          // P0.5, P0.4, P0.3 and P0.2 are outputs (for SPI datas
    

    PLEASE do not comment incorrectly, I were just about to post "your pinnings are wrong' when I realized that

    XBR0            = 0x06;          // Enable SPI bus
    is
    XBR0            = 0x06;          // Enable UART0 and SPI bus
    

    some of us will gladly help you, but if you make it more difficult to help you than need be such help will soon fade away.

    Now, if you read the datasheet very carefully, you will find a little well hidden nugget which is that SPI must be initialized before the crossbar, since SPI init is the only place the (non)existence of NSS is known.

    Erik