#include <Arduino.h>
// Global variables
volatile uint16_t centiseconds = 0;
volatile bool running = false;
// Hardware Timer object for STM32
HardwareTimer *MyTim;
// Segment map for 0-9 (Common Cathode)
// DP G F E D C B A
const uint8_t segment_map[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
// --- ISR 1: External Interrupt (Push Button) ---
void buttonISR() {
static uint32_t last_interrupt_time = 0;
uint32_t interrupt_time = millis();
// Simple software debounce
if (interrupt_time - last_interrupt_time > 200) {
running = !running;
}
last_interrupt_time = interrupt_time;
}
// --- ISR 2: Timer Interrupt (10ms Time Base) ---
void timerISR() {
if (running) {
centiseconds++;
if (centiseconds > 9999) centiseconds = 0; // Reset at 99.99
}
}
void setup() {
// 1. Configure Segment Pins (D0-D7 and D12)
pinMode(D0, OUTPUT); pinMode(D1, OUTPUT); pinMode(D12, OUTPUT);
pinMode(D3, OUTPUT); pinMode(D4, OUTPUT); pinMode(D5, OUTPUT);
pinMode(D6, OUTPUT); pinMode(D7, OUTPUT);
// 2. Configure Digit Selection Pins (D8-D11)
pinMode(D8, OUTPUT); pinMode(D9, OUTPUT);
pinMode(D10, OUTPUT); pinMode(D11, OUTPUT);
// 3. Configure Button with External Interrupt (ISR 1)
pinMode(D2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(D2), buttonISR, FALLING);
// 4. Configure Hardware Timer (ISR 2)
// Set frequency to 100Hz (10ms period)
MyTim = new HardwareTimer(TIM3);
MyTim->setOverflow(100, HERTZ_FORMAT);
MyTim->attachInterrupt(timerISR);
MyTim->resume();
}
void refreshDisplay() {
uint8_t d[4] = {
(uint8_t)((centiseconds / 1000) % 10),
(uint8_t)((centiseconds / 100) % 10),
(uint8_t)((centiseconds / 10) % 10),
(uint8_t)(centiseconds % 10)
};
for (int i = 0; i < 4; i++) {
// Clear all digits (Active HIGH for Common Cathode off)
digitalWrite(D8, HIGH); digitalWrite(D9, HIGH);
digitalWrite(D10, HIGH); digitalWrite(D11, HIGH);
uint8_t segs = segment_map[d[i]];
if (i == 1) segs |= 0x80; // Add Decimal Point for 88.88 format
// Write segments
digitalWrite(D0, (segs & 0x01)); digitalWrite(D1, (segs & 0x02) >> 1);
digitalWrite(D12, (segs & 0x04) >> 2); digitalWrite(D3, (segs & 0x08) >> 3);
digitalWrite(D4, (segs & 0x10) >> 4); digitalWrite(D5, (segs & 0x20) >> 5);
digitalWrite(D6, (segs & 0x40) >> 6); digitalWrite(D7, (segs & 0x80) >> 7);
// Turn ON current digit (Active LOW for selection)
digitalWrite(D8 + i, LOW);
delay(2);
}
}
void loop() {
refreshDisplay();
}