1.3.5 IOC Without a Timer
Modules | Limit High | Resolution |
---|---|---|
IOC | 4.194s | 2.75 μs |
This method is similar to the interrupt-on-change with a timer, with the exception that it uses the system clock to count, and not a timer.
OVERVIEW
This provides a “cheap” method in determining the width of a pulse. The user must wait for a rising edge to be detected and then increment a register until a second rising interrupt is detected. This measures the period. A rising edge, and then subsequent falling edge measurement, will be saved and then subtracted from the period to get the pulse width.
SETUP
Steps to measure the period:
- Configure one of the IOC pins to interrupt on rising edge (IOCBP)
- Set the pin as a digital input
- Set up any variable so that it will count
‘
T
’ (Figure 2) without overflowing - Start incrementing the temporary variable
(
period_count
) - When the IOC flag is set, clear it and
save the count variable into a temporary variable (
temp1
) - Continue incrementing count variable
- When the interrupt flag is set again,
clear it and save the count variable into another temporary variable
(
temp2
) - Period is
now:
Period = temp2 - temp1
IOC without Timer Period Setup and Operation Code
Configure IOC Pins (Step 1) IOCBP = 0x20; // Sets Interrupt on rising edge of RB5 Input Pin Setup (Step 2) TRISBbits.TRISB5 = HIGH; // Set RB5 as a digital input uint24_t period_count = 0; // Set up a variable to count the period (Step 3) while(!IOCBFbits.IOCBF5){ // Wait for IOC flag to set (Step 4) period_count = period_count + 1; // Increment period_count (Step 4) } IOCBFbits.IOCBF5 = 0; // Clear IOC flag (Step 5) temp1 = period_count; // Save period_count value into temp1 (Step 5) while(!IOCBFbits.IOCBF5){ // Wait for IOC flag to set (Step 6) period_count = period_count + 1; // Increment period_count (Step 6) } IOCBFbits.IOCBF5 = 0; // Clear IOC flag (Step 7) temp2 = period_count; // Save period_count value into temp2 (Step 7)
Steps to measure the pulse:
- Configure one of the IOC pins to interrupt on rising edge (IOCBP)
- Set the pin as a digital input
- Set up any variable so that it will count
‘
W
’ (Figure 2) without overflowing - Start incrementing the temporary variable
(
pulse_count
) - When the IOC flag is set, clear it and
save the timer into a temporary variable (
temp1
) - Configure the pin to interrupt on falling edge (IOCBN)
- When the interrupt flag is set again,
clear it and save the count variable into another temporary variable
(
temp2
) - Pulse width is
now:
MeasuredPulse = temp2 - temp1; while(MeasuredPulse>Period) MeasuredPulse -= Period;
IOC without Timer Pulse Setup and Operation Code
Configure IOC Pins (Step 1) IOCBP = 0x20; // Sets Interrupt on rising edge of RB5 Input Pin Setup (Step 2) TRISBbits.TRISB5 = HIGH; // Set RB5 as a digital input uint24_t pulse_count = 0; // Set up a variable to count the pulse (Step 3) while(!IOCBFbits.IOCBF5){ // Wait for IOC flag to set (Step 4) pulse_count = pulse_count + 1; // Increment pulse_count (Step 4) } IOCBFbits.IOCBF5 = 0; // Clear IOC flag (Step 5) temp1 = pulse_count; // Save pulse_count value into temp1 (Step 5) Configure IOC Pins (Step 6) IOCBP = 0x00; // clear Interrupt on rising edge of RB5 IOCBN = 0x20; // Set Interrupt on falling edge of RB5 while(!IOCBFbits.IOCBF5){ // Wait for IOC flag to set (Step 6) pulse_count = pulse_count + 1; // Increment pulse_count (Step 6) } IOCBFbits.IOCBF5 = 0; // Clear IOC flag (Step 7) temp2 = period_count; // Save period_count value into temp2 (Step 7)
LIMITATIONS
Since this implementation is in C, there is a greater number of instructions needed compared to an assembly routine. The snippet in Disassembly of Two Lines of C Code is what is required to check if a pin is high and increment a variable if it is. Notice the amount of instructions required for just a couple of statements.
Disassembly of Two Lines of C Code
33: while(!IOCBFbits.IOCBF5){
// Wait for the the RB5 IOC Flag to be triggered
055B 2D66 GOTO 0x566
0566 017D MOVLB 0x3D
0567 1E9D BTFSS IOCBF, 0x5
0568 2D6A GOTO 0x56A
0569 2D6B GOTO 0x56B
056A 2D5C GOTO 0x55C
34: pulse_count = pulse_count + 1;
// While the RB5 IOC Flag is low, increment the pulse_count
055C 3001 MOVLW 0x1
055D 0140 MOVLB 0x0
055E 074F ADDWF pulse_count, W
055F 00CF MOVWF pulse_count
0560 3000 MOVLW 0x0
0561 3D50 ADDWFC 0x50, W
0562 00D0 MOVWF 0x50
0563 3000 MOVLW 0x0
0564 3D51 ADDWFC 0x51, W
0565 00D1 MOVWF 0x51
count
’ on each
instruction cycle is 20 instructions clocks, or rather 5 μs, if FOSC == 16MHz. If
the pulse occurred and the ‘count
’ register contains a value of 12, then the
pulse width is
then:Pulse Width = count*delay*InstructionTimer
Pulse Width = 12*20* 1/ (16MHz/4) = 60μs