95 lines
3.2 KiB
C
95 lines
3.2 KiB
C
#include "timer.h"
|
||
#include "../App/clock.h"
|
||
|
||
// 外部引用的全局滴答/标志变量 (在 main.c 中定义)
|
||
extern volatile u16 ms_tick;
|
||
extern volatile bit alarm_flash_flag;
|
||
extern volatile u16 key_scan_timer;
|
||
|
||
/* =========================================================================
|
||
* Timer0:自由运行硬件时间戳基准
|
||
* ========================================================================= */
|
||
|
||
// Timer0 溢出次数,扩展 16 位硬件计数为 32 位软件时间戳的高位部分
|
||
static volatile u16 timer0_ovf_count = 0;
|
||
|
||
void Timer0_Init(void)
|
||
{
|
||
TMOD &= 0xF0; // Timer0 模式位清零 -> Mode 0 (STC 上为 16 位不停表计数)
|
||
TL0 = 0;
|
||
TH0 = 0;
|
||
ET0 = 1; // 开启 Timer0 溢出中断允许
|
||
TR0 = 1; // 启动 Timer0 计数,此后永不停止 (全局 EA 由 Timer1_Init() 统一开启)
|
||
}
|
||
|
||
/**
|
||
* @brief Timer0 溢出中断服务程序 (每约 32.768ms 触发一次)
|
||
* @details 只做计数扩展,不做任何耗时操作,保持中断尽量短。
|
||
*/
|
||
void Timer0_Isr(void) interrupt 1
|
||
{
|
||
timer0_ovf_count++;
|
||
}
|
||
|
||
u32 Timer0_GetTimestamp(void)
|
||
{
|
||
u16 ovf1, ovf2;
|
||
u8 h1, h2, l;
|
||
do {
|
||
ovf1 = timer0_ovf_count;
|
||
h1 = TH0;
|
||
l = TL0;
|
||
h2 = TH0;
|
||
ovf2 = timer0_ovf_count;
|
||
} while (h1 != h2 || ovf1 != ovf2);
|
||
return ((u32)ovf1 << 16) | ((u16)h1 << 8) | l;
|
||
}
|
||
|
||
/* =========================================================================
|
||
* Timer1:系统 1ms 基准滴答
|
||
* ========================================================================= */
|
||
|
||
// 主循环按键扫描定时标志 (由 1ms 中断置 1,主循环响应清除),定义详见 event.h 的 extern 声明
|
||
volatile bit key_scan_flag = 0;
|
||
|
||
void Timer1_Init(void)
|
||
{
|
||
AUXR |= 0x40; // 设定定时器 1 为 1T 模式 (无分频,主频直接输入)
|
||
TMOD &= 0x0F; // 设置定时器 1 模式寄存器,保留低四位 (定时器0配置)
|
||
{
|
||
// 按照系统主频 (MAIN_Fosc) 计算 1ms 对应的重装载值
|
||
u16 reload = (u16)(65536UL - (MAIN_Fosc / 1000UL));
|
||
TL1 = (u8)reload; // 载入低 8 位
|
||
TH1 = (u8)(reload >> 8);// 载入高 8 位
|
||
}
|
||
ET1 = 1; // 开启定时器 1 中断允许
|
||
TR1 = 1; // 启动定时器 1 计数
|
||
EA = 1; // 开启全局中断允许
|
||
}
|
||
|
||
/**
|
||
* @brief 定时器 1 中断服务程序 (每 1ms 触发一次)
|
||
* @details 承担系统软时钟计算,并每 10ms 置位主循环按键扫描标志,不直接在中断中进行 ADC 多次采样。
|
||
*/
|
||
void Timer1_Isr(void) interrupt 3
|
||
{
|
||
// 1ms 递增全局滴答计数器 (0~999 循环),供各 App 的呼吸灯/闪烁/超时等周期性效果使用
|
||
ms_tick++;
|
||
if (ms_tick >= 1000) {
|
||
ms_tick = 0;
|
||
}
|
||
|
||
// 1ms 定时更新软时钟
|
||
Clock_IncMS();
|
||
|
||
// 报警屏幕红边框以 100ms 周期亮灭,进行颜色爆闪指示
|
||
alarm_flash_flag = (ms_tick / 100) % 2;
|
||
|
||
/* 物理按键定时计数 (每 10ms 置位一次标志位) */
|
||
key_scan_timer++;
|
||
if (key_scan_timer >= 10) {
|
||
key_scan_timer = 0; // 重置扫描分频计数器
|
||
key_scan_flag = 1; // 仅在中断里置起标志位,留待主循环中执行实际读取与消抖
|
||
}
|
||
}
|