WriteSPI locking up on PIC18F26J53

Thread Starter

spinnaker

Joined Oct 29, 2009
7,815
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?
 

Thread Starter

spinnaker

Joined Oct 29, 2009
7,815
An update

Here is where it is getting stuck

Rich (BB code):
unsigned char WriteSPI1( unsigned char data_out )
{
  unsigned char TempVar;  
  TempVar = SSP1BUF;           // Clears BF
  PIR1bits.SSP1IF = 0;         // Clear interrupt flag
  SSP1CON1bits.WCOL = 0;            //Clear any previous write collision
  SSP1BUF = data_out;          // write byte to SSP1BUF register
  if ( SSP1CON1 & 0x80 )       // test if write collision occurred
   return ( -1 );              // if WCOL bit is set return negative #
  else
   //while( !SSP1STATbits.BF ); // wait until bus cycle complete 
   while(!PIR1bits.SSP1IF); // wait until bus cycle complete     <<   Locking up here
  return ( 0 );                // if WCOL bit is not set return non-negative#
}
I read somewhere that you should not read the .SSP1IF register directly so I modified it as follow:

Rich (BB code):
unsigned char WriteSPI1( unsigned char data_out )
{
  unsigned char TempVar;  
  unsigned char TempVar2;  
  TempVar = SSP1BUF;           // Clears BF
  PIR1bits.SSP1IF = 0;         // Clear interrupt flag
  SSP1CON1bits.WCOL = 0;            //Clear any previous write collision
  SSP1BUF = data_out;          // write byte to SSP1BUF register
  if ( SSP1CON1 & 0x80 )       // test if write collision occurred
   return ( -1 );              // if WCOL bit is set return negative #
  else
   //while( !SSP1STATbits.BF ); // wait until bus cycle complete 
    do
    {
        TempVar2 = PIR1bits.SSP1IF;
    }   while(!TempVar2); // wait until bus cycle complete
  return ( 0 );                // if WCOL bit is not set return non-negative#
}
But it still locks up in the while loop.

Looks like the interrupt is never being called.
 
Last edited:

Thread Starter

spinnaker

Joined Oct 29, 2009
7,815
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.
 

Thread Starter

spinnaker

Joined Oct 29, 2009
7,815
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.
 

thatoneguy

Joined Feb 19, 2009
6,349
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.
 

Thread Starter

spinnaker

Joined Oct 29, 2009
7,815
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.
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.
 

thatoneguy

Joined Feb 19, 2009
6,349
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.
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.
 
Top