STM8S 系列 MCU 的 Timer5 是一個 16 位通用定時器,支援定時中斷、輸入捕獲 (測脈寬/頻率)、輸出比較等模式。本文提供模組化驅動頭文件與源文件,涵蓋基礎定時、輸入捕獲初始化、通道使能、方向選擇、中斷控制,並附帶主程式調用示例。
timer5.h
#ifndef _TIMER5_H_
#define _TIMER5_H_
#include "global.h" // 假設定義 uint8, uint16, ENB, DIS, SETB0 等
// 分頻係數枚舉 (PSCR 值)
#define TIM5_DIV1 0
#define TIM5_DIV2 1
#define TIM5_DIV4 2
#define TIM5_DIV8 3
#define TIM5_DIV16 4
#define TIM5_DIV32 5
#define TIM5_DIV64 6
#define TIM5_DIV128 7
// 中斷源掩碼
#define TIM5_UPD_IT 0x01 // 更新中斷
#define TIM5_CC1_IT 0x02 // 通道1 捕獲/比較
#define TIM5_CC2_IT 0x04
#define TIM5_CC3_IT 0x08
// 計數方向
#define TIM5_DIR_UP 0
#define TIM5_DIR_DOWN 1
// API 聲明
extern void TIM5_Init_Base(uint16_t arr, uint8_t psc); // 定時器模式初始化
extern void TIM5_Init_InputCapture(void); // 輸入捕獲模式初始化
extern void TIM5_Channel_Cmd(uint8_t ch_mask, uint8_t en); // 通道使能/禁止
extern void TIM5_Set_Direction(uint8_t ch, uint8_t dir); // 設置捕獲邊沿方向
extern void TIM5_IT_Cmd(uint8_t it_mask, uint8_t en); // 中斷使能/禁止
extern void TIM5_Cmd(uint8_t en); // 定時器總開關
#endif
timer5.c 關鍵實現
void TIM5_Init_Base(uint16_t arr, uint8_t psc) {
TIM5_EGR = 0x00; // 禁止更新事件產生
TIM5_PSCR = psc; // 設置分頻 (PSCR=4 → 16分頻)
TIM5_ARRH = (arr >> 8) & 0xFF; // 自動重裝載值高位
TIM5_ARRL = arr & 0xFF; // 低位
TIM5_CNTRH = 0; TIM5_CNTRL = 0; // 計數器歸零
TIM5_CR1 = 0x00; // CR1: CEN=0 (暫不啟動), UDIS=0 (允許更新)
}
void TIM5_Init_InputCapture(void) {
// 1. 先禁止所有通道
TIM5_CCER1 &= ~(0x01 | 0x10); // CC1E=0, CC2E=0
TIM5_CCER2 &= ~0x01; // CC3E=0
// 2. 配置捕獲模式: 邊沿檢測、濾波、預分頻
// CCMRx: ICxF=0000(無濾波), ICxPSC=00(無預分頻), CCxS=01(ICx映射到TIxFP1)
TIM5_CCMR1 = 0x31; // 通道1: 捕獲上升沿, 映射TI1
TIM5_CCMR2 = 0x32; // 通道2: 捕獲上升沿, 映射TI2 (或根據需求修改)
TIM5_CCMR3 = 0x31; // 通道3
// 3. 從模式控制器: 復位模式 (SMS=100)
TIM5_SMCR = 0x04;
// 4. 設置捕獲極性 (CCERx: CCxP/CCxNP)
TIM5_Set_Direction(TIM5_CC1_IT, TIM5_DIR_UP); // 通道1 上升沿
TIM5_Set_Direction(TIM5_CC2_IT, TIM5_DIR_DOWN); // 通道2 下降沿
TIM5_Set_Direction(TIM5_CC3_IT, TIM5_DIR_UP); // 通道3 上升沿
// 5. 使能通道 1,2
TIM5_Channel_Cmd(TIM5_CC1_IT | TIM5_CC2_IT, ENB);
}
void TIM5_IT_Cmd(uint8_t it_mask, uint8_t en) {
if (en) TIM5_IER |= it_mask;
else TIM5_IER &= ~it_mask;
}
void TIM5_Cmd(uint8_t en) {
if (en) {
TIM5_IT_Cmd(TIM5_UPD_IT, ENB); // 啟用更新中斷
TIM5_CR1 |= 0x01; // CEN=1 啟動計數器
} else {
TIM5_IT_Cmd(TIM5_UPD_IT, DIS);
TIM5_CR1 &= ~0x01;
}
}
#include "timer5.h"
void main(void) {
// 系統時鐘 16MHz,PSCR=4 (16分頻) → 計數頻率 1MHz (1us/拍)
// ARR=29 → 週期 30us 進入更新中斷
TIM5_Init_Base(30, TIM5_DIV16);
TIM5_Cmd(ENB); // 啟動定時器、使能更新中斷
while (1) {
// 主循環處理其他任務
}
}
// 中斷服務程序 (需在 stm8s_it.c 中實現)
/*
@far @interrupt void TIM5_UPD_IRQHandler(void) {
// 30us 週期任務
TIM5_SR1 &= ~0x01; // 清除更新標誌
}
*/
| 寄存器 | 關鍵位 | 說明 |
|---|---|---|
CR1 | CEN(bit0) | 計數器使能 |
PSCR | [3:0] | 預分頻器 (2^PSCR 分頻) |
ARRH/L | - | 自動重裝載值 (周期 = ARR+1) |
CNTRH/L | - | 計數器當前值 |
IER | UIE(0), CC1IE(1), CC2IE(2), CC3IE(3) | 中斷使能 |
SR1 | UIF(0), CC1IF(1), CC2IF(2), CC3IF(3) | 狀態標誌 (寫0清除) |
CCER1/2 | CCxE, CCxP, CCxNP | 捕獲/比較使能、極性 |
CCMR1/2/3 | CCxS, ICxF, ICxPSC | 捕獲模式選擇、濾波、預分頻 |
SMCR | SMS[2:0] | 從模式 (復位/門控/觸發) |