WriteSPI locking up on PIC18F26J53

Discussion in 'Embedded Systems and Microcontrollers' started by spinnaker, Nov 18, 2011.

  1. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    991
    I am trying to write to the SPI port of a PIC18F26J53.

    When I call WriteSPI, WriteSPI locks up and never returns from the function.

    I am running the chip at the default 4MHZ.

    Here are my configuration settings.

    #pragma config WDTEN = OFF
    #pragma config XINST = OFF
    #pragma config OSC = INTOSC

    This is my first experience with a PIC18F26J53 so perhaps it is a config setting?

    Here is my code:

    OpenSPI1(SPI_FOSC_4, MODE_00, SMPEND);
    WriteSPI1(255);


    I have also tried

    OpenSPI11(SPI_FOSC_4, MODE_00, SMPEND);
    WriteSPI11(255);

    which locks up and

    OpenSPI2(SPI_FOSC_4, MODE_00, SMPEND);
    WriteSPI2(255);

    Which does not lock up but I have not yet figured out how to configure the SPI2 pins since they seem to be programmable.

    I also have a 18F14K22 which works fine with WriteSPI.

    Any idea wht WriteSPI would be locking up on the PIC18F26J53?
     
  2. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    991
    An update

    Here is where it is getting stuck

    Code ( (Unknown Language)):
    1.  
    2.  
    3.  
    4.  
    5. unsigned char WriteSPI1( unsigned char data_out )
    6. {
    7.   unsigned char TempVar;  
    8.   TempVar = SSP1BUF;           // Clears BF
    9.   PIR1bits.SSP1IF = 0;         // Clear interrupt flag
    10.   SSP1CON1bits.WCOL = 0;            //Clear any previous write collision
    11.   SSP1BUF = data_out;          // write byte to SSP1BUF register
    12.   if ( SSP1CON1 & 0x80 )       // test if write collision occurred
    13.    return ( -1 );              // if WCOL bit is set return negative #
    14.   else
    15.    //while( !SSP1STATbits.BF ); // wait until bus cycle complete
    16.    while(!PIR1bits.SSP1IF); // wait until bus cycle complete     <<   Locking up here
    17.   return ( 0 );                // if WCOL bit is not set return non-negative#
    18. }
    19.  
    20.  
    21.  
    I read somewhere that you should not read the .SSP1IF register directly so I modified it as follow:

    Code ( (Unknown Language)):
    1.  
    2.  
    3.  
    4. unsigned char WriteSPI1( unsigned char data_out )
    5. {
    6.   unsigned char TempVar;  
    7.   unsigned char TempVar2;  
    8.   TempVar = SSP1BUF;           // Clears BF
    9.   PIR1bits.SSP1IF = 0;         // Clear interrupt flag
    10.   SSP1CON1bits.WCOL = 0;            //Clear any previous write collision
    11.   SSP1BUF = data_out;          // write byte to SSP1BUF register
    12.   if ( SSP1CON1 & 0x80 )       // test if write collision occurred
    13.    return ( -1 );              // if WCOL bit is set return negative #
    14.   else
    15.    //while( !SSP1STATbits.BF ); // wait until bus cycle complete
    16.     do
    17.     {
    18.         TempVar2 = PIR1bits.SSP1IF;
    19.     }   while(!TempVar2); // wait until bus cycle complete
    20.   return ( 0 );                // if WCOL bit is not set return non-negative#
    21. }
    22.  
    23.  
    But it still locks up in the while loop.

    Looks like the interrupt is never being called.
     
    Last edited: Nov 19, 2011
  3. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    991
    I but a scope on the output pins. I also removed the while loop and replaced it with a delay. I put a scope on CK1 and SDO1. I wrote a loop to constantly send bytes to the port. I am seeing no transitions on either pin.

    I wrote some code to toggle the latches on both of those pins and I do see transitions.

    The datasheet says:

    The output pins for several peripherals are also
    equipped with a configurable open-drain output option.
    This allows the peripherals to communicate with
    external digital logic operating at a higher voltage level,
    without the use of level translators.
    The open-drain option is implemented on port pins
    specifically associated with the data and clock outputs
    of the EUSARTs, the MSSP modules (in SPI mode) and
    the ECCP modules. It is selectively enabled by setting
    the open-drain control bit for the corresponding module
    in the ODCON registers (Register 10-1, Register 10-2
    and Register 10-3). Their configuration is discussed in
    more detail with the individual port where these
    peripherals are multiplexed. Output functions that are
    routed through the PPS module may also use the
    open-drain option. The open-drain functionality will
    follow the I/O pin assignment in the PPS module.
    When the open-drain option is required, the output pin
    must also be tied through an external pull-up resistor
    provided by the user to a higher voltage level, up to
    5.5V (Figure 10-3). When a digital logic high signal is
    output, it is pulled up to the higher voltage level.


    So I assume this means since I am using SPI I need a pullup, so I used a 10K pull up to 5.5 vdc.
     
  4. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    Last edited: Nov 22, 2011
  5. Wendy

    Moderator

    Mar 24, 2008
    20,765
    2,536
  6. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    991
  7. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
  8. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    991
    Well got this one figured out. Microchip was not setting the TRIS registers in their library.

    I am being to learn not to trust Microchip's libraries. While their MCUs are top of the line the libraries they have to support them are usually horrible. Full of bugs and or overly complicated. I think one of the reasons they have so many bugs is they try to cover every chip making it as simple as possible instead of keeping it simple and put some configuration in the hands of the end user programmer.
     
  9. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    The sample code sets the TRIS registers before calling the routine, perhaps if they comment why they are setting the TRIS registers, or mentioning that it is required for SPI to work, it would help.
     
  10. spinnaker

    Thread Starter AAC Fanatic!

    Oct 29, 2009
    4,866
    991
    The problem is for some PICs the OpenSPI function sets the TRIS registers. For others it does not. They need to be consistent and if the end user needs to set the TRIS, it sound be mentioned in the documentation.
     
  11. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    That is a bit messed up, but if the coder always sets the tris registers, only 1 instruction cycle will be wasted when the function is called when the library sets the tris as well.

    I'm not defending Microchip, I feel they should document "little things" like this, and I REALLY like the new datasheet format, where when you look at any peripheral, ALL special registers are shown, with those untouched greyed out. That grid saves a ton of headaches.

    When it comes to the code, if you always set the TRIS bit for intended SPI use before calling the Init, it should work. I think the difference lies in the series that have Multi Master/Slave capability and those which do not. Correct me if I'm wrong there.
     
Loading...