The PulseOut Command is good for generating pulses if accuracy is not too important. However, if you need better accuracy and resolution, another solution is required. I needed to generate pulses in the 100 to 2500 us range and wanted an accuracy of +- 1us over this range. The code below is what I came up with. This code works on a midrange PIC16F690 operating at 8Mhz. However, it should work on any PIC, but may need some minor modifications.
How It Works:
Timer1 is loaded with a preset value based upon the variable passed to the sub routine. The timer is started and the pulse pin is set high. When timer1 overflows the timer1 interrupt flag bit (TMR1IF) is set. This causes the program to exiit the polling loop and set the pulse Pin off. The timer is then stopped and TMRIF flag is cleared and the sub ends.
Note: Pulse values < 4 will give unexpected results.
Results as measured with Saleae Logic Analyzer.
Pulse_Out_us (2500) Actual Pulse Width = 2501.375 us
Pulse_Out_us (1000) Actual Pulse Width = 1000.750 us
Pulse_Out_us (100) Actual Pulse Width = 100. 125 us
Pulse_Out_us (10) Actual Pulse Width = 10.125 us
;**************************************
; Example Code: Output an accurate pulse
; Author: William Roth 03/13/2015
; File: Pulse_Test.gcb
;**************************************
#chip 16F690,8
; ---- Define Hardware settings
; ---- Define I2C settings - CHANGE PORTS
#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_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
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 '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
Last edit: William Roth 2015-03-14
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
.
Generating Accurate Pulses (PIC)
The PulseOut Command is good for generating pulses if accuracy is not too important. However, if you need better accuracy and resolution, another solution is required. I needed to generate pulses in the 100 to 2500 us range and wanted an accuracy of +- 1us over this range. The code below is what I came up with. This code works on a midrange PIC16F690 operating at 8Mhz. However, it should work on any PIC, but may need some minor modifications.
How It Works:
Timer1 is loaded with a preset value based upon the variable passed to the sub routine. The timer is started and the pulse pin is set high. When timer1 overflows the timer1 interrupt flag bit (TMR1IF) is set. This causes the program to exiit the polling loop and set the pulse Pin off. The timer is then stopped and TMRIF flag is cleared and the sub ends.
Note: Pulse values < 4 will give unexpected results.
Results as measured with Saleae Logic Analyzer.
Pulse_Out_us (2500) Actual Pulse Width = 2501.375 us
Pulse_Out_us (1000) Actual Pulse Width = 1000.750 us
Pulse_Out_us (100) Actual Pulse Width = 100. 125 us
Pulse_Out_us (10) Actual Pulse Width = 10.125 us
Last edit: William Roth 2015-03-14