Continue to Site

# 16 bit timer values

Status
Not open for further replies.

#### robmitch

##### New Member
hi all,
I am trying to use a 16-bit timer to get the time between rising edges on an input pin. I am going to use the capture/compare mode. What I am stuck on is the C syntax to ge the 16-bit timer value ie: I want to calculate the time in seconds (or milliseconds) using:

Timer elapsed time (s) = (Capture value -Start value)*Prescale/Sys Clock frequency (Hz)

where the Cature and Start values are the 16-bit values made from the high and low 8-bit values. What would the code look like?

float fElapsedTime = ( ??? - ??? )*64/18432000;

Also, how do I get the reverse (load values into the timer high and low reload registers) based on a time ie say 0.025s...
Rob

#### Pommie

##### Well-Known Member
To capture the values you would use an int and do,
Code:
unsigned int val1;
val1=(ccpr1l+(ccpr1h<<8));

once you have captured 2 values you simply do,
Code:
    elapsed = val2-val1;

If you want to put it in a float then just put the above in your parentheses.

I don't quite understand what you mean my in reverse? Are you wanting to generate a pulse?

Mike.

#### robmitch

##### New Member
Mike,
THANKS.
I meant how to get from a float to ccpr1l & ccpr1h

Aside from that, maybe I should tell you what I am trying to do... No doubt someone will know how best to do it.

I am trying to take a PPM signal from an RC transmitter into the mc, then output a PPM signal which is the same as the input with two channels modified.

See here for PPM signal format:

R/C PPM encoding - MFTech

What I was thinking of was using a capture/compare timer and interrupt on the rising edge of the input pin.

Elsewhere, I will be using clock cycles to use sensor input to get the information/pulsewidth I need for the two new channels.

I effectively want to pass through the first 6 channels (probably by relaying the rising edges to the output pin), then I want to generate/change the remaining pulses by using another timer.

I wanted the code snippet to get the incoming pulse width to print to the screen for debugging etc.

Any ideas would be appreciated.
Regards,
Rob

EDIT:
I just realised that I wouldnt be able to simply relay the rising edge of the incoming signal to the output - I need to see the falling edge and put it out too... Obviously couldnt do that with a rising edge capture/compare timer.
Any thoughts on how best to do this problem?
Cheers,
Rob

Last edited:

#### Pommie

##### Well-Known Member
I had a play with this, I would do it something like this,
Code:
//with 8MHz int osc,

void WaitStart(){
intcon2.INTEDG0=1;      //interrupt on rising edge
intcon.INT0IF=0;        //int0 cleared
tmr1h=0;                //clear timer 1
tmr1l=0;
t1con=0x90;             //timer 1 prescaller 2 and RD16
while(!intcon.INT0IF);  //wait for edge
t1con.TMR1ON=1;         //start timer
}

int WaitFalling(){
intcon2.INTEDG0=0;      //interrupt on falling edge
intcon.INT0IF=0;        //int0 cleared
while(!intcon.INT0IF);  //wait for edge
t1con.TMR1ON=0;         //start timer
return(tmr1h<<8+tmr1l); //return time in uS
}

// in main code
unsigned int Length;
unsigned char i;
while(1){
do{
WaitStart();
Out=1;                 //copy to output pin
Length=WaitFalling();
Out=0;                 //copy
}while(Length<3000);       //until we find pulse longer than 3mS
for(i=0;i<6;i++){          //copy next 6 pulses to output
WaitStart();
Out=1;
Length=WaitFalling();
Out=0
}
//do other two channels here
}

This could be done on interrupt (and probably will have to be) but the above should get you started. I didn't set the IE bits and so no interrupts will be generated.

Note, totally untested and probably won't even compile.

Edit, above in BoostC format.

Mike.

Last edited:

#### robmitch

##### New Member
Mike,
Thanks so much. I will have a think about putting it together with interrupts.
Regards,
Rob

#### Pommie

##### Well-Known Member
I would try getting it to measure and pass through the pulses first before trying to make it interrupt driven.

Mike.

Last edited:

#### robmitch

##### New Member
Well, I have achieved my intermediate goal!

I started simple - using a pin that gave an interrupt on either the rising or falling edge, I simply relayed the rising and fallling edges to another output gpio pin by setting it high/low. I then used a timer to time the delay between the rising and falling interrupts, and added some logic to see if the delay was greater than 3ms (thanks mike) to notify the start of the PPM frame, and count the current input channel.

Then, I started to modify the output signal, by only relaying the first 6 channel pulses to the output, and using another timer to create my own channels 7 & 8. I made the delay for each pulse based on a fixed number that I could increment/decrement with keyboard strokes to the terminal. The servos on the receiver side would all work - the first 6 channels controllable with the transmitter, and the next two controllable by the micro.

Now, I want to make channel 7 (the first of my new channels) delay based on the output of my compass sensor, which is connect to the micro via UART1 (UART0 is the terminal connection). See thread for details of compass module, which now communicates with the micro properly:

My problem now is that whenever I turn on the compass module, the servos on my receiver side start to twitch slightly, meaning that the PPM signal is either being garbled occasionally or the pulse widths are changing from frame to frame. I think it is the later, because I can see the outgoing PPM signal on the scope (I cant see enough detail to see if the pulse widths are changing though, they just look the same)

Anyone got some ideas? I have set the input PPM pin interrupt to high (and I do the relaying/signal modification inside the interrupt), so this should be a priority and shouldnt be upset by a silly uart happening in the background, but it is.

I have tried the uart in both interrupt and polling mode, and still the same. I was going to try to make the compass module spit out a single reading each time the PPM frame start pulse starts (gives a good 5-10ms of time where nothing is happening), although the update rate of the compass is only 30Hz, so it wouldnt be able to keep up with that.

The highest comm rate for the compass module is 9600BAUD, which I am using.

I dont have any twitching issues with UART0 operational and transmitting to the terminal (but do have issues when it receives my keyboard strokes).

Any known issues like this using uart recieving and real-time signals?
Cheers,
Rob

#### Pommie

##### Well-Known Member
Sounds like the uart is doing something with the interrupts. It could be disabling them for accurate timing, using them to feed a fifo or something else. You could setup the hardware directly and write your own routines, or, if your background program isn't doing anything else then you could implement a software uart which would solve the problem.

Mike.

#### robmitch

##### New Member
Thanks Mike,
Surely other people wouldnt tolerate it, if the uart was messing with other interrupts set with high priority? Oh well.

What do you mean by setting up hardware directly vs a software uart? What would be a description of a hardware setup?
Cheers,
Rob

#### Pommie

##### Well-Known Member
Hi rob,

I'm assuming from your other thread that you are using the Zilog chip and so I can't really help on the hardware as I don't know it. I suggest you look at the data sheet and see how to setup the uart hardware yourself (rather than use a library). If your interrupt functions are being messed up by a polled uart then the library functions must be somehow effecting the interrupt.

mike.

#### robmitch

##### New Member
Oops,
Low voltage fed to regulator.... It works now. I think the uart was getting continual break interrupts or something similar.
Cheers,
Rob

Status
Not open for further replies.

Replies
18
Views
566
Replies
0
Views
420
Replies
0
Views
520
Replies
11
Views
2K
Replies
5
Views
386