登录/注册

STM32 电子闹钟源码

更多

下面是一个基于STM32的电子闹钟源码示例(使用HAL库),包含时间显示、闹钟设置与触发功能。代码以STM32F103C8T6(Blue Pill开发板)为例,使用I2C OLED显示(SSD1306)和按键控制。

硬件配置


源码文件结构

/* 文件: main.c */
#include "stm32f1xx_hal.h"
#include "ssd1306.h"
#include "fonts.h"

// 硬件配置
#define KEY_SET_PIN        GPIO_PIN_0   // PA0 设置键
#define KEY_UP_PIN         GPIO_PIN_1   // PA1 加键
#define KEY_DOWN_PIN       GPIO_PIN_2   // PA2 减键
#define KEY_OK_PIN         GPIO_PIN_3   // PA3 确认键
#define BUZZER_PIN         GPIO_PIN_4   // PA4 蜂鸣器

// 全局变量
RTC_HandleTypeDef hrtc;
TIM_HandleTypeDef htim3; // 用于按键扫描
uint8_t display_mode = 0; // 0:时间, 1:设置时间, 2:设置闹钟
uint8_t alarm_enabled = 0;
uint8_t alarm_triggered = 0;
RTC_TimeTypeDef sTime = {0, 0, 0};    // 当前时间
RTC_DateTypeDef sDate = {0, 0, 0};    // 当前日期
RTC_TimeTypeDef alarmTime = {7, 0, 0}; // 默认闹钟07:00:00

// 函数声明
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_RTC_Init(void);
static void MX_TIM3_Init(void);
void update_display(void);
void handle_keys(void);
void check_alarm(void);
void beep(uint16_t duration_ms);

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_RTC_Init();
    MX_TIM3_Init();
    SSD1306_Init();

    HAL_TIM_Base_Start_IT(&htim3); // 启动按键扫描定时器

    while (1) {
        HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN); // 获取时间
        HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN); // 获取日期

        check_alarm();      // 检查闹钟触发
        update_display();   // 更新OLED显示
        HAL_Delay(100);     // 主循环延迟
    }
}

// 更新OLED显示
void update_display(void) {
    char buf[20];
    SSD1306_Clear();

    switch(display_mode) {
        case 0: // 显示时间
            sprintf(buf, "Time: %02d:%02d:%02d", sTime.Hours, sTime.Minutes, sTime.Seconds);
            SSD1306_GotoXY(0,0);
            SSD1306_Puts(buf, &Font_7x10, 1);

            sprintf(buf, "Date: %02d/%02d/%02d", sDate.Date, sDate.Month, sDate.Year);
            SSD1306_GotoXY(0,20);
            SSD1306_Puts(buf, &Font_7x10, 1);

            sprintf(buf, "Alarm: %02d:%02d %s", alarmTime.Hours, alarmTime.Minutes, 
                    alarm_enabled ? "ON" : "OFF");
            SSD1306_GotoXY(0,40);
            SSD1306_Puts(buf, &Font_7x10, 1);
            break;

        case 1: // 设置时间
            SSD1306_GotoXY(0,0);
            SSD1306_Puts("Set Time", &Font_11x18, 1);
            sprintf(buf, "%02d:%02d:%02d", sTime.Hours, sTime.Minutes, sTime.Seconds);
            SSD1306_GotoXY(10,30);
            SSD1306_Puts(buf, &Font_16x26, 1);
            break;

        case 2: // 设置闹钟
            SSD1306_GotoXY(0,0);
            SSD1306_Puts("Set Alarm", &Font_11x18, 1);
            sprintf(buf, "%02d:%02d %s", alarmTime.Hours, alarmTime.Minutes, 
                    alarm_enabled ? "ON" : "OFF");
            SSD1306_GotoXY(10,30);
            SSD1306_Puts(buf, &Font_16x26, 1);
            break;
    }
    SSD1306_UpdateScreen();
}

// 按键处理
void handle_keys(void) {
    static uint8_t setting_step = 0;

    if(HAL_GPIO_ReadPin(GPIOA, KEY_SET_PIN) == GPIO_PIN_RESET) {
        HAL_Delay(50); // 消抖
        if(HAL_GPIO_ReadPin(GPIOA, KEY_SET_PIN) == GPIO_PIN_RESET) {
            display_mode = (display_mode + 1) % 3;
            setting_step = 0;
        }
        while(HAL_GPIO_ReadPin(GPIOA, KEY_SET_PIN) == GPIO_PIN_RESET); // 等待释放
    }

    if(display_mode > 0) { // 设置模式
        if(HAL_GPIO_ReadPin(GPIOA, KEY_OK_PIN) == GPIO_PIN_RESET) {
            HAL_Delay(50);
            if(HAL_GPIO_ReadPin(GPIOA, KEY_OK_PIN) == GPIO_PIN_RESET) {
                setting_step = (setting_step + 1) % 3;
                if(display_mode == 2 && setting_step == 2) {
                    alarm_enabled = !alarm_enabled; // 切换闹钟开关
                }
            }
            while(HAL_GPIO_ReadPin(GPIOA, KEY_OK_PIN) == GPIO_PIN_RESET);
        }

        // 时间/闹钟调整
        if(HAL_GPIO_ReadPin(GPIOA, KEY_UP_PIN) == GPIO_PIN_RESET) {
            HAL_Delay(50);
            if(HAL_GPIO_ReadPin(GPIOA, KEY_UP_PIN) == GPIO_PIN_RESET) {
                switch(setting_step) {
                    case 0: // 时
                        if(display_mode == 1) sTime.Hours = (sTime.Hours + 1) % 24;
                        else alarmTime.Hours = (alarmTime.Hours + 1) % 24;
                        break;
                    case 1: // 分
                        if(display_mode == 1) sTime.Minutes = (sTime.Minutes + 1) % 60;
                        else alarmTime.Minutes = (alarmTime.Minutes + 1) % 60;
                        break;
                }
            }
            while(HAL_GPIO_ReadPin(GPIOA, KEY_UP_PIN) == GPIO_PIN_RESET);
        }

        if(HAL_GPIO_ReadPin(GPIOA, KEY_DOWN_PIN) == GPIO_PIN_RESET) {
            HAL_Delay(50);
            if(HAL_GPIO_ReadPin(GPIOA, KEY_DOWN_PIN) == GPIO_PIN_RESET) {
                switch(setting_step) {
                    case 0: // 时
                        if(display_mode == 1) sTime.Hours = (sTime.Hours + 23) % 24;
                        else alarmTime.Hours = (alarmTime.Hours + 23) % 24;
                        break;
                    case 1: // 分
                        if(display_mode == 1) sTime.Minutes = (sTime.Minutes + 59) % 60;
                        else alarmTime.Minutes = (alarmTime.Minutes + 59) % 60;
                        break;
                }
            }
            while(HAL_GPIO_ReadPin(GPIOA, KEY_DOWN_PIN) == GPIO_PIN_RESET);
        }

        // 确认设置时间
        if(display_mode == 1 && setting_step == 2) {
            HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
            display_mode = 0;
            setting_step = 0;
        }
    }
}

// 检查闹钟触发
void check_alarm(void) {
    if(alarm_enabled && !alarm_triggered && 
       sTime.Hours == alarmTime.Hours && 
       sTime.Minutes == alarmTime.Minutes &&
       sTime.Seconds == 0) {

        alarm_triggered = 1;
        HAL_GPIO_WritePin(GPIOA, BUZZER_PIN, GPIO_PIN_SET); // 蜂鸣器开启

    } else if(alarm_triggered && sTime.Seconds > 10) { // 响铃10秒
        alarm_triggered = 0;
        HAL_GPIO_WritePin(GPIOA, BUZZER_PIN, GPIO_PIN_RESET); // 关闭蜂鸣器
    }
}

// 定时器3中断(按键扫描)
void TIM3_IRQHandler(void) {
    if(__HAL_TIM_GET_FLAG(&htim3, TIM_FLAG_UPDATE)) {
        __HAL_TIM_CLEAR_FLAG(&htim3, TIM_FLAG_UPDATE);
        handle_keys();
    }
}

// RTC初始化(使用LSI)
static void MX_RTC_Init(void) {
    hrtc.Instance = RTC;
    hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
    hrtc.Init.OutPut = RTC_OUTPUTSOURCE_ALARM;
    if(HAL_RTC_Init(&hrtc) != HAL_OK) Error_Handler();
}

// 其他初始化代码(时钟、GPIO、TIM3等)需根据标准库补充
// 完整工程需包含ssd1306.c/fonts.c等文件

关键功能说明

  1. 时间管理

    • 使用STM32内置RTC(通过LSI驱动)
    • 支持时间/日期读取和设置
  2. 闹钟功能

    • 独立存储闹钟时间(alarmTime结构体)
    • 使能标志(alarm_enabled)
    • 整点触发蜂鸣器10秒
  3. 用户界面

    • OLED显示:时间/日期/闹钟状态
    • 四按键控制
      • SET键:切换模式(时间显示→设置时间→设置闹钟)
      • UP/DOWN:调整数值
      • OK键:确认设置/切换闹钟开关
  4. 蜂鸣器控制

    • GPIO直接驱动(需三极管放大)

使用说明

  1. 硬件连接

    • OLED: SCL→PB6, SDA→PB7
    • 按键: PA0~PA3(下拉电阻)
    • 蜂鸣器: PA4(低电平触发)
  2. 操作流程

    • 短按SET键循环切换显示模式
    • 在设置模式下:
      • UP/DOWN键调整小时/分钟
      • OK键切换设置项(时→分→确认)
      • 闹钟模式下OK键可开关闹钟
  3. 校准RTC

    • 因LSI精度有限,需在MX_RTC_Init()中调整异步分频值
    • 建议使用外部32.768kHz晶振提高精度

完整工程需包含SSD1306驱动库和字体库(常用fonts.c/hssd1306.c/h可从开源项目获取)。开发环境推荐使用STM32CubeIDE。

觉醒时刻:电子闹钟功耗大探索 | 老陆测功耗08

氛围的显眼包……为避免这尴尬的场景,是时候深入了解下电子闹钟的功耗与续航性能。叮铃铃~正片来啦今天我们一起来看看电子

2024-07-09 08:04:45

RT-thread源码移植到STM32F10x和STM32F4xx

RT-thread源码移植到STM32F10x和STM32F4xx: 一、源码

2023-11-15 09:38:59

闹钟的ESD整改案例

前言:闹钟(clock)是带有闹时装置的钟。既能指示时间,又能按人们预定的时刻发出音响信号或其他信号。闹钟的机芯结构主要有机械式和石英电子式两大

2023-06-08 09:39:03

STM32F407 DCMI摄像头源码

STM32F407 DCMI摄像头源码(电源技术存在的问题总结)-【资源描述】:STM32F407 DCMI摄像头

资料下载 h1654155275.0032 2021-09-16 16:15:00

DAPLINK和STM32最小系统组合源码

DAPLINK和STM32最小系统组合源码下载。

资料下载 姚小熊27 2021-06-04 14:32:34

电子闹钟源码文件下载

电子闹钟源码文件下载

资料下载 苏车把 2021-05-17 09:53:49

STM32单片机网络远程升级固件的源码下载

STM32单片机网络远程升级固件的源码下载

资料下载 罗程123 2021-04-17 09:27:26

基于VerilogHDL的LED数字电子时钟程序及源码

基于VerilogHDL的LED数字电子时钟程序及源码

资料下载 Tred 2021-04-06 14:05:05

如何利用atmega16实现电子闹钟的设计?

如何利用atmega16实现电子闹钟的设计?

2022-01-24 06:13:54

STM32F103实现简易闹钟小程序的过程分享

前言开发板:正点原子 STM32F103 精英版语言:C语言开发环境:Keil5使用了 KEY LED LCD RTC FLASH(用于存储闹钟信息) BEEP(充当闹铃)代码下载:码云GitHub

2022-01-18 07:26:52

STM32L4待机模式闹钟唤醒方法

STM32L4待机模式闹钟唤醒方法在很多低功耗应用中都会用到待机模式,而在使用待机模式的同时一定要用STM32的RTC功能,一般都是秒级别的。在

2022-01-13 07:27:23

如何让STM32闹钟程序每天固定时间醒来呢

如何让STM32的闹钟程序每天固定时间醒来呢?

2021-11-26 07:58:34

如何唤醒STM32L4的待机模式闹钟

如何唤醒STM32L4的待机模式闹钟?

2021-11-23 06:29:48

STM32F103上的RTC闹钟中断功能以及用闹钟中断唤醒STM32的待机模式

RTC代表的是实时时钟的意思。因为它提供的时钟基准比较准确所以用处还是很多的。本文章主要讲解基于STM32F103上的RTC闹钟中断功能以及用闹钟

2021-08-13 07:29:06

浅谈STM32_RTC闹钟

STM32_RTC闹钟

2020-04-08 11:14:22

7天热门专题 换一换
相关标签