![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
tmach
Joined: 20 Dec 2003 Posts: 14
|
Any Suggestions! |
Posted: Thu Mar 11, 2004 9:02 pm |
|
|
Hello All!
I am using port B interrupt on change to implement a software SPI. I set RB4 as clock and RB5 as latch, data is connected to RB1. I left shift 16 bits of data on a clock L->H and then if I receive Latch L->H trigger, I process the 16-bit data. Of the 16 bits, If bit 0 (the first bit that I receive) is high, I send some configuration data through UART.
To test my code, I send 16 clock pulses and corresponding 16 bits of data (the data changes at -ve edge of clock to avoid any timing issues), then I set latch high. The data that I send is FFFF (first bit is 1) so, I expect to see something from the UART, but I see that the UART works once in 5 or 6 times that I send the data. Also I observe that this freq changes if the latch high pulse width is increased. I am using a clock freq of 2 MHz. But after some time if latch pulse if high for long time, then I see the UART data sent each time I latch the 16-bit data, even if MSB bit is not set! I am clueless
Please advise if I am doing something wrong in my code? My code is attached. My device is 16F874A and 20 MHz osc.
*************************************************************
#INT_RB
void intRB()
{
if(SPI_ENABLE == 0) // shift data if the latch is low
{
if((SPI_CLK == 1) && (WAIT == 0)) //Clock L->H
{
// move two bytes from the DIN line to our (long) word
shift_left(&DIN_data[0],2, SPI_DIN);
}
WAIT = 0;
}
else // enable L->H transition, time to process the shifted data
{
WAIT = 1;
if(bit_test(DIN_data[1],7)) // check for BIT if high
{
BIT_FLG = 1; //set the bit activate flag
}
// start storing the data in the registers
if(bit_test(DIN_data[1],6) && bit_test(DIN_data[1],5))
{
RF.Tx2_L = DIN_data[0];
RF.Tx2_H = DIN_data[1];
}
else if(!bit_test(DIN_data[1],6) && bit_test(DIN_data[1],5))
{
RF.Tx1_L = DIN_data[0];
RF.Tx1_H = DIN_data[1];
}
else if(bit_test(DIN_data[1],6) && !bit_test(DIN_data[1],5))
{
RF.Rx2_L = DIN_data[0];
RF.Rx2_H = DIN_data[1];
}
else if(!bit_test(DIN_data[1],6) && !bit_test(DIN_data[1],5))
{
RF.Rx1_L = DIN_data[0];
RF.Rx1_H = DIN_data[1];
}
}
}
#use delay(clock=20000000)
main()
{
//port initialization
//Interrupt defines
ENABLE_INTERRUPTS(INT_RB);
ENABLE_INTERRUPTS(GLOBAL);
delay_ms(settle); // Let the inputs settle down
while(true)
{
if(BIT_FLG == 1)
{
BIT_FLG = 0;
printf("%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X",
RF.Tx1_H,RF.Tx1_L,RF.Tx2_H,RF.Tx2_L,
RF.Rx1_H,RF.Rx1_L,RF.Rx2_H,RF.Rx2_L);
}
}
} ![Rolling Eyes](images/smiles/icon_rolleyes.gif) |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
Re: Any Suggestions! |
Posted: Fri Mar 12, 2004 4:57 am |
|
|
tmach wrote: | Hello All!
I am using port B interrupt on change to implement a software SPI. I set RB4 as clock and RB5 as latch, data is connected to RB1. I left shift 16 bits of data on a clock L->H and then if I receive Latch L->H trigger, I process the 16-bit data. Of the 16 bits, If bit 0 (the first bit that I receive) is high, I send some configuration data through UART.
To test my code, I send 16 clock pulses and corresponding 16 bits of data (the data changes at -ve edge of clock to avoid any timing issues), then I set latch high. The data that I send is FFFF (first bit is 1) so, I expect to see something from the UART, but I see that the UART works once in 5 or 6 times that I send the data. Also I observe that this freq changes if the latch high pulse width is increased. I am using a clock freq of 2 MHz. But after some time if latch pulse if high for long time, then I see the UART data sent each time I latch the 16-bit data, even if MSB bit is not set! I am clueless
Please advise if I am doing something wrong in my code? My code is attached. My device is 16F874A and 20 MHz osc.
*************************************************************
#INT_RB
void intRB()
{
if(SPI_ENABLE == 0) // shift data if the latch is low
{
if((SPI_CLK == 1) && (WAIT == 0)) //Clock L->H
{
// move two bytes from the DIN line to our (long) word
shift_left(&DIN_data[0],2, SPI_DIN);
}
WAIT = 0;
}
else // enable L->H transition, time to process the shifted data
{
WAIT = 1;
if(bit_test(DIN_data[1],7)) // check for BIT if high
{
BIT_FLG = 1; //set the bit activate flag
}
// start storing the data in the registers
if(bit_test(DIN_data[1],6) && bit_test(DIN_data[1],5))
{
RF.Tx2_L = DIN_data[0];
RF.Tx2_H = DIN_data[1];
}
else if(!bit_test(DIN_data[1],6) && bit_test(DIN_data[1],5))
{
RF.Tx1_L = DIN_data[0];
RF.Tx1_H = DIN_data[1];
}
else if(bit_test(DIN_data[1],6) && !bit_test(DIN_data[1],5))
{
RF.Rx2_L = DIN_data[0];
RF.Rx2_H = DIN_data[1];
}
else if(!bit_test(DIN_data[1],6) && !bit_test(DIN_data[1],5))
{
RF.Rx1_L = DIN_data[0];
RF.Rx1_H = DIN_data[1];
}
}
}
#use delay(clock=20000000)
main()
{
//port initialization
//Interrupt defines
ENABLE_INTERRUPTS(INT_RB);
ENABLE_INTERRUPTS(GLOBAL);
delay_ms(settle); // Let the inputs settle down
while(true)
{
if(BIT_FLG == 1)
{
BIT_FLG = 0;
printf("%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X",
RF.Tx1_H,RF.Tx1_L,RF.Tx2_H,RF.Tx2_L,
RF.Rx1_H,RF.Rx1_L,RF.Rx2_H,RF.Rx2_L);
}
}
} ![Rolling Eyes](images/smiles/icon_rolleyes.gif) |
Seriously, I'd suspect your problem is latency.
When the interrupt occurs on RB, The code takes a _very_ long time (in computer terms), to actually get to the interrupt handler. I did some 'rough' calculations for another thread, and predicted about 108 clock cycles to get to the start of the handler for a 16 family chip. Now with a 2MHz SPI clock, you will potentially receive edges at just 10 clock cycle intervals. Hence you will have missed perhaps 10 of the SPI clocks, when you reach the handler for the first time. By the second loop round, you will probably have just about finished clocking your data, and whether you see a '1' or a '0' will then depend on luck. Clocking at a slower rate, the probability that data is still arriving increases.
You are trying to operate, perhaps a factor of about 20* above the maximum practical frequency for an interrupt driven receive routine. You need to rethink, and either operate at a very slow rate, using the interrupt apporach, or possibly operate at the high rate (which could just about be done if you stay inside the routine), and send a single 'trigger' edge, to make the slave go into the handler routine, then wait long enough for it to have reached the handler, and then send the rest of the clocks...
This problem exists, to a lesser extent, with the hardware SPI, but even here, the need to place the 'return' byte into the buffer, soon after the data has arrived, and the lack of double buffering on the receiver, makes high rates hard to achieve.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|