#include "stm32c0xx_hal.h"
// Define pins for digits and segments
#define DIGIT_1_PIN GPIO_PIN_0
#define DIGIT_2_PIN GPIO_PIN_1
#define DIGIT_3_PIN GPIO_PIN_2
#define DIGIT_4_PIN GPIO_PIN_3
#define DIGIT_PORT GPIOD
#define SEG_A_PIN GPIO_PIN_0
#define SEG_B_PIN GPIO_PIN_1
#define SEG_C_PIN GPIO_PIN_2
#define SEG_D_PIN GPIO_PIN_3
#define SEG_E_PIN GPIO_PIN_4
#define SEG_F_PIN GPIO_PIN_5
#define SEG_G_PIN GPIO_PIN_6
#define SEG_DP_PIN GPIO_PIN_7
#define SEGMENT_PORT GPIOA
// Precompute digit enable patterns and segment patterns with decimal points
const uint16_t DIGIT_ENABLE[4] = {DIGIT_1_PIN, DIGIT_2_PIN, DIGIT_3_PIN, DIGIT_4_PIN};
uint8_t segment_patterns[4] = {0}; // Precomputed patterns for each digit
// Segment patterns for digits 0-9 (common anode - inverted logic)
const uint8_t digit_patterns[10] = {
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90
};
float counter_value = 0.005f;
const float COUNTER_INCREMENT = 5.5f;
uint8_t current_digit = 0;
uint32_t last_display_update = 0;
uint32_t last_counter_update = 0;
void update_display_buffer() {
uint16_t value;
uint8_t dp_pos;
if (counter_value < 10.0f) {
value = (uint16_t)(counter_value * 1000.0f);
dp_pos = 0;
} else if (counter_value < 100.0f) {
value = (uint16_t)(counter_value * 100.0f);
dp_pos = 1;
} else if (counter_value < 1000.0f) {
value = (uint16_t)(counter_value * 10.0f);
dp_pos = 2;
} else {
value = (uint16_t)counter_value;
dp_pos = 4; // No decimal point
}
// Extract digits and precompute segment patterns
segment_patterns[0] = digit_patterns[value / 1000];
segment_patterns[1] = digit_patterns[(value / 100) % 10];
segment_patterns[2] = digit_patterns[(value / 10) % 10];
segment_patterns[3] = digit_patterns[value % 10];
// Enable decimal point in the precomputed pattern if needed
if (dp_pos < 4) {
segment_patterns[dp_pos] &= ~(1 << 7);
}
}
void setup() {
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
// Configure digit pins as output
GPIO_InitStruct.Pin = DIGIT_1_PIN | DIGIT_2_PIN | DIGIT_3_PIN | DIGIT_4_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DIGIT_PORT, &GPIO_InitStruct);
// Configure segment pins as output
GPIO_InitStruct.Pin = SEG_A_PIN | SEG_B_PIN | SEG_C_PIN | SEG_D_PIN |
SEG_E_PIN | SEG_F_PIN | SEG_G_PIN | SEG_DP_PIN;
HAL_GPIO_Init(SEGMENT_PORT, &GPIO_InitStruct);
// Turn off all digits initially
HAL_GPIO_WritePin(DIGIT_PORT, DIGIT_1_PIN | DIGIT_2_PIN | DIGIT_3_PIN | DIGIT_4_PIN, GPIO_PIN_RESET);
update_display_buffer();
}
void loop() {
uint32_t now = HAL_GetTick();
// Display update with direct register access
if (now - last_display_update >= 2) { // Reduced to 2ms for brighter display
// Turn off current digit using direct register access
DIGIT_PORT->BRR = DIGIT_ENABLE[current_digit];
// Move to next digit
current_digit = (current_digit + 1) & 0x03;
// Set segments for new digit
SEGMENT_PORT->ODR = (SEGMENT_PORT->ODR & 0xFF00) | segment_patterns[current_digit];
// Enable new digit using direct register access
DIGIT_PORT->BSRR = DIGIT_ENABLE[current_digit];
last_display_update = now;
}
// Counter update
if (now - last_counter_update >= 1000) {
counter_value += COUNTER_INCREMENT;
// Correct roll-over logic
if (counter_value > 9999.999f) {
counter_value = 0.005f;
}
update_display_buffer();
last_counter_update = now;
}
}
int main(void) {
HAL_Init();
setup();
while (1) {
loop();
}
}