|
|
View previous topic :: View next topic |
Author |
Message |
prog Guest
|
SPI Problem with 16F88 |
Posted: Mon Jul 21, 2008 9:03 am |
|
|
Hello
I am having a problem with SPI interface to communicate between a PIC16F88 and a GPRS modem, using the CCS pic C compiler.
The problem is that sometimes the value is wrong an the rest of time the byte is one bit shift.
Code: |
setup_spi(SPI_SLAVE|SPI_L_TO_H|SPI_CLK_DIV_16);
EXT_isr() {
if (input(SS)==0) //se ha activado el SS
{
while (!spi_data_is_in());
data_spi[aux] = spi_read();
aux++;
}
}
|
I have tried with different configurations, but all time the read value is incorrect.
thank you |
|
|
Ttelmah Guest
|
|
Posted: Mon Jul 21, 2008 10:41 am |
|
|
First, a slave _does not have a clock setting_. The most likely problem is that setting this, is resulting in incorrect configuration of the registers.
Now, your 'code', makes it impossible to have a hope of knowing what is really going on. What is int_ext connected to?. What SPI 'mode' does the modem use?. What speed?. etc. etc..
Best Wishes |
|
|
Guest
|
|
Posted: Tue Jul 22, 2008 1:05 am |
|
|
Hi,
The mode configuration that I use is: 2MHz, the data valid on rising edge.
I have connect the SS to input of port B, and I have configured the INT_RB:
ext_int_edge( H_TO_L );
enable_interrupts(INT_RB);
When the SS change the interruption jump, and call the next funtion:
Code: |
#INT_RB
EXT_isr() {
if (input(SS)==0)
{
flag_spi=1;
while (!spi_data_is_in());
data_spi[aux] = spi_read();
}
}
|
I have tried without clock setting, but the problem is the same, sometimes the value is incorrect and other times it read anything.
I saw the problems the other people and I changed the configuration for this:
Code: |
setup_spi(SPI_SLAVE | SPI_SS_DISABLED | SPI_L_TO_H | SPI_XMIT_L_TO_H);
|
In this case the read value is correct all times, but some time the interruption ocurrs but it ready any data.
Thank you[/code] |
|
|
Ttelmah Guest
|
|
Posted: Tue Jul 22, 2008 3:01 am |
|
|
That is not the SPI mode.
There are four standard SPI modes. The GPRS modem, will say somewhere in it's data sheet a comment like 'compatible with SPI mode 0'. This defines both how data is sent by it, and how the receiving device has to send it's data. It is about 3000% easier to setup SPI, by just identifying the mode number, and then looking up the required PC settings (a table of modes to CCS codes, has been published here many times...).
It sounds as if your device uses mode 0, since the combination you have working, is the setting for this.
Key problem was that you are not actually 'using' SS. SS, is a hardware pin with the SPI, and requires you to use this pin. However it raised the comment, 'why not'. If you connected the SS pin to the hardware pin, and instead of using INT_EXT (which as it stands, you are stuck in for the receiving of the whole command string), just use the INT_SSP. You will receive an interrupt for each byte, and can simply set a flag when the last byte is seen to tell your main code that the data is ready.
As it stands, the code will not work properly, since in most devices, 'SS' will not go high, for a short period _after_ the last byte has been sent. Your code sees the last byte, transfers it into the buffer, then tests the input pin, which is still low, so goes back to waiting for another byte, which does not arrive, till the next frame begins. Hence you will have to wait for the next command to start, and will receive the bytes 'out of sync'.
Use the hardware, and count the received bytes, so you know when the packet has finished.
Best Wishes |
|
|
prog Guest
|
|
Posted: Tue Jul 22, 2008 4:09 am |
|
|
I have seen the datasheet and the GPRS modem uses mode 0.
I have tried to change the INT_RB by INT_SSP and use SS, but the problem persists. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Jul 22, 2008 3:58 pm |
|
|
Quote: | I have connect the SS to input of port B, and I have configured the INT_RB:
ext_int_edge( H_TO_L );
enable_interrupts(INT_RB); | It looks like you have mixed up INT_RB and INT_EXT.
INT_EXT: activated by a change on the INT pin (B0, pin 6). The edge generating the interrupt is selected by calling ext_int_edge().
INT_RB: this interrupt is triggered by any change on the pins B4 to B7. It is different from all the other interrupts in that the interrupt flag can not be cleared directly but only by reading from port B. For all interrupts the compiler clears the interrupt flag for you, but in INT_RB you have to ensure PORT_B is read.
With the above information I suggest you adapt your program.
Instead of code fragments please post a small test program. Make sure the program is complete, including all fuses, etc, so we can copy/paste it into our compiler. Keep it small as possible, maximum 20 lines. |
|
|
|
|
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
|