How to Use the PIC16F15244 Family as an I/O Expander for More Design Flexibility: 7 Segment Display Demo
Microchip’s PIC16F15244 family controls a 7-segment display directly, saving I/O and power dissipation in the main MCU
The 7-segment display is a classic display technology, commonly used to show everything from time to counter values. Each display is composed of an array of LEDs which form each of the display segments. Two of the biggest challenges with these types of displays are the number of I/O needed and the amount of current to sink or source into each segment. By using the PIC16F15244 as an I/O expander, the power dissipation and quantity of I/O required by the main microcontroller are reduced.
The PIC16F15244 device family, can be used to drive the display directly due to the strong sinking and sourcing capabilities of the device, so long as the I/O current is kept within the limits defined in the device datasheet.
• Arduino Uno
> 7-segment display
- Before use, please check to see if this display is common anode or common cathode. The instructions below cover any changes that need to be made to the software to ensure the display operates as expected.
- Generally, a common-anode display can pass more output current than a common-cathode display due to the stronger low-side I/O drivers.
> Current limiting resistors
- Each segment of the display must be protected with an individual current limiting resistor to prevent the LEDs from burning out. The resistor value required will vary depending on the size of the display, the desired brightness and the emitted wavelength.
• Jumper wire for connections
The Arduino-Compatible Library for this software, along with the required firmware for the PIC16F15244 family device is available on Github. Inside the Github repository, there are 2 software examples:
• 123_gettingStarted – Displays “1 2 3” on the display. This code is a good starting point to tinker with.
• Countdown Timer – The display shows a 10 second countdown timer with a reset button.
See Figure 1. Demo Wiring Guide
Important: Program the device before connecting RA0 and RA1 to GND.
Wiring to Arduino Uno
• SDA – A4
• SCL – A5
• INT – Pin 2
Countdown Timer Setup Code
Important: Before continuing, be sure to program the PIC16F15244 device with the “Advanced I2C Expander” Code Example and install the communication library (located in the same repository)!
For this example, pins 6 – 0 are the outputs to the 7-segment display. Pin 7 is a connection to a push-button which resets the countdown timer.
On start, the program resets the device to the default settings that the device was compiled with. The other configuration steps are blocked until the INT line is asserted by the device, which indicates that the settings have been applied and the device is ready for more I2C communication.
On PIC® MCU devices, the TRIState (TRISx) register controls the direction of the I/O. If a bit is set to 0, then it is an output, while a 1 indicates the pin is an input. For this example, TRISx, where the x indicates the I/O PORT that is being controlled by the example, should be set to 0x80 (in binary: 0b1000 0000) to control the display and utilize the pushbutton.
For the pushbutton to operate correctly, the button needs to be pulled-up to Vdd when the button is not pressed. This ensures the button is at a logic 1 when idle. When the button is pressed, the button connects the I/O line to ground, which causes the line to fall to a logic 0. To achieve this without adding an extra resistor, the internal weak pull-up (WPUx) resistors are turned on for this I/O line.
Next, the interrupt events need to be setup for the I/O expander. There are two possible interrupt sources when running – interrupt on change (IOC), (rising edges (IOCxP) or falling edges (IOCxN)) and memory operation completion. In the case of this example, the only interrupt (after the initial reconfiguration) is when the button is pressed (IOCxN) or when the button is released (IOCxP). By default, the falling edge is used, however using the released edge is also a valid configuration. Both events can be enabled at the same time, however the status register does not differentiate between the two.
Setting Up the Display
If the display used is a common-anode display, then the device sinks current when the segments are on. With a common-cathode display, the inverse is true. In order to turn off the LEDs, it is necessary for the I/O lines to be at the inverse of the ON state. Table 1 shows the relationship in more detail.
See Table 1. Segment Display States
Alternatively, the lines could be tri-stated (TRISx) to turn them off, however it is more power efficient and better practice to change the output logic level (LATx) due to leakage current.
Countdown Timer Looping Code
Note: Before running this example, please select the function to match the type of display in use.
In the loop, the program checks for a flag that is set when the interrupt (INT) line goes low, indicating a change in state for the pushbutton. When this flag is set, the IOC register is cleared by reading it, and the counter is reset to 10.
If the counter is not 0, then (counter – 1) is shown on the display. When the counter equals 0, then the display flashes at 2 Hz while showing 0, as shown in figure 2.
This code example shows one way that the I/O expander can be used to simplify a larger and more complex system. Creating this functionality without an I/O expander would add at least 5 additional I/O lines to the main microcontroller. The saved I/O lines could be used to add more features or to use a physically smaller microcontroller.
The final blog post in this series will cover using the I/O Expander to create a keypad controller.