Explanation:
The PulseOut
Command is a reliable method for generating pulses if accuracy is not critical,
the PulseOut
command uses a calculation of the clock to speed for the timing .
If you need better accuracy and resolution then an alternative approach is required.
To generate pulses in the 100 us to 2500 us range with an accuracy of +- 1us over this range is practical using the approach shown in this example.
This example code works on a midrange PIC16F690 operating at 8Mhz. However, it should work on any Microchip PIC microcontroller, but may need some minor modifications.
Usage:
Pulse_Out_us ( word_value )
How It Works:
Timer1
is loaded with a preset value based upon the variable passed to the sub routine.
The timer (Timer1
) is started and the pulse pin (the output pin) is set high.
When Timer1
overflows the Timer1 interrupt flag bit (TMR1IF
) is set. This causes the program to
exit a polling loop and set the pulse Pin off. Then, Timer1
is stopped and TMRIF
flag is cleared and the sub routine exits.
This method supports delays between 5 us and 65535 us and uses Timer1.
Test Results:
These tests were completed using a Saleae Logic Analyzer.
Pulse setting | Time Results |
---|---|
|
|
|
|
|
|
|
|
|
|
Demonstration program:
;************************************** ; Code: Output an accurate pulse ; Author: William Roth 03/13/2021 ;************************************** #chip 16F690,8 ; ---- Define Hardware settings ; ---- Define I2C settings - CHANGE PORTS AS REQUIRED #define I2C_MODE Master #define I2C_DATA PORTB.4 #define I2C_CLOCK PORTB.6 #define I2C_DISABLE_INTERRUPTS ON ; ---- Set up LCD - Using I2C LCD Backpack #define LCD_IO 10 #define LCD_WIDTH 20 ;specified lcd width for clarity only. 20 is the default width #define LCD_I2C_Address_1 0x4e ; default to 0x4E ; ---- May need to use SLOW or MEDIUM if your LCD is a slower device. #define LCD_SPEED Medium #define LCD_Backlight_On_State 1 #define LCD_Backlight_Off_State 0 CLS ; ---- USART settings #define USART_BAUD_RATE 38400 #define USART_TX_BLOCKING DIR PORTB.7 OUT ; ---- Setup Pulse parameters #define PulsePin PORTC.4 Dim Time_us As WORD Dir PulsePin Out 'Pulsout pin Set PulsePin off ; ---- Setup Timer InitTimer1 Osc, PS1_2 'For 8Mhz Chip 'InitTimer1 Osc, PS1_4, 'For 16 Mhz Chip TMR1H = 0: TMR1L = 0 'Clear timer1 TMR1IF = 0 'Clear timer1 int flag TMR1IE = on 'Enable timer1 Interrupt (Flag only) ' **** This is the MAIN loop ***** Do PULSE_OUT_US (2500) 'Measured as 2501.375 us wait 19 ms Pulse_Out_US (1000) 'Measured as 1000.750 us wait 19 ms Pulse_Out_US (100) 'Measured as 100.125 us wait 19 ms Pulse_Out_US (10) 'Measured as 10.125 us Wait 19 ms loop SUB PULSE_OUT_US (IN Variable as WORD) TMR1H = 65535 - Variable_H 'Timer 1 Preset High TMR1L = (65535 - Variable) + 4 'Timer 1 Preset Low Set TMR1ON ON 'Start timer1 Set PulsePin ON 'Set Pin high Do While TMR1IF = 0 'Wait for Timer1 overflow Loop Set PulsePin off ' Pin Low Set TMR1ON OFF ' Stop timer 1 TMR1IF = 0 'Clear the Int flag END SUB
Also see PulseOut