Second Counter Timer

I developed a program to display a real-time second counter on the LCD. I declared an integer variable initialized at zero and used a loop.

IntermediateFull instructions provided1 hour29
Second Counter Timer

Things used in this project

Hardware components

Standard LCD - 16x2 White on Blue
Adafruit Standard LCD - 16x2 White on Blue
×1
STM32F7 Series
STMicroelectronics STM32F7 Series
×1
Female/Female Jumper Wires
Female/Female Jumper Wires
×1
Male/Female Jumper Wires
Male/Female Jumper Wires
×1
Male/Male Jumper Wires
×1
Rotary potentiometer (generic)
Rotary potentiometer (generic)
×1
Breadboard (generic)
Breadboard (generic)
×1
USB Cable, USB Type C Plug
USB Cable, USB Type C Plug
×1

Software apps and online services

STM32CUBEPROG
STMicroelectronics STM32CUBEPROG

Story

Read more

Schematics

STM32F407ZGT6-based Development Board Schematic Diagram

Schematic diagram for GPIO pins

Pinout Configuration in STM32CubeIDE

This is where you setup your GPIO pins

16x2 LCD Schematic Diagram

For wiring connections

Code

main.c

C/C++
This is the generated main.c file by STM32CubeIDE
#include "main.h"
#include "stm32f4xx_hal.h"
#include <stdio.h>
#include <string.h>

/* LCD pins (PA0..PA5) */
#define LCD_RS_Port GPIOA
#define LCD_RS_Pin  GPIO_PIN_0
#define LCD_EN_Port GPIOA
#define LCD_EN_Pin  GPIO_PIN_1
#define LCD_D4_Port GPIOA
#define LCD_D4_Pin  GPIO_PIN_2
#define LCD_D5_Port GPIOA
#define LCD_D5_Pin  GPIO_PIN_3
#define LCD_D6_Port GPIOA
#define LCD_D6_Pin  GPIO_PIN_4
#define LCD_D7_Port GPIOA
#define LCD_D7_Pin  GPIO_PIN_5

/* prototypes */
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void lcd_init(void);
static void lcd_send_cmd(uint8_t cmd);
static void lcd_send_data(uint8_t data);
static void lcd_print(const char *s);
static void lcd_set_cursor(uint8_t row, uint8_t col);
static char keypad_get_label(void);

/* small helpers */
static void lcd_delay(uint32_t ms) { HAL_Delay(ms); }

static void lcd_enable_pulse(void)
{
    HAL_GPIO_WritePin(LCD_EN_Port, LCD_EN_Pin, GPIO_PIN_SET);
    lcd_delay(1);
    HAL_GPIO_WritePin(LCD_EN_Port, LCD_EN_Pin, GPIO_PIN_RESET);
    lcd_delay(1);
}

static void lcd_write4(uint8_t nibble)
{
    HAL_GPIO_WritePin(LCD_D4_Port, LCD_D4_Pin, (nibble & 0x01) ? GPIO_PIN_SET : GPIO_PIN_RESET);
    HAL_GPIO_WritePin(LCD_D5_Port, LCD_D5_Pin, (nibble & 0x02) ? GPIO_PIN_SET : GPIO_PIN_RESET);
    HAL_GPIO_WritePin(LCD_D6_Port, LCD_D6_Pin, (nibble & 0x04) ? GPIO_PIN_SET : GPIO_PIN_RESET);
    HAL_GPIO_WritePin(LCD_D7_Port, LCD_D7_Pin, (nibble & 0x08) ? GPIO_PIN_SET : GPIO_PIN_RESET);
    lcd_enable_pulse();
}

static void lcd_send_cmd(uint8_t cmd)
{
    HAL_GPIO_WritePin(LCD_RS_Port, LCD_RS_Pin, GPIO_PIN_RESET);
    lcd_write4((cmd >> 4) & 0x0F);
    lcd_write4(cmd & 0x0F);
    lcd_delay(2);
}

static void lcd_send_data(uint8_t data)
{
    HAL_GPIO_WritePin(LCD_RS_Port, LCD_RS_Pin, GPIO_PIN_SET);
    lcd_write4((data >> 4) & 0x0F);
    lcd_write4(data & 0x0F);
    lcd_delay(2);
}

static void lcd_print(const char *s)
{
    while (*s) lcd_send_data((uint8_t)*s++);
}

static void lcd_set_cursor(uint8_t row, uint8_t col)
{
    uint8_t addr = (row == 0) ? (0x80 + col) : (0xC0 + col);
    lcd_send_cmd(addr);
}

static void lcd_init(void)
{
    lcd_delay(50);
    // wake sequence
    lcd_write4(0x03); lcd_delay(5);
    lcd_write4(0x03); lcd_delay(5);
    lcd_write4(0x03); lcd_delay(1);
    lcd_write4(0x02); // 4-bit mode
    // config
    lcd_send_cmd(0x28); // 4-bit, 2 lines
    lcd_send_cmd(0x0C); // display on, cursor off
    lcd_send_cmd(0x06); // entry mode
    lcd_send_cmd(0x01); // clear
    lcd_delay(5);
}


int main(void)

{

  HAL_Init();                      // Initialize HAL (resets peripherals, SysTick, etc.)

  SystemClock_Config();            // Configure the system clock

  MX_GPIO_Init();                  // Initialize GPIO pins for LCD


  lcd_init();                      // Initialize LCD in 4-bit mode

  lcd_print("Timer (sec):");       // Print static label on Line 1


  uint32_t counter = 0;            // Counter variable for seconds

  char buffer[16];                 // Buffer to hold converted string for LCD output


  while (1)                        // Infinite loop

  {

    lcd_send_cmd(0xC0);            // Move cursor to Line 2, position 0

    sprintf(buffer, "%lu", counter); // Convert counter value into string

    lcd_print(buffer);             // Print the counter value on LCD


    HAL_Delay(1000);               // Delay 1 second

    counter++;                     // Increment counter each second

  }

}

/* ---------------- System and GPIO initialization ---------------- */

void SystemClock_Config(void)
{
    // Minimal HSI clock config. Replace with CubeMX generated clock if you have it.
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
    HAL_RCC_OscConfig(&RCC_OscInitStruct);
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_HCLK|
                                  RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
}

static void MX_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* enable clocks */
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOD_CLK_ENABLE();
    __HAL_RCC_GPIOE_CLK_ENABLE();
    __HAL_RCC_GPIOG_CLK_ENABLE();

    /* LCD PA0..PA5 output */
    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|
                          GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    HAL_GPIO_WritePin(GPIOA, GPIO_InitStruct.Pin, GPIO_PIN_RESET);

    /* Keypad rows: PD10, PD8 (GPIOD) */
    GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_8;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_10|GPIO_PIN_8, GPIO_PIN_SET); // idle HIGH

    /* Keypad rows: PE14, PE12 (GPIOE) */
    GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
    HAL_GPIO_WritePin(GPIOE, GPIO_PIN_14|GPIO_PIN_12, GPIO_PIN_SET); // idle HIGH

    /* Keypad cols: PE13, PE11 as inputs with pull-up */
    GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    /* Keypad cols: PG6, PG7 as inputs with pull-up */
    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
}

main.h

C/C++
A header file that contains all the important declarations and definitions needed by main.c
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.h
  * @brief          : Header for main.c file.
  *                   This file contains the common defines of the application.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */

/* USER CODE END ET */

/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */

/* USER CODE END EC */

/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */

/* USER CODE END EM */

/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);

/* USER CODE BEGIN EFP */

/* USER CODE END EFP */

/* Private defines -----------------------------------------------------------*/

/* USER CODE BEGIN Private defines */

/* USER CODE END Private defines */

#ifdef __cplusplus
}
#endif

#endif /* __MAIN_H */

Credits

JUNIE JEBREEL BOTAWAN
1 project • 0 followers
JARMAINE MESBAHODDIN ABDUL
0 projects • 0 followers

Comments