|
|
View previous topic :: View next topic |
Author |
Message |
mdares
Joined: 26 Oct 2005 Posts: 19
|
SPI Interrupt problem (interrupt every 16 bits, not every 8) |
Posted: Wed Oct 26, 2005 7:22 am |
|
|
Hi Everyone,
I am having a problem with using interrupts to signal SPI data is ready. I have a PIC 18F458-E and am running the following code:
Code: |
#include <stdlib.h>
#include <9356spi.c>
#use delay(clock=40000000)
#use rs232(baud=9600, parity=n, BITS=8, xmit=PIN_C6, rcv=PIN_C7)
void main() {
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_spi(SPI_SLAVE|SPI_SS_DISABLED|spi_l_to_h);
// Now everything is setup, enable the interrupts
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
printf("Waiting for Data\n\r");
while(1) {} //Wait for interrupts
}
#INT_SSP
SPI_ISR() {
int8 writedata=8;
int8 readdata;
disable_interrupts(INT_SSP); // Disable SPI interrupts while in it's ISR
readdata = spi_read(writedata);
printf("Read: %X\n\r", readdata);
enable_interrupts(INT_SSP);
}
|
I am sending data from a TI DSP running as a master sending 8-bits at a time, and had no troubles when I was not using the interrupt handler. Since I have started using the SPI interrupt I am only receiving data every second time I send it. It seems as though the PIC is waiting for 16 bits before triggering the interrupt. I am sure this makes sense somehow, but I am expecting an interrupt every 8-bits that are clocked in.
I am using version 3.224 of the compiler. Can anyone shed any light on this problem for me?
Matthew |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Wed Oct 26, 2005 7:47 am |
|
|
Remove the enable and disable SPI interrupts from the interrupt handler. The PIC is not re-entrant and an SPI interrupt cannot interrupt itself. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
mdares
Joined: 26 Oct 2005 Posts: 19
|
|
Posted: Wed Oct 26, 2005 7:54 am |
|
|
That makes sense, and is done, but is still doesn't fix my every other byte interrupt problem. Any ideas there?
Matthew |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Wed Oct 26, 2005 8:02 am |
|
|
Take the printf out of the interrupt handler _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
mdares
Joined: 26 Oct 2005 Posts: 19
|
|
Posted: Wed Oct 26, 2005 8:24 am |
|
|
I understand how I would not want that there eventually, but for testing it should be fine, I am using a software breakpoint on my DSP, so the ISR has seconds to run in between transmissions.
In either event, I tried it for completeness and it is still the same problem. The ISR is only running after 2 8-bit messages have been clocked out by the DSP. Any other suggestions?
Matthew |
|
|
Ttelmah Guest
|
|
Posted: Wed Oct 26, 2005 8:50 am |
|
|
Though you are very confident the printf will not cause a problem, remove it anyway...
The time needed for the print, is going to be very significant (perhaps 11mSec), with the handler returning after about 8mSec, which is plenty of time for it to have missed one SPI transaction. The interrupt flag, is cleared at the _end_ of the interrupt handler, so if a second SPI interrupt occurs inside the handler, this is lost.
Having it here, also implies that interrupts will be disabled in any external print operations, which chile there are none shown inside your wait, could also cause problems...
If you must print a status for debugging, just use a 'putc', to send the single character received, which with the hardware buffer, should avoid problems provided no more than acouple of characters arrive in rapid succession.
Best Wishes |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Wed Oct 26, 2005 8:55 am |
|
|
What happens if the DSP sends three bytes? Just wondering if you have the matching SPI config at both ends. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
mdares
Joined: 26 Oct 2005 Posts: 19
|
|
Posted: Wed Oct 26, 2005 9:05 am |
|
|
Ttelmah,
you misunderstand. I have removed it, and the problem persists. But it shouldn't be a timing issue because the DSP has a software breakpoint set before each transmission (Hence it can only send data with user interaction, making it at least a full second between transmissions).
Andrew,
The first byte is ignored, the second is printed, the third ignored and the forth printed... and so on. While I wouldn't discount the idea of it being a DSP configuration problem, I think it is unlikely as the setup works fine when I am not relying on the PIC to set that interrupt. (i.e. I just do an SPI_READ and wait for data in the main loop). This leads me to believe the PIC is requiring 16 bits of data to trigger the interrupt, which doesn't make sense to me.
I am sorry if this is at all confusing,
Matthew |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Wed Oct 26, 2005 10:27 am |
|
|
Obviously I have not used the SPI with interrupts before...
The problem is in the handler. What is happening is an interrupt is received and the byte is read from the SPI port. A this point a new SPI command is issued - writing out the writedata value. The code is then loops until the byte has been serialised out onto the wire. Once the byte is serialised out the interrupt flag will be set. However the interrupt handler now clears the interrupt flag so this interrupt condition is lost.
Code: | .................... #INT_SSP
.................... SPI_ISR()
.................... {
.................... int8 writedata=8;
*
0758: MOVLW 08
075A: MOVLB 1
075C: MOVWF xAD
.................... int8 readdata;
....................
.................... readdata = spi_read(writedata);
075E: MOVF FC9,W
0760: MOVFF 1AD,FC9
0764: BTFSS FC7.0
0766: BRA 0764
0768: MOVFF FC9,1AE
.................... }
....................
....................
....................
....................
076C: BCF F9E.3
076E: MOVLB 0
0770: GOTO 0066 |
IMHO the compiler is at fault. It should not loop until the character has been serialized out. Here is a work around: Code: |
#INT_SSP
SPI_ISR()
{
int8 writedata=8;
read_first_byte = spi_read(writedata);
read_second_data = spi_read();
} |
_________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
mdares
Joined: 26 Oct 2005 Posts: 19
|
|
Posted: Wed Oct 26, 2005 10:36 am |
|
|
Ah,
So I was stuck without an interrupt until the master clocked again. Thank you SO much for your time andrew! It's people like you that make these forums work and keep people like me sane.
Matthew |
|
|
Ttelmah Guest
|
|
Posted: Wed Oct 26, 2005 10:52 am |
|
|
You will find quite a lot of posts in the archives about SPI. Wha is shown here is a fairly 'classic' problem (sorry I misunderstood that you had already tried without the printf). The SPI code as written by CCS, is not really very well 'suited' to use in an interrupt driven system. I use my own defines for all the SSP interrupts, and have found them a lot less trouble. :-)
Code: |
/* Now the SSP handler code. Using my own, since the supplied routines test the wrong way round for my needs */
#DEFINE READ_SSP() (SSPBUF)
#DEFINE WAIT_FOR_SSP() while((SSPSTAT & 1)==0)
#DEFINE WRITE_SSP(x) SSPBUF=(x)
#DEFINE CLEAR_WCOL() SSPCON=SSPCON & 0x3F
|
For me, these proved a lot simpler. On an interrupt, I can just read the character, and write the 'reply' if required into the output buffer, without any testing involved.
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|