No, it never gets out of this routine as it is stuck in the loop at lines 28-29 waiting for BF to be set for the third byte.Does it disable the SPI when it has nothing more to send and zap the last clock?
Yes, I agree.I don't know why you need the delay.. that's suspicious.
Again, the SPI can't be turned off since the processor is stuck in this loop... and at 2.4us its about 1 clock time. I wonder if the original programmer has that to allow for one more clock time after reading BF==1 before loading the next char. Maybe he was losing a clock also. The problem with where the delay is is that it would NOT apply on the last character.... And if he turns the SPI off after the last character.....
SPI_fu is strong in this one.. Good catch. I'm off for more coffee.Photo 1: Positive clock, rising edge
Photo 2: Positive clock, falling edge
Photo 3: Negative clock, rising edge, 7 bit.
Either the hardware is fubar, or your code is unintentionally mucking with the config registers.
Edit: I choose the latter.
Hmm, but the two registers that control the port are set identically between bytes 1 and 2, so why does it change (I've checked that this is the case, both before and after the SSP1BUF = data_out line)?Photo 1: Positive clock, rising edge
Photo 2: Positive clock, falling edge
Photo 3: Negative clock, rising edge, 7 bit.
Either the hardware is fubar, or your code is unintentionally mucking with the config registers.
Edit: I choose the latter.
This is where I hate C. An optimization my be causing a write to SSP1STAT and/or SSP1CON while you think you are only doing a read. Have you tried the simulator? I think you can set a trigger to stop simulation whenever a particular bit gets flipped.Hmm, but the two registers that control the port are set identically between bytes 1 and 2, so why does it change (I've checked that this is the case, both before and after the SSP1BUF = data_out line)?
I would not discount broken hardware, but how would I prove it?
You could infer it from the colossal errata sheet... Reread item #30. That's what the 1 clock cycle delay is about (don't load the next character until 1 clock cycle after detecting BF). You might try increasing that as a test.I would not discount broken hardware, but how would I prove it?
But wouldn't I see anything that happens (inc. interrupts) by stepping through the code using MPLAB/PICKit3?This is where I hate C. An optimization my be causing a write to SSP1STAT and/or SSP1CON while you think you are only doing a read. Have you tried the simulator? I think you can set a trigger to stop simulation whenever a particular bit gets flipped.
Things like this usually happen in one of two cases:
1. An (possibly unassociated) interrupt is accessing the registers;
2. Access to a register in another bank is occurring without properly setting up the BSR register, or improper use of the BANKED/ACCESS flag.
Thanks for your help. Good luck with your finalYou could infer it from the colossal errata sheet... Reread item #30. That's what the 1 clock cycle delay is about (don't load the next character until 1 clock cycle after detecting BF). You might try increasing that as a test.
I note that the last bit sent is different between chars 1-2 but same between 2-3. Combined with the errata item 30 I am getting bad vibes. The I2C mode has a LSbit of one char to MSbit to the next char problem that is data dependent if certain timings are not observed. Don't recall what it is right now but its the same hardware.
Look, here's what I would do. Scrap this and bit bang it. As I said the MSSP on this thing is a mess. Someone has applied some errata fixes in hope of making it work but as you can see (and @joeyd999) pointed out, the hardware is fubar. And as far as using MPSIM, uhhh.. unless they've fixed it, it hangs when you poll BF. I have switches in my code for MPSIM. I know, right? *wipes away tears*
As it is written, you would suffer MINIMAL performance consequences by bit banging. The code waits for each character to be sent anyway. It might even be better since you don't have to add the 2.4uS delay. You can spiff things up by doing things between the clock edges i.e. raise the clock, shift the data byte, lower the clock, decrement the bit counter etc. and it will be pretty zippy. That's how I do it.
Joey and @spinnaker posted while I was typing.. Spin makes a good point about interrupts. I agree with Joey to see what the compiler has generated - but I'd still be bit banging it. I think you are fighting silicon battles that you can't win.
You might open a ticket at uCHIP and see what they say. Maybe they have another workaround.
Good luck.
Improv final today. Gotta go practice.
Maybe. Maybe not.But wouldn't I see anything that happens (inc. interrupts) by stepping through the code using MPLAB/PICKit3?
//-------------------------------- WRITE 1 BYTE TO OPENED EE ----------------------------
// Assumes EE is opened for writing. Sends data byte, returns when its sent
unsigned char EE_WriteByte(unsigned char dat)
{
SSP1BUF = dat; // drop it on buf to send
while(!BF1); // wait for returned byte
return SSP1BUF; // read buf to clear, return byte
}
//-------------------------------- READ 1 BYTE FROM OPENED EE ---------------------------
// Assumes EE is opened for reading. Sends dummy byte, returns byte replied by EE
unsigned char EE_ReadByte(void)
{
SSP1BUF = 0x55; // send dummy byte
while(!BF1); // wait for reply
return SSP1BUF; // read and return reply
}
I tried just the following code, in a project on its own:Maybe. Maybe not.
A few thousand, or more, lines of code my get executed before those bits get transitioned.
At this point, I agree with @spinnaker. Make a small project with only the relevant lines of code -- just the SPI. Get that to work to the exclusion of everything else. Then, incorporate the working code into your main program. If the problem reappears, at least that tells you the issue lies somewhere outside of your SPI code.
unsigned char Errata_WriteSPI( unsigned char data_out)
{ unsigned char temp;
temp = SSP1STAT;
while( (temp & 1) == 1)
{ temp = SSP1BUF; temp = SSP1STAT; } // clear BF before the operation starts
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
{
temp = SSP1STAT;
while( (temp & 1) == 0)
{
temp = SSP1STAT; // wait until bus cycle complete
}
}
return ( 0 ); // if WCOL bit is not set return non-negative #
}
void main(void)
{ unsigned char runvar;
runvar = 1;
OpenSPI(SPI_FOSC_64, MODE_11, SMPMID);
while(runvar == 1)
{
if (Errata_WriteSPI(0x55))
runvar = 0;
if (Errata_WriteSPI(0xAA))
runvar = 0;
}
CloseSPI();
}
Good. At least you don't have to waste time with your SPI code anymore.I tried just the following code, in a project on its own:
unsigned char Errata_WriteSPI( unsigned char data_out)
{ unsigned char temp;
temp = SSP1STAT;
while( (temp & 1) == 1)
{ temp = SSP1BUF; temp = SSP1STAT; } // clear BF before the operation starts
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
{
temp = SSP1STAT;
while( (temp & 1) == 0)
{
temp = SSP1STAT; // wait until bus cycle complete
}
}
return ( 0 ); // if WCOL bit is not set return non-negative #
}
void main(void)
{ unsigned char runvar;
runvar = 1;
OpenSPI(SPI_FOSC_64, MODE_11, SMPMID);
while(runvar == 1)
{
if (Errata_WriteSPI(0x55))
runvar = 0;
if (Errata_WriteSPI(0xAA))
runvar = 0;
}
CloseSPI();
}
Worked like a charm, churning 0x55 followed by 0xAA out continuously...which is good, I suppose...except it means there is something more subtle and tricky to find at work in the main code![]()
How about immediately reconfiguring CKE/CKP prior to each transmission?I have been checking them using MPLAB/PICKit3 by putting breakpoints before and after the SSP1BUF = data_out line. Neither register changes over the course of the instruction.
| Thread starter | Similar threads | Forum | Replies | Date |
|---|---|---|---|---|
| X | PIC18f8722 (given delay and clocked by oscillator) | Microcontrollers | 16 | |
| P | Fun project with pic18f8722 | Microcontrollers | 2 | |
| Z | analog comparator in pic18f8722 | Microcontrollers | 17 | |
| A | About PIC18F8722 UART | Microcontrollers | 3 | |
| B | [PIC18F8722]Light a LED? | Microcontrollers | 11 |