PIC32 Microcontroller

Developed bare-metal C firmware for the PIC32MX795F512L (MIPS32 M4K core, 80 MHz, 512 KB flash, 128 KB RAM) running on the Beti PIC32 Training Board. Used direct Special Function Register (SFR) manipulation for two independent peripherals with no RTOS or HAL.
Stack & Toolchain
| Layer | Choice |
|---|---|
| Language | C (C89 dialect via mikroC) |
| IDE / Compiler | mikroC PRO for PIC32 |
| Programmer | mikroBootloader (USB HID, v2.1.1.0) |
| Hardware | Beti PIC32 Egitim Seti (PIC32MX795F512L) |
| Output artifact | .hex (Intel HEX format, flashed over USB HID) |
The build pipeline is source → mikroC compile → .hex → mikroBootloader → on-chip flash.
DC Motor Control
Direction logic is controlled by two pushbuttons on Port E mapped to Port A outputs:
- Button 0 pressed → counterclockwise
- Button 1 pressed → clockwise
- Both pressed → motor stopped (explicit interlock)
SFRs configured:
AD1PCFG = 0xFFFF; // disable analog input on all pins (digital mode)
TRISA = 0x0000; // Port A → output (motor control signals)
TRISE = 0x00FF; // Port E → input (button reads)
Reading PORTE and writing LATA avoids read-modify-write hazards on shared port registers. The main loop continuously polls the buttons and updates the motor control signals accordingly.
Seven-Segment Display
Computed and displayed $f(x) = x^3$ for $x = 1 \text{ to } 21$ on a 4-digit multiplexed seven-segment display.
Multiplexing approach: only one digit is physically active at any instant. The firmware cycles through all four digit-select lines fast enough (~1 kHz effective refresh) which makes the display appear static. Stopping the loop on any digit would leave only that digit lit.
Implementation breakdown:
// Segment pattern LUT — index is digit 0–9, value is active-low segment bitmap
const unsigned char seg_patterns[10] = { 0x3F, 0x06, 0x5B, 0x4F, 0x66,
0x6D, 0x7D, 0x07, 0x7F, 0x6F };
// Decompose n into individual digits for each display position
void decompose(unsigned int n, unsigned char digits[4]) { ... }
// Multiplex loop — runs inside a timed outer loop per x value
for (pos = 0; pos < 4; pos++) {
DIGIT_SELECT = (1 << pos); // enable one digit
SEGMENT_PORT = seg_patterns[d[pos]];
Delay_ms(2); // ~500 Hz per digit → 125 Hz full refresh
SEGMENT_PORT = 0x00; // blank before switching (prevents ghosting)
}
After displaying 9261 ($x = 21$), the sequence wraps back to x = 1. This was implemented as a modulo on the loop counter rather than a restart, so there’s no flash or discontinuity at the boundary.