Bộ định thời TIM (Phần một)
- Bộ định thời (Timer) có thể đếm xung clock và tạo ngắt khi đạt giá trị đặt trước
- Đơn vị cơ bản gồm bộ đếm 16-bit, bộ chia tần số và thanh ghi tự động nạp lại, cho phép định thời tối đa 59.65s với clock 72MHz
- Cung cấp đa dạng chức năng: chọn nguồn clock, bắt giữ vào/ra, giao diện encoder, chế độ master-slave
- Phân loại: Bộ định thời cao cấp, phổ thông và cơ bản
Loại bộ định thời trên STM32F103C8T6
Bao gồm TIM1, TIM2, TIM3, TIM4 với đặc tính khác nhau
Cấu trúc hệ thống
Bộ định thời cơ bản
Sử dụng clock nội 72MHz, bộ chia tần số có thể chia tối đa 65536. Khi bộ đếm đạt giá trị trong thanh ghi tự động nạp, tín hiệu ngắt được phát và bộ đếm được đặt lại.
Bộ định thời phổ thông
Cấu hình TIM3 ở chế độ master để kích hoạt TIM2 thông qua ngõ ra TRGO. TIM2 được thiết lập ở chế độ clock ngoài để tạo hệ thống định thời nối tiếp.
Bộ định thời cao cấp
Thêm thanh ghi đếm lặp để mở rộng thời gian định thời lên gấp 65536 lần. Hỗ trợ 2 ngõ ra PWM bổ trợ với mạch tạo khoảng chết (dead time) để điều khiển động cơ không chổi than.
Nguyên lý ngắt định thời
Công thức tính tần số bộ đếm: CK_CNT = CK_PSC / (PSC + 1)
Tần số tràn bộ đếm: CK_CNT_OV = CK_CNT / (ARR + 1)
Cây tín hiệu clock (RCC)
Hệ thống phân phối tín hiệu clock đến các ngoại vi, là nền tảng cho mọi hoạt động phần cứng
Bộ so sánh đầu ra (Phần hai)
- Chức năng điều chế độ rộng xung (PWM) thông qua so sánh giá trị CNT và CCR
- Thông số PWM: Tần số = 1 / TS, Độ rộng = TON/TS, Độ phân giải = bước thay đổi độ rộng
- Mỗi kênh có khả năng tạo tín hiệu bổ trợ với mạch tạo khoảng chết (DTG) trên bộ định thời cao cấp
Ứng dụng thực tế
- Servo motor: Tín hiệu 20ms với xung cao 0.5-2.5ms điều khiển góc quay
- Động cơ DC: Cần mạch cầu H (TB6612) để điều khiển chiều quay và tốc độ
Bộ bắt giữ đầu vào (Phần ba)
- Ghi nhận giá trị bộ đếm khi phát hiện cạnh chuyển đổi trên ngõ vào
- Hỗ trợ đo tần số/độ rộng xung thông qua chế độ PWMI
- Chế độ master-slave cho phép tự động kích hoạt phần cứng
Nguyên lý đo tần số
Phương pháp đo tần số phù hợp tín hiệu cao, đo chu kỳ phù hợp tín hiệu thấp
Giao diện encoder (Phần tư)
- Xử lý tín hiệu encoder vuông pha để xác định vị trí, hướng và tốc độ
- Chế độ đếm tăng/giảm tự động dựa trên trạng thái tín hiệu A/B
- Kháng nhiễu thông qua phát hiện tín hiệu bất thường trên kênh đối nghịch
Ví dụ ứng dụng
Khi encoder quay phải: CNT tăng dần theo số xung, quay trái: CNT giảm tương ứng
Mã nguồn minh họa
Cấu hình ngắt định thời
void Timer_Init(void) {
// Kích hoạt clock TIM2 và GPIO
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// Cấu hình clock nội
TIM_InternalClockConfig(TIM2);
// Thiết lập tham số định thời
TIM_TimeBaseInitTypeDef timConfig;
timConfig.TIM_Prescaler = 7199;
timConfig.TIM_Period = 9999;
timConfig.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &timConfig);
// Xóa cờ ngắt và kích hoạt ngắt
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
// Cấu hình NVIC
NVIC_InitTypeDef nvicConfig;
nvicConfig.NVIC_IRQChannel = TIM2_IRQn;
nvicConfig.NVIC_IRQChannelPreemptionPriority = 2;
nvicConfig.NVIC_IRQChannelSubPriority = 1;
nvicConfig.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvicConfig);
// Kích hoạt bộ định thời
TIM_Cmd(TIM2, ENABLE);
}
// Hàm xử lý ngắt
void TIM2_IRQHandler(void) {
if (TIM_GetITStatus(TIM2, TIM_IT_Update)) {
counter++;
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
Cấu hình PWM
void PWM_Init(void) {
// Kích hoạt clock
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// Cấu hình chân PWM
GPIO_InitTypeDef gpioConfig;
gpioConfig.GPIO_Pin = GPIO_Pin_0;
gpioConfig.GPIO_Mode = GPIO_Mode_AF_PP;
gpioConfig.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpioConfig);
// Thiết lập tham số PWM
TIM_TimeBaseInitTypeDef timConfig;
timConfig.TIM_Prescaler = 719;
timConfig.TIM_Period = 99;
timConfig.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &timConfig);
// Cấu hình kênh so sánh
TIM_OCInitTypeDef ocConfig;
ocConfig.TIM_OCMode = TIM_OCMode_PWM1;
ocConfig.TIM_OutputState = TIM_OutputState_Enable;
ocConfig.TIM_Pulse = 90;
ocConfig.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &ocConfig);
// Kích hoạt PWM
TIM_Cmd(TIM2, ENABLE);
}
void PWM_SetDuty(uint16_t value) {
TIM_SetCompare1(TIM2, value);
}