|
|
View previous topic :: View next topic |
Author |
Message |
Guest
|
Trying to capture data from another device |
Posted: Sat Aug 09, 2008 1:44 pm |
|
|
Im trying to capture the data from a handheld laser range finder. Specifically, I'm reading the three logic signals going to the lcd. There is a data signal, a clock signal, and an enable signal. I'm guessing that this is an i2c bus, but I'm not sure.
Code: |
#int_ext
void ext_isr() //enable
{
if(int_edge_flag == 1) // edge = H_TO_L, data is coming
{
ext_int_edge(0, L_TO_H); //toggle edge for next isr iteration
int_edge_flag = 0; //flag to denote trigger edge
enable_interrupts(INT_EXT1);
}
else //edge = L_TO_H, time to print packet
{
ext_int_edge(0, H_TO_L);
int_edge_flag = 1;
disable_interrupts(INT_EXT1);
disable_interrupts(INT_EXT);
x=0;
print_buffer_flag = 1;
}
}
#int_ext1
void ext1_isr() //clock
{
if(input(DATA_PIN))
{
byte_in |= bit_mask;
}
bit_mask = bit_mask << 1;
if(bit_mask == 0x0200) //9 bits per word
{
bit_mask = 0x0001;
buffer[x] = byte_in;
x++;
byte_in = 0;
}
}
|
In main, the buffer is printed over rs232 to a PC. The data I've gotten back doesn't seem to be right. I've put the data signal and the enable signal on an oscilloscope. I can see that the first byte is 0x006A, or 106. But that number has never appeared in my data output from the PIC. Alot of the numbers are powers of 2.
Im using a PIC25j10 with a 9.216MHz crystal, using the PLL mode to run at 36.864MHz. The lcd clock signal has a frequency of 100kHz. Is this too fast for my code? How can I calculate how long 1 iteration of my ext1 isr takes? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Aug 09, 2008 2:34 pm |
|
|
Post your variable declarations for that code. |
|
|
Guest
|
|
Posted: Sat Aug 09, 2008 4:07 pm |
|
|
This is the entire code
Code: |
#include<18f25j10.h>
#fuses H4_SW, NOPROTECT, NOWDT
#define SYSTEM_CLOCK 36864000
#use delay( clock = SYSTEM_CLOCK )
#use rs232( xmit=PIN_C6, baud=9600, bits=8, parity=N )
#define N 64
#define DATA_PIN PIN_A0
int1 int_edge_flag,print_buffer_flag;
int16 bit_mask=0x0001;
int16 byte_in;
int16 buffer[N];
int16 x,y,z;
#int_ext
void ext_isr() //enable triggers ext0
{
if(int_edge_flag == 1) // edge = H_TO_L, data is coming
{
ext_int_edge(0, L_TO_H); //toggle edge for next isr iteration
int_edge_flag = 0;
enable_interrupts(INT_EXT1);
}
else //edge = L_TO_H, time to print packet
{
ext_int_edge(0, H_TO_L);
int_edge_flag = 1;
disable_interrupts(INT_EXT1);
disable_interrupts(INT_EXT);
x=0;
print_buffer_flag = 1;
}
}
#int_ext1
void ext1_isr() //clock triggers ext1
{
if(input(DATA_PIN))
{
byte_in |= bit_mask;
}
bit_mask = bit_mask << 1;
if(bit_mask == 0x0200) //9 bits per byte
{
bit_mask = 0x0001;
buffer[x] = byte_in;
x++;
byte_in = 0;
}
}
void main ()
{
setup_oscillator(OSC_PLL_ON) ;
for(y=0;y<N;y++)
{
buffer[y] = 0;
}
enable_interrupts(GLOBAL);
enable_interrupts(INT_EXT);
ext_int_edge(0, H_TO_L); //enable is active low
ext_int_edge(1, L_TO_H); //clock is active high
int_edge_flag = 1; //flag to signify ext0 trigger edge H_TO_L is 1, L_TO_H is 0
while (TRUE)
{
if(print_buffer_flag)
{
for(y=0;y<N;y++)
{
printf("\n\r %Lu",buffer[y]);
}
print_buffer_flag = 0;
enable_interrupts(INT_EXT);
}
}
}
|
|
|
|
Ttelmah Guest
|
|
Posted: Sun Aug 10, 2008 2:46 am |
|
|
First comment is that this doesn't sound at all like 'I2C'. It sounds as if this is perhaps a logic based synchronous serial (more like the PS/2 protocol). Now, really the only answer is going to be to find out what it really is!....
However, if it is a synchronous clock based protocol, then I'd suggest cutting the interrupts to just one. The problem is that 100K, while not 'too fast' for the PIC to handle, _does_ require careful thought. If you can work out which edge of the clock corresponds to stable data, have just one interrupt, from this edge. Interrupts, cost a lot of time. If you are interrupting on both edges of something potentially changing at 100KHz, you have just 5uSec between these changes. The PIC won't handle this.
I'd suggest then, that you actually need to stay inside the data handler, when the active clock edge is received. Add a 'timeout', so if you miss an edge, the code will recover.
Though this goes against the 'keep interrupts as short as possible' mantra, at this sort of data rate, it is going to be needed.
So (In a sort of 'theoretical' form):
Code: |
#intxxxxx
void active_clock_edge(void) {
int16 data=0;
int16 mask=1;
int8 ctr;
int1 temp;
//Read the data ASAP
tmp=input_bit(DATA_BIT);
//Now set a timer, to timeout after perhaps 1.5 character times
set_timerx(count);
clear_interrupts(INT_TIMERX);
//Program a bit statement, to access the interrupt flag for this timer
//as TimerxIF
if (tmp) data|=mask; //Put the first bit into the result
for (ctr=0;ctr<8;ctr++) {
//Now 8 more bits to handle
while (input_bit(CLOCK_BIT)==ACTIVE) {
if (TimerxIF) return; //Timeout if interrupt flag is set
}
//Now wait for the clock to go active again
while (input_bit(CLOCK_BIT)!=ACTIVE) {
if (TimerxIF) return; //Again timeout
}
mask<<=1; //setup the mask, and this rotation, according to the
//order the bits arrive
if (input_bit(DATA_BIT)) data|=mask;
}
//Here set a flag that 'data' has arrived, and copy the received character
//to a temporary store.
}
|
Now, you will have to work out what timer to use for the timeout, what edge to set the interrupt to, and what levels are the 'active' ones etc., and generate the real code, but this is the sort of approach needed to receive such a data stream.
Best Wishes |
|
|
Guest
|
|
Posted: Sun Aug 10, 2008 12:33 pm |
|
|
Actually, the ext0 is for the enable. ext1 is for the clock. The enable goes low for a couple of milliseconds, during which the clock and data line do their thing. I'm only changing the trigger edge for the enable, to know when the packet starts and ends.
The clocks interrupt is always positive edge triggered. The clock is a 100kHz signal, but its duty cycle is probably only 20% or less. The rising edge of the clock occurs in the center of a data bit.
There is also a delay between groupings of 9 clocks. I don't have the scope in front of me right now, but Im pretty certain this delay is longer than 90 us, the duration of one byte.
But what you've laid out makes sense.
Quote: | //Program a bit statement, to access the interrupt flag for this timer
//as TimerxIF |
So for timer0, I would do some thing like this?
#define TIMER0IF bit_test(INTCON,5) |
|
|
Guest
|
|
Posted: Sun Aug 10, 2008 2:13 pm |
|
|
This is what the first byte looks like on a scope
Code: | ___
ENA |____________________________________________ ....
CLK_______|___|___|___|___|___|___|___|___|________ ....
___ ___ _______
DAT_________| |___| |___| |______________ ....
0 1 0 1 0 1 1 0 0
|
001101010 = 0x006A |
|
|
Ttelmah Guest
|
|
Posted: Sun Aug 10, 2008 3:10 pm |
|
|
#define TIMER0IF bit_test(INTCON,5)
No, I'd just define a bit.
so:
#bit TIMER0IF=INTCON.5
I'd use the rising edge of the clock then, to sample ASAP. Given the delays getting into the interrupt, it may still be borderline.
Best Wishes |
|
|
Guest
|
|
Posted: Sun Aug 10, 2008 8:03 pm |
|
|
How can you calculate the total propagation delay of the interrupt, meaning the time between the signal changing, and the interrupt service routine starting? |
|
|
Ttelmah Guest
|
|
Posted: Mon Aug 11, 2008 2:40 am |
|
|
Count the instructions.
Normally the instruction at address 8, executes, a maximum of 14.25 clocks after the event. You then have the code to save the internal registers, which is slightly 'worse' on a 18chip, but then reduced a little by the presence of the RETFIE 1 instruction, which allows three registers to be skipped. Typically 15 double length instructions. Then the interrupt bit itself is tested, and it's enable, usually another 5 instruction times, before you arrive at the handler. So a total of about 155 clock cycles. Equivalent to just under 40 instruction times. With your clock, about 4.2uSec.
As you can see, this should be 'OK' with your clocks, but it doesn't leave a lot of spare time, especially if you leave the interrupt and return (it takes about as long to come out again), and code in the interrupt itself can take a surprising time.
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
|