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, 2021 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, 2021 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, 2021 by TomCollins Veteran of the Digi Community (2,311 points)
I'll try with Timer C, thank you