|
|
View previous topic :: View next topic |
Author |
Message |
alan
Joined: 12 Nov 2012 Posts: 357 Location: South Africa
|
SPI Enhanced mode |
Posted: Tue Apr 29, 2014 12:29 am |
|
|
Good day
dsPIC33EP32MC202
CCS 5.019
I am trying to get the enhanced mode of the SPI to work, but no luck so far. Probably over looking something stupid.
The standard #use works.
Code: |
#use spi(FORCE_HW, SLAVE, SPI1, MODE=3, BITS=8, ENABLE=PIN_B0) |
I can't find any CCS functions to enable Enhanced mode, so I tried accessing the registers directly.
Code: |
#word SSPBUF = getenv("SFR:SPI1BUF")
#word SSP1STAT = getenv("SFR:SPI1STAT")
#word SSP1CON2 = getenv("SFR:SPI1CON2")
and
SSP1STAT = 0;
SSP1CON2 =0x000;
SSP1STAT = 0x8000;
|
The above works, if I set SSP1STAT =0 only then SPI does not work, which is correct and thus verified that I am accessing the correct SFR.
If I change to
Code: |
SSP1STAT = 0;
SSP1CON2 =0x0001; //Enabling Enhanced mode
SSP1STAT = 0x8000;
|
then my SPI does not work at all.
Are the enhanced mode so much different from standard mode.
Here are the SPI routine as well.
Code: |
#INT_SPI1
void SSP1_isr(void) {
static uint8_t ValLSB;
uint8_t Command;
//Read the value from SSPBUF and load next Val
Command = SSPBUF;
switch (Command) {
case 0: SSPBUF = ValLSB; break;
case VADC: SSBUF = make8(VinADC,1); ValLSB = make8(VinADC,0);
break;
default:
}
}
|
Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Tue Apr 29, 2014 1:10 am |
|
|
Hurrah...
Good start.
Easiest way to enable the enhanced mode is simply to configure using the standard code, and add:
Code: |
#bit SPIBEN=getenv("BIT:SPIBEN")
SPIBEN=TRUE;
//then enables the buffer
|
For normal byte based transfers you probably want SISEL=001. For the fastest block based transfers 010 is better, but then means the interrupt handler will always be handling multiple bytes. See comment at end.
Code in your ISR needs a lot more work.
The standard supplied SPI routines are awful (haven't checked recently if they are still as bad...). They are great for use in 'main' code, but not for use in an ISR. Hence as you have realised, for ISR based transfers, you have to go DIY.
Things missing are the ability to directly write the buffer, and then not wait for a transfer etc..
Now in your code, things to realise:
1) Because you have the buffering enabled, there can be up to eight bytes waiting on an ISR. So your read functions need to loop testing the SRXMPT bit until the buffer is empty. Whether this is likely to apply depends on how fast the data is arriving, and how 'busy' your chip is (other interrupts etc.).
2) When asked to write, you can load up to eight bytes inside one ISR. If multiple bytes are waiting to send, the write needs to loop writing data, until SPITBF goes true (signalling the output buffer is full).
3) The ISR code needs to handle error states. If SPIROV gets set, you have missed a received byte, and may need to have some form of error recovery.
I suspect your biggest problem is the interrupt mode. You have it set to interrupt when RX is empty. For a slave replying to transmissions, you want an interrupt when it has data.
Best Wishes |
|
|
alan
Joined: 12 Nov 2012 Posts: 357 Location: South Africa
|
|
Posted: Tue Apr 29, 2014 1:26 am |
|
|
Thanks Ttelmah,
That is why I want Enhanced mode, to interrupt on when data are in the buffer. But will implement what you have suggested and then give feedback.
Regards
(Edit) You have to disable the SPI first otherwise it does not take the new configuration. |
|
|
alan
Joined: 12 Nov 2012 Posts: 357 Location: South Africa
|
|
Posted: Thu May 01, 2014 2:34 am |
|
|
Given up on this, not worth the effort right now.
Thanks Ttelmah |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Thu May 01, 2014 12:36 pm |
|
|
Standard mode, interrupts when a byte has been received. Does what you want.... |
|
|
alan
Joined: 12 Nov 2012 Posts: 357 Location: South Africa
|
|
Posted: Fri May 02, 2014 12:03 am |
|
|
According to the data sheet the MCU interrupts when a byte/word has been shifted out. I need to transmit about 4 words and were hoping to pack it in and forget. But will have a look when time is available (Who am I kidding ).
Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Fri May 02, 2014 1:19 am |
|
|
The slave has nothing to do with 'shifting out'. That interrupt only occurs when you are a master device.
On a slave, everything is effectively controlled by 'shifting in'. When the slave receives a byte, there is an interrupt. At the same time as a byte is shifted in, anything already in the output buffer is shifted out. However remember that this _lags_ the input transaction. At the interrupt, the slave has received a byte, and then has to load the byte to be sent on the _next_ transaction.
Now, depending on the speed involved, you could handle this with the enhanced buffer, but then you need to possibly 'rethink' how the transaction is setup.
What you would do, is program to interrupt on a single byte.
Wait for the interrupt, which then says the master has sent you something.
Look at what the master has sent, and use this to determine the reply.
Disable the interface, and reprogram to interrupt on 'buffer empty'.
Enable the interface, and load the reply to send into the output buffer.
Exit the interrupt.
You'd then get another interrupt when the buffer empties, and can then go back to the single byte interrupt programming.
The master would need to send the 'request' byte, pause a moment (long enough for the slave to work out what the reply is to be, and reprogram the interface), and then clock in eight reply bytes as fast as it can.
The problem is that unless you change the interface 'mode' after the request byte, the chip will interrupt on every byte (so you gain nothing over the standard mode). Alternative is to have another signal say to load the buffer 'in advance' of the data being clocked (this is a fairly common way of working) - so you drop a 'select' line, and use an interrupt from _this_ to signal to load the buffer. The master drops this line, waits a moment for the buffer to be loaded, and just clocks eight bytes in. For this you don't use INT_SPI at all, unless you need to send more than eight bytes, where you interrupt when the buffer is nearly empty, to say 'load the next lot of data'.
This is the easier mode to program, and avoids having to send extra data over the bus.
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
|