The goal of this tutorial is to reintroduce you to the timer subsystem, implement a timer using an interrupt-based design, convert your pushbuttons from prior tutorials to interrupt-based functionality, and verify the results on your LCD.
This assignment builds off the LCD and Button Tutorial, with minor hardware modifications. Thus it is suggested that you keep all the components on the board as they were from that tutorial.
The two exceptions are the two pushbutton pins. You will need to shift to using GPIO registers that support interrupt-on-change (IOC). See critical information section above for details.
If you haven’t completed the LCD and pushbuttons tutorial, we strongly suggest you review that first.
Critical Information and Concepts | Importance |
---|---|
In TMRX.h, find the name of the function that permits the user to define a custom callback function | We will be defining and using a custom callback function that runs whenever the timer interrupt is fired. |
In the PIC18F47Q10 Datasheet, identify which GPIO pins can be used to trigger interrupts. Look for “IOC” or Interrupt-on-Change to learn more | Can you use any GPIO pin to trigger an input-based interrupt? |
In the Microchip MPLab Code Configurator User’s Guide, determine what WPU and OD stand for. WPU is explained better on this page that discusses setting up GPIO. Look up the explanation for OD by searching for “ODC Registers” on this page to understand its use for a different PIC family. | Determine the correct GPIO settings for I/O pins, as well as the best way to use these options in conjunction with a pushbutton switch. |
In this tutorial on sprintf(), determine what library(or libraries) you need to include | You will need to format a string. |
Read through this tutorial on interrupts in MCC to understand how linking a callback works | You will need to create custom callbacks to process incoming interrupts |
Search for “how to print the % character with sprintf()” | % is a special character and thus needs something special |
Open the MPLabX project from the LCD and Button Tutorial, and comment out the lines of code for incrementing and decrementing the PWM duty cycle in main(). This will be done in a different way.
or
Launch MPLAB® X and create a new project for your PIC IC.
Open MCC and update the following settings:
Please use MCC Classic. We can support it better, it has more advanced configuration options, but is also still relatively easy to use.
System
TMRX:
Pin Manager: Grid View
Pin Module
System Interrupts Page
Generate the MCC configuration and compile the project.
Open TmrX.h
Open “main.c”
If set up correctly, your new callback function should be called once every millisecond
Custom callback code: Now, create a new global variable, initializing it to zero, for storing the time in milliseconds. Create a second global variable (also initialized to zero) to store the time in seconds.
Note: This code should work if the time in ms is any value over than 1 second.
Note 2: This code should be written so as it doesn’t reset, clear, truncate, or lose time information.
In the while loop in main(), add code that
Example:
"t= 45.34s "
Note: the blank spaces within quotes correspond to valid lcd positions
Note: It is bad practice to put printf() or sprintf() functions in a callback because it takes so much time to process.
This section assumes you have set up IOC-based interrupts in MCC and generated a new configuration file as specified in the MCC setup section above
Open pin_manager.h
Create a function pin_down() above main. it should return type void and take no input variables.
In the main() function,
Create a function pin_up() above main. it should return type void and take no input variables.
In the main() function,
Custom Callback code
In the while loop in main(), add code that:
checks the current time against the time the up or down buttons were pushed.
checks whether those buttons are currently pushed
if the above two are true, increments or decrements the duty cycle (once and only once) if the current time reaches some internal delay (in a non-blocking way). Resets this check if the buttons ever change state before reaching their limit
Fills a 16-character string with the current duty cycle, starting with “DC=” and ending in “%”
prints that string to the bottom line of the LCD.
Example:
"t= 45.34s "
"dc= 75% "
Note: It is bad practice to put printf() or sprintf() functions in a callback because it takes so much time to process.