|
|
View previous topic :: View next topic |
Author |
Message |
neil
Joined: 08 Sep 2003 Posts: 128
|
SPI in one direction and packeting bytes? |
Posted: Thu Dec 16, 2004 7:51 am |
|
|
Hello people, I am trying to use SPI from pic to pic for one way communication from master to slave. I have a control system which I previously designed with a 16F877 and want to link it to a small slave which is triggering thyristors. The slave is a 16F818.
I have my thyristor triggering cct on Pin B3/CCP1 and have left SDO (out from slave to master) disconnected.
My first question is: Is it OK to disuse SDO and even configure the port pin as input for use elsewhere?
Second, the way I am sending the data might be a bit inefficient. I need to send 10-bit words in each transaction, so I am shifting my data bytes around so that the 10 bits are spread equally across the 2 SPI bytes and the first 3 bits tell the receiver the byte order. eg: 1st byte: 000ddddd, 2nd byte: 001ddddd where 'd' is a data bit and the '1' identifies the second byte.
The slave then shuffles the 5 bits from each SPI byte back into the original 10-bit word. I have done this using bit shifting, ORing and masking.
For those in the know.... Ttelmah maybe? is this a hopelessly long-winded way of doing it, ir is it a neat idea?
____________________________________
For your information, I have already implemented this and it does work, but occasionally stops working. Sometimes it won't start working again even after a full power off of master and slave Only actually reprogramming the device sometimes fixes it!! Weird!
I do have three interrupt sources in use, but the code in the ISRs is very short... just setting a flag, clearing timer1 and the like. My CCP interrupt was occuring every 100�s, which I think might have been a bit too frequent, but it now only occurs every 10ms. The CCP and ext interrupts happen every 10ms, but with a variable (known) delay between them. You can probably work out what this circuit is doing from these times if you're in the UK
Whoa! hope this hasn't bored you too much!! Your insight will be much appreciated, and Merry Christmas! |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Thu Dec 16, 2004 8:22 am |
|
|
Quote: | Is it OK to disuse SDO and even configure the port pin as input for use elsewhere? |
Yes you can use the SDO pin as an input in SPI mode - when you do this the SDO output function is disabled. You cannot however use it as a general purpose output when in SPI mode.
Quote: | The slave then shuffles the 5 bits from each SPI byte back into the original 10-bit word. I have done this using bit shifting, ORing and masking.
For those in the know.... Ttelmah maybe? is this a hopelessly long-winded way of doing it, ir is it a neat idea? |
Well if it works for you and you are not time constrained why change it?
If you did not need to use the byte identifier then it would be more efficient to have the lower 8 bits in one byte and the remaining two bits in the other. One thing to consider is the PIC has a very efficient nibble swap instruction (in assembler). This mechanism could be used to arrived at a more efficient, but less readable, solution. You could put the low order nibble in one byte with the high order nibble being clear to indicate this is the low order nibble of the 10 bit value being constructed. The remaining 6 bits are stored in the next byte with the high order bit set to identify this byte contains the high order nibble. This way the most significant bit indicates high or low order byte of the sequence. To reconstruct the 10 bit value you use the swap nibble instruction in conjunction with the W register to rebuild the low order 8 bits. The remaining 2 high order bits are recovered by stripping the most significant bit and nibble swapping to move the high order nibble to the low order position of that byte.
Quote: | Only actually reprogramming the device sometimes fixes it!! Weird!
|
Did you remember to disable low voltage programming? _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
neil
Joined: 08 Sep 2003 Posts: 128
|
I wish! |
Posted: Thu Dec 16, 2004 8:48 am |
|
|
Hi Andrew, thanks for your ideas. Unfortunately it's not the LVP bit. I checked the configuration bits. This has caught me out before, so it's always a good one to check before the tearing out of hair!!
In between posting and going off to do something else, I came back to my bench and switched the power back on, and not a peep out of the slave!
I have a 'data' led on the slave board which I toggle in each SSP interrupt using the command "data ^= 1;" Nice and simple. No data LED suggests, or rather proves(?) that the interrupt is never happening.
The data LED on my master is indicating that data is being sent. My cable between the 2 (about a foot long) is intact.
I'm confused!
Note: I am toggling the LED rather than flashing it to avoid using any delays, so the LED goes on for the 1st SPI byte and off for the 2nd. There is also a visible delay between the two SPI bytes. |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
|
neil
Joined: 08 Sep 2003 Posts: 128
|
|
Posted: Thu Dec 16, 2004 10:19 am |
|
|
Hi, this is probably going to make me look stupid now....
Code: |
#include <16F818.h>
#use delay(clock=4000000)
#fuses HS,PUT,NOMCLR,NOLVP,BROWNOUT,NOWDT,CCPB2
#use FAST_IO(A)
#use FAST_IO(B)
#bit INTF=0xB.1
#bit DATA = 6.6 // Goes to 'DATA' LED on iss 2 PCB (YELLOW).
#bit ERR = 6.7 // Goes to 'ERROR' LED on iss 2 PCB (RED).
#bit ZX = 5.3 // Goes to 'J2' on iss. 2 PCB.
#byte SSPBUF = 0x13
#define hi(x) *(&x+1)
#define lo(x) *(&x)
long phase=0,incoming_data;
int RX_Byte,data_changed=0;
short spi_data_in=0;
#int_SSP // ISR is very short!
SPI_byte_RX() {
spi_data_in=1;
DATA^=1;
}
<rest>
void main() {
<snip>
setup_spi(spi_SLAVE | SPI_L_TO_H);
enable_interrupts(INT_CCP1);
enable_interrupts(INT_EXT); // Enable the zero-crossing interrupt.
enable_interrupts(INT_SSP);
INTF=0; // Clear any garbage interrupt.
enable_interrupts(global);
<snip>
while(TRUE){ // Main loop - nothing to tie up proc. here!
if(spi_data_in){
spi_data_in=0; // reset flag
RX_Byte = SSPBUF; // transfer buffer to variable
//___This arranges bytes into order after reception over SPI.
if(RX_Byte < 32) lo(incoming_data)=RX_Byte; // If <32, it must be a Low Byte.
else hi(incoming_data)=(RX_Byte & 0b00011111); // else (ie. if >=32) it must be a High. Also, mask out the identifier bits.
data_changed++;
}
if(data_changed == 2){
data_changed = 0;
//___Shift long back to reconstruct the 10-bit variable.
lo(incoming_data) <<= 3; // Shift Lo bits back to MSB justified. eg. 00098765|00043210 -> 00098765|43210000.
incoming_data >>= 3; // Shift entire long back to represent 10-bit int. eg. 00098765|43210000 -> 0000009876543210.
}
}
}
|
Messy, I know. The 'data changed' variable is there to make sure the data is only ever re-justified to a long after both bytes have been RX over SPI.
The code is just the relevant bits. I have snipped out all the code which does the thyrsitor triggering. This is all interrupt based, between the EXT int for zero crossing detection and the CCP interrupt for triggering. This part is tried and trusted, unless you think this may be causing problems for the SPI handling?
Thanks again,
Neil. |
|
|
drh
Joined: 12 Jul 2004 Posts: 192 Location: Hemet, California USA
|
|
Posted: Thu Dec 16, 2004 1:03 pm |
|
|
Are the master PIC and slave PIC powered by the same source? If so, are you allowing enough time for the slave to initialize before trying to talk to it? _________________ David |
|
|
Guest
|
|
Posted: Thu Dec 16, 2004 4:38 pm |
|
|
Hi David, funny you should say that... in fact the slave is powered by a transformerless (capacitor drop) power supply at line potential and the master has a dedicated power supply 'block' which is isolated.
The slave is isolated by means of some fast logic optoisolators on the SPI bus, rather than a transformer. This has crossed my mind as a potential problem, but I cannot see a problem as it is.
Anything I haven't thought of?
Regards,
Neil. |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Thu Dec 16, 2004 5:32 pm |
|
|
Have you simplified the code too much? There is no set_tris command to set port B to output for the LED etc _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
neil
Joined: 08 Sep 2003 Posts: 128
|
|
Posted: Fri Dec 17, 2004 3:21 am |
|
|
Hello again,
I have set up the tris registers, and I am using 'fast IO' on both ports. Do you know if fast IO can cause problems? I am not changing any IOs from I to O, they are all set for the life of the code.
Here is another excerpt. I am not posting the whole code for the sake of keeping these posts readable and smallish, not for any privacy issue!
Regards,
Neil.
Code: | setup_ccp1(CCP_COMPARE_INT); //Setup the CCP, before enabling the interrupt
set_tris_a(0x00);
set_tris_b(0x13); // 1100 1000 L-H
setup_spi(spi_SLAVE | SPI_L_TO_H);
//SSPSTAT = 0; // SPI Slave, rising edge, idle high.
//SSPCON = 0x35;
porta=0;
OPBIT=1; //ensure trigger line is high (inactive).
set_timer1(0);
DATA = 0; // DATA LED off.
ERR=0;
phase = 200;
CCPIF=0; //Ensure that a CCP interrupt has not already occured, before next line.
SSPIF=0;
enable_interrupts(INT_CCP1);
enable_interrupts(INT_EXT); // Enable the zero-crossing interrupt.
enable_interrupts(INT_SSP);
//enable_interrupts(INT_RTCC);
INTF=0; //Also make sure that the code starts 'in sync', by clearing all interrupt flags.
enable_interrupts(global);
|
|
|
|
|
|
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
|