Home/Support/Support Forum/How to pulse an output
Welcome to Digi Forum, where you can ask questions and receive answers from other members of the community.

How to pulse an output

+1 vote

We're using BL4S200 boards and I need to pulse some outputs for short periods of time (on demand, not a periodic signal). Resolution must be in the 10th of microseconds range (e.g. a pulse of 100┬Ás).

Having access to a kind of high resolution counter would have been nice, but it seems we only have a counter in the millisecond range.

What would be the best way of doing that?

Thank you
asked Mar 9 in Rabbit by STR New to the Community (8 points)

Please log in or register to answer this question.

2 Answers

+1 vote
Here's a sleep function based on Timer C. It's not optimized, there's no bound checking, but it can be used as a starting point. The code is based on the sample file "TIMER_C_INT.c". Some definitions are in this file.
void SleepUs(word delayUs) { float timerCDivIdeal = (((float)delayUs/1000.0) * (float)MAIN_PCLK_FREQUENCY / 16. / 1000. - 1.); // The actual timer C divider value is rounded to an unsigned long integer type. unsigned long timerCDivider = (unsigned long)(timerCDivIdeal + 0.5); // ensure timer C is disabled WrPortI(TCCSR, &TCCSRShadow, 0x00); WrPortI(TCDLR, NULL, (int)(0xff & timerCDivider)); WrPortI(TCDHR, NULL, 0xff & (timerCDivider/0x100)); timerc_count = 0; // enable timer C WrPortI(TCCSR, &TCCSRShadow, 0x01); // enable timer C while (timerc_count < 1) { } WrPortI(TCCSR, &TCCSRShadow, 0x00); // disable timer C } int main(void) { int i; unsigned long start, end; printf("Rabbit's peripheral clock frequency is taken to be %.4f MHz.\n", MAIN_PCLK_FREQUENCY / 1.e6); printf("The ideal (to 2 decimal places) timer C divider value is %.2f.\n", TIMERC_DIVIDER_IDEAL); printf("The actual timer C divider value used herein is %lu.\n", TIMERC_DIVIDER); printf("If perfect clocks, an approximate %.4f%% count error is expected.\n", (TIMERC_DIVIDER_IDEAL / TIMERC_DIVIDER - 1.) * 100.); // ensure timer C is disabled WrPortI(TCCSR, &TCCSRShadow, 0x00); // set up timer C to use pclk/16 WrPortI(TCCR, &TCCRShadow, 0x09); // install timer C's ISR SetVectIntern(TIMERC_OFS / 0x10, timerC_isr); // The very first call is not accurate, because there's an extra interrupt. SleepUs(1000); // Now let's busy-wait many times to check if it's accurate enough. start = MS_TIMER; for (i = 0; i < 500; ++i) { SleepUs(1000); } end = MS_TIMER; printf("time elapsed == %lu ms timerc_count=%lu\n", end - start, timerc_count); }
answered Mar 10 by STR New to the Community (8 points)
0 votes
At that resolution/duration, I'd say to write assembly code flagged as "__nodebug", with interrupts disabled at the start and restored at the end.

Hopefully you won't have anything else that will mind getting blocked for the duration of the pulse.

Take a look a the code referencing __numcycles_1us in "BLxS2xx.LIB" to see how it calculates delays.

You could also investigate the use of a Timer C interrupt to trigger code that will turn off the output after a specified time. This would avoid blocking other processes waiting for the duration of the pulse to end. Take a look at Samples/TIMERC/TIMER_C_INT.c for an example of a periodic interrupt in the millisecond range. You'd have to read through the Rabbit documentation on how to configure Timer C so that you can get a one-shot interrupt of a higher-resolution duration.

The other two samples in that directory demonstrate use of Timer C to control an output pin. It may be possible to use Timer C to generate a single pulse of a specific duration without any need to trigger an interrupt and execute code.
answered Mar 9 by TomCollins Veteran of the Digi Community (2,222 points)
I'll try with Timer C, thank you