Microhip has published a "Compiled Tips 'N Tricks Guide " that tells "how" to do certain tasks with PIC 8-Bit Microcontrollers. Instead of providing code in ASM or C, this document provides the steps that need to be taken to perform the task. This makes it relatively straight forward to adapt to GREAT COW BASIC.
In Chapter 3, Tip 3, the guide offers a tip on measuring pulse width using Timer 1 and a CCP module. I used this as the basis for the code that follows. However, I found that polling the CCP flag bit was more convenient than using an interrupt.
In this example, I used a PIC 16F1829 operating at 32 Mhz with its internal oscillator. The GCB code uses Timer 1 and CCP4. However, any one of the four CCP modules could be used. Another PIC was used to generate the pulses to be measured. A TEK THS730A Scope was used to measure/verify pulse widths.
The test setup uses a Cheap 4x20 LDC module with an I2C Backpack. However you could just as well use serial output to a terminal program to view the data.
Resolution: With the Timer Prescaler at 1:8 and the Chip Frequency at 32 MHz the pulse width resolution is 1 microsecond. With the Timer Prescaler at 1:2 and the ChiP Frequency at 32MHz the resolution is 250 nanoseconds.
Accuracy: Accuracy is dependent upon the accuracy of the system clock, but scope measurements show an accuracy of +- 1us from 3us to 1000us.
Note: For a real application I would suggest adding a line or two of code that polls the TIMER1 overflow flag. IF the timer overflows, then either no pulse was detected or the pulse was longer than allowed by the prescaler/OSC settings. In this case, return a value of zero for pulse width.
Here's the example code:
=================================================
#Chip 16F1829, 32
#CONFIG MCLRE = OFF
#define I2C_MODE Master
#define I2C_DATA PORTA.2
#define I2C_CLOCK PORTC.0
#define I2C_DISABLE_INTERRUPTS ON
'''Set up LCD
#define LCD_IO 10
#define LCD_SPEED FAST
#define LCD_Backlight_On_State 1
#define LCD_Backlight_Off_State 0
CLS
PRINT "Pulse Width Test"
DIM PULSE_WIDTH AS WORD
DIR PORTC.6 IN
InitTimer1 OSC, PS1_8 'Change to PS1_2 for 250ns resolution
wait 1 s
CLS
DO 'MAIN LOOP
PULSE_IN 'Get positive pulse width.
Locate 0,0: PRINT Pulse_Width: PRINT " "
wait 1 s
Loop
MACRO PULSE_IN 'Measure Pulse Width
'Configure CCP4 to Capture rising edge
CCP4CON = 5 '00000101
StartTimer 1
CCP4IF = 0
do while CCP4IF = 0 'Wait for rising edge
loop
TMR1H = 0: TMR1L = 0 'Clear timer to zero
CCP4IF = 0 'Clear flag
'Configure CCP4 to Capture Falling Edge
CCP4CON = 4 '00000100'
do while CCP4IF = 0 'Wait for falling edge
loop
StopTimer 1 'Stop the time
Pulse_Width = TIMER1 'Save the timer value
CCP4IF = 0 'Clear the CCP4 flag
End MACRO
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
A long belated thanks for this tip. I built a Grid Frequency Meter inspired by this suggestion and the design of that has been made the subject of an article in Elektor Magazine (July/August 2022).
I made sure to reference this page citing it as the basis of the frequency measuring portion of the code.
Thanks again.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Microhip has published a "Compiled Tips 'N Tricks Guide " that tells "how" to do certain tasks with PIC 8-Bit Microcontrollers. Instead of providing code in ASM or C, this document provides the steps that need to be taken to perform the task. This makes it relatively straight forward to adapt to GREAT COW BASIC.
In Chapter 3, Tip 3, the guide offers a tip on measuring pulse width using Timer 1 and a CCP module. I used this as the basis for the code that follows. However, I found that polling the CCP flag bit was more convenient than using an interrupt.
In this example, I used a PIC 16F1829 operating at 32 Mhz with its internal oscillator. The GCB code uses Timer 1 and CCP4. However, any one of the four CCP modules could be used. Another PIC was used to generate the pulses to be measured. A TEK THS730A Scope was used to measure/verify pulse widths.
The test setup uses a Cheap 4x20 LDC module with an I2C Backpack. However you could just as well use serial output to a terminal program to view the data.
Resolution: With the Timer Prescaler at 1:8 and the Chip Frequency at 32 MHz the pulse width resolution is 1 microsecond. With the Timer Prescaler at 1:2 and the ChiP Frequency at 32MHz the resolution is 250 nanoseconds.
Accuracy: Accuracy is dependent upon the accuracy of the system clock, but scope measurements show an accuracy of +- 1us from 3us to 1000us.
Note: For a real application I would suggest adding a line or two of code that polls the TIMER1 overflow flag. IF the timer overflows, then either no pulse was detected or the pulse was longer than allowed by the prescaler/OSC settings. In this case, return a value of zero for pulse width.
Here's the example code:
=================================================
Many thanks. I was looking at porting some code from another language that measures frequency. Your example will be an enourmous help.
Much appreciated.
A long belated thanks for this tip. I built a Grid Frequency Meter inspired by this suggestion and the design of that has been made the subject of an article in Elektor Magazine (July/August 2022).
I made sure to reference this page citing it as the basis of the frequency measuring portion of the code.
Thanks again.
Nice - well done.
Got a copy of the article?