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 over EUSART and with a LED.
Part |
---|
PIC18F47Q10 Curiosity Nano (or DIP IC) |
Two breadboard-compatible SPST buttons |
LED and an appropriate current-limiting resistor (or the onboard LED) |
Study the following critical information and concepts
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 |
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
EUSART
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
printf()
Example:
t= 45.34s
Note: It is bad practice to put printf() or sprintf() functions in a callback because it takes so much time to process.
In this section you will be implementing software-based debounce logic to ensure that button pushes are not over-counted. We will create “interrupt on change” (IOC) handling that will run code whenever it detects a button-push, and use the
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
**Identify the way to map callback functions to interrupts. **Open pin_manager.h
. Find and note the name for the function that links callback functions to each of the two pins selected for your pushbutton switches. There should be two functions available, one for each pin you configured in MCC.
Create your first IOC callback. Create a function pin_down() above main. it should return type void and take no input variables.
In the main() function, link the new pin_down() function using the first callback linking function found earlier. This should be done before enabling interrupts
Create your second callback. Create a function pin_up() above main. it should return type void and take no input variables.
In the main() function, link the new pin_up() function using the first callback linking function found earlier. This should be done before enabling interrupts
Write custom callback code. In pin_down() and pin_up() implement custom code that captures the current time that each button push occurs and save it into a new global variable.
Implement the debounce logic. 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 still being pushed.
If the above two are both true, and if the current time reaches some internal delay (in a non-blocking way)
Fills and prints a string with the current duty cycle, starting with “DC=” and ending in “%” using printf()
.
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.
Download and compile your code and demonstrate