HƯỚNG DẪN STM CƠ BẢN - B3

LẬP TRÌNH TIMER VỚI STM32

Author: Pham Cong Huy

GIỚI THIỆU

Timer là một ngoại vi được tích hợp trong hầu hết các dòng vi điều khiển, chức năng chính của timer là giúp xác định chính xác một khoảng thời gian, điều khiển xung đầu ra, đo và đếm xung đầu vào…

Đối với STM32F1 có tất cả 7 bộ timer trong đó có 1 systick timer (bộ timer của hệ thống thường được sử dụng trong các ứng dụng thời gian thực với RTOS), 2 watchdog timer (chức năng chính là đánh thức và khởi động lại vi điều khiển). Với 4 bộ timer từ TIM1 đến TIM4 còn lại sẽ được sử dụng với các chế độ như: Timer Base,PWM mode, One-pulse mode, Input Capture, Output Compare, Encoder… Trong đó TIM1 là bộ Timer điều khiển nâng cao chuyên phục vụ cho việc băm xung, xuất xung.

TIMER BASE

HOẠT ĐỘNG

Timer-Base là chế độ chính của Timer bao gồm các hoạt động đếm: lên, xuống hoặc cả lên lên và xuống.

Để xác định độ dài cho một xung clock chúng ta sẽ dựa vào tần số thạch anh sử dụng và bộ chia tần số Prescaler. Bộ chia 16bit tương ứng với giá trị là 65535. Các giá trị này có thể được thay đổi và điều chỉnh bằng lập trình. Các tính tần số của một xung clock nếu giá trị thạch không bị thay đổi bởi việc cấu hình các bộ chia tần số ở phần Clock Configuration như sau:


F(Clock) = F(Thạch anh) / Giá trị Prescaler

Đối với trường hợp ta cấu hình các bộ chia tần số thì F(thạch anh) lúc này sẽ lấy theo thông số sau cùng của các bộ APB1 và APB2 ở phần Clock Configuration của phần mềm cầu hình.
Counter Period sẽ là giá trị đếm tối đa tối đa, khi bộ định thời đếm qua giá trị này cờ tràn timer sẽ được bật. Giá trị này cũng số 16bit với ứng với giá trị tối đa là 65535.

Ví dụ: Chúng ta sử dụng thạch anh nội với tần số 8Mhz, nhập Prescaler với giá trị là 8000 và Counter Period là 999 với chế độ đếm lên. Thì chúng ta có thể tính được:

  • Fclock = 8Mhz / 8000 = 1 kHz tương ứng T = 1 ms.
  • Với Counter Period là 999, bộ định thời sẽ đếm từ 0 đến 999 tức là đã đếm 1000 xung với chu kì 1ms. Vậy bộ định thời đã xác định được 1 giây.

Sau khi hệ thống (ở đây là thanh ghi TIMx_CNT – Counter register) đếm đến giá trị Counter Period (thực chất là đếm từ giá trị [65535 - Counter Period] đến 65536) cờ báo tràn được bật lên, và chúng ta có thể lập trình dựa theo ứng dụng của việc báo tràn này.

CẤU HÌNH

Chúng ta sẽ cấu hình cho TIM2 với một ví dụ đơn giản là thực hiện nhấp nháy LED PC13 trong thời gian 1 giây.

Hãy tạo một project mới và đi vào bước configure:

Trong tab Pinout & Configuration ta sẽ mở mục Timers và chọn cấu hìn cho TIM2.

  • Clock Source: chọn Internal Clock.
  • Prescaler: nhập 8000
  • Counter mode: chọn Up
  • Auto-reload preload: Chọn Enable, đây là là việc cho phép nạp lại giá trị đếm vào thanh ghi sau khi báo tràn.

Picture1

Cũng trong tab Pinout & Configuration, tại mục System Core/NIVIC ta tích chọn Enable cho ngắt TIM2. Ngoài ra để nạp xuống chip thì trong mục SYS/Debug hãy chọn Serial Wire nhé.

Picture2

Còn một vấn để nữa chúng ta cần lưu ý là tần số của thạch anh nội sẽ được cấp cho Timer, chúng ta có thể cấu hình nó ở tab Clock Configuration.

Tại đây chúng ta hãy quan sát những ô được viền xanh thì có thể được chỉnh sửa. Hãy chú ý đến hai ô APB1 Timer clockAPB2 Timer clock. Đây là hai ô có thể hiệu chỉnh tần số mà hệ thống cấp cho bộ Timer (tần số tối đa có thể được cấp là 72Mhz). Trong đó APB2 dành cho TIM1 còn APB1 dành cho TIM2, TIM3, TIM4. Các bạn có thể hiệu chỉnh hai chỉ số này kết hợp với PrescalerCounter Period để có được khoảng thời gian cần định thời một cách chính xác.

Picture3

Tiếp theo đó hãy save file để có thể generate code.

HAL TIMER BASE FUNCTION

Hầu hết các hàm khởi tạo và cấu hình cho Timer đã được tạo sẵn sau bước Configure. Cho nên người lập trình chỉ cần lập trình ngắt timer cho hàm HAL_TIM_PeriodElapsedCallback(), đặt hàm ngay trước bên ngoài int main(void) trong file main.c và tiếng hành code cho nó.

Picture4

Tiếp theo trong hàm int main(void) trước hàm while(1) ta viết hàm.

HAL_TIM_BASE_START_IT(&htimx) đây là hàm khởi động timer với chức năng ngắt.

Picture5

Như vậy đã hoàn thành một ví dụ đơn giản với việc điều khiển LED PC13 với Timer Base.

TIMER INPUT CAPTURE MODE

GIỚI THIỆU

Ở chế độ này, timer sẽ đếm khoảng thời gian giữa hai lần bắt được xung cạnh lên hoặc cạnh xuống ở tín hiệu nhận được.

Picture6

Mode này hoạt động theo cách lưu lại giá trị đếm của Timer ở những lần xung lên hoặc xuống từ đó sẽ đo được độ rộng của xung, tần số của xung.

CẤU HÌNH

Để cấu hình cho chế độ này, ta chọn một timer, tại một channel mà ta muốn cấu hình, chọn Input Capture direct mode. Tiếp theo ta chỉnh sửa các giá trị Prescaler, Counter Mode, Counter Period phù hợp.

Picture7

Trong mục NIVI Setting ta tích chọn Enabled cho interrupt.

Picture8

Chúng ta có thể ứng dụng cấu hình này cho việc đo thời gian giữa hai lần nhấn nút.

FUNCTIONS

Một số hàm nên lưu ý khi thực hiện chế độ này như:

HAL_TIM_IC_Start (TIM_HandleTypeDef * htim, uint32_t Channel) có chức năng cho timer chạy với chế độ cơ bản không ngắt.

HAL_TIM_IC_Start_IT (TIM_HandleTypeDef * htim, uint32_t Channel) chức năng cho timer chạy ở chế độ có ngắt.

HAL_TIM_ReadCapturedValue(TIM_HandleTypeDef * htim, uint32_t Channel) chức năng là đọc giá trị đếm của timer từ khối Capture Compare, dành riêng cho hai mode Input Capture và Output Compare

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) đây là hàm để người lập trình tương tác, sửa chửa khi có tín hiệu ngắt từ việc bắt được xung lên hoặc xuống của tín hiệu.

 TIMER OUTPUT COMPARE

GIỚI THIỆU

Chế độ output Compare cho phép xuất xung ra khi các chân output tại thời điểm mà bộ đếm timer có giá trị bằng với giá trị được cài đặt trước đó.

Picture9

Cách hoạt động của chế độ này dựa trên việc so sánh giá trị đếm của bộ timer lưu ở thanh ghi CNT với CCR1 đã được người lập trình cài đặt giá trị. Khi hai giá trị này bằng nhau thì cho phép toggle giá trị tại chân vi điều khiển.

CẤU HÌNH

Việc cấu hình chế độ Output Compare cũng rất quen thuộc, ta chọn timer và channel sau chọn Output Compare CHx. Điều chỉnh các thông số Prescaler, Counter mode, Counter period phù hợp.

Picture10

Ngoài ra nếu muốn sử dụng chức năng ngắt với mode timer này ta hãy tích vào Enabled tại mục NIVIC Setting.

Picture11

FUNCTIONS

HAL_TIM_OC_Start (TIM_HandleTypeDef * htim, uint32_t Channel) có chức năng cho timer chạy và xuất xung ở chế độ cơ bản không ngắt.

HAL_TIM_IC_Start_IT (TIM_HandleTypeDef * htim, uint32_t Channel) chức năng cho timer chạy ở chế độ có ngắt.

void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) hàm cho người lập trình thao tác để xử lí khi có tín hiệu ngắt.

__HAL_TIM_SET_COUNTER(TIM_HandleTypeDef *htim, uint16_t value) Hàm có chức năng đặt lại giá trị đếm của bộ timer, ta sẽ thường sử dụng hàm này khi muốn cho thực hiện lặp đi lặp lại timer bằng cách cho giá trị value bằng giá trị ban đầu trước khi đếm. Có thể đặt hàm này trong hàm xử lí ngắt để thực hiện việc đếm lại.