Bài 04: TIMER BASE VỚI MXCUBE SỬ DỤNG STM32F303CC

  1. Giới thiệu sơ lược về EXTI.
  2. STM32f303CC có tất cả 13 timer nhưng trong đó đã bao gồm 1 systick timer, 2 watchdog timer. Vậy có 10 timer dùng cho các chức năng như ngắt, timer base, PWM, Encoder, Input capture…. Trong đó TIM1 và TIM8 là Timer đặc biệt, chuyên dụng cho việc xuất xung với các mode xuất xung, các mode bảo vệ đầy đủ hơn so với các timer khác. TIM1, TIM2, TIM3, TIM4, TIM8 là các timer có đầy đủ 4 channel còn các timer còn lại là timer nội hoặc không đầy đủ các channel.

    Có 3 vấn đề về thanh ghi cơ bản cần tìm hiểu trong bài này đó là :

    • Timer clock.
    • Prescaler.
    • Auto Reload Value.

    Prescaler là bộ chia tần số của timer. Bộ chia này có giá trị tối đa là 16 bit tương ứng với giá trị nạp vào là 65535. Các giá trị này có thể được thay đổi và điều chỉnh bằng lập trình. Tần số sau bộ chia này sẽ được tính là:

    fCK_CNT = fCK_PSC/(PSC+1).

    • FCK_CNT: tần số sau bộ chia.
    • fCK_PSC: tần số clock đầu vào cấp cho timer.
    • PSC: chính là giá trị truyền vào được lập trình bằng phần mềm.

    Auto Reload value là giá trị bộ đếm tối đa có thể được điều chỉnh để nạp vào cho timer. Giá trị bộ đếm này được cài đặt tối đa là 32 bit tương ứng với giá trị nạp vào là 4294967295. Tuy nhiên chỉ có timer 2 có được giá trị này, các timer khác đều có tối đa là 16 bit tương ứng với giá trị nạp vào là 65535. Từ các thông số trên ta rút ra công thức cần tính cuối cùng đó là:

    FTIMER= fSYSTEM/[(PSC+1)(Period+1)]

    • Ftimer : là giá trị cuối cùng của bài toán, đơn vị là hz.
    • F system : tần số clock hệ thống được chia cho timer sử dụng, đơn vị là hz.
    • PSC : giá trị nạp vào cho bộ chia tần số của timer. Tối đa là 65535.
    • Period : giá trị bộ đếm nạp vào cho timer. Tối đa là 65535.

    Ngắt tràn timer: khi giá trị đếm của bộ đếm timer(thanh ghi CNT) vượt qua giá trị của Auto Reload Value thì cờ báo tràn sẽ được kích hoạt. Trình phục vụ ngắt tràn sẽ xảy ra nếu được cấu hình cho phép trước đó.

  3. Tạo project với MXCUBE.
  4. Vd: chớp tắt led với chu kì 2s, 1 giây sáng, 1s tắt trên chân PB9, sử dụng ngắt tràn timer1.

    1. New project . Cửa sổ mới được mở ra. Chọn loại MCU theo tên hoặc theo họ, loại package… Ở đây mình nhớ tên luôn nên gõ vào cho nhanh STM32F303CC.
    2. Chọn loại MCU, Double click vào tên MCU được tìm thấy hoặc bấm vào Start project để bắt đầu quá trình cài đặt. Lưu project lại rồi bắt đầu cấu hình. Cấu hình thạch anh, chuẩn nạp trước tiên. Bài này sử dụng timer 1(Cấu hình ngắt tràn – internal clock) và 1 led (sử dụng chân PB9, output). Click chuột trái để chọn chức năng cho ngoại vi.Click chuột phải để tạo nhãn cho chân ngoại vi cho dễ nhìn.
    3. Cấu hình clock ở tab clock configuration. Tùy thuộc vào thạch anh sử dụng và các ứng dụng khác nhau mà chỉnh tốc độ clock ở các mode khác nhau. Ở đây mình đã sử dụng thạch anh 8Mhz nên có thể điều chỉnh tốc độ tối đa của HCLK là 72Mhz. Những chỗ nào mà chương trình cho phép thay đổi giá trị thì chỗ đó được phép thay đổi clock. Chúng ta có thể quan sát được đầu ra của tất cả các ngoại vi. Khá rõ ràng đúng không.
    4. Tab configuration . Chúng ta sử dụng GPIO và ngắt timer1 nên quan tâm đến tab GPIO, NVIC trong mục System ,Tim1 trong mục control. Các thông số như sau:
      1. Tab GPIO: Cấu hình chân LED này mình đã đề cập ở bài 02 nên phần này mình sẽ không đề cập nữa.
      2. Tab NVIC : cấu hình phần này mình đã đề cập trong bài 03. Chỉ lưu ý là phân chia mức độ ưu tiên ngắt cho phù hợp, tránh trùng lẫn các mức ưu tiên ngắt.
      3. Tab TIM1: Ở đây mình sử dụng ngắt tràn Timer1 nên sẽ có phần cấu hình TIM1 trong thẻ counter settings:
        • Prescaler: bộ chia clock vào cho thanh ghi prescaler quyết định. Giá trị tối đa 65535. Dựa trên công thức tính toán lý thuyết ở trên thì mình chọn là 7199.
        • Counter mode : cấu hình bộ đếm của timer, đếm lên xuống hoặc vừa lên vừa xuống. Dựa trên công thức tính toán lý thuyết ở trên và hệ số PSC là 7199 thì mình chọn ARR là 9999.
        • Counter period: giá trị đếm load vào thanh ghi ARR.
        • Internal clock devision : liên quan đến sử dụng clock nội của timer thay cho lock hệ thống, dùng cho các ứng dụng đặc biệt, để giá trị mặc định là no division.
        • Repetition counter : hệ số nhân của sự kiện xảy ra ngắt tràn. Vd giá trị Repetition counter =9, mà cài đặt ngắt 1s 1 lần thì sau 10 lần mới có 1 sự kiện ngắt xảy ra tức là 10s ngắt 1 lần.
      4. Tab NVIC: chức năng của các mục mình đã đề cập trong bài 03, ở đây chỉ khác là click chọn Tim1 update and Tim16 interrupts là vì ở đây cài đặt ngắt tràn, line ngắt của TIM16 trùng với line ngắt tim1.
    5. Cài đặt file xuất ra cho project : vào Project -> settings.Việc cài đặt tương tự như các bài 02, 03. Và không có gì khác biệt nhiều.
    6. Xuất code sau khi cài đặt : Project -> code generate hoặc click vào biểu tượng. Sau khi code được sinh ra click vào open project để mở project đó lên.
  5. Chỉnh sửa code trên keil C.
  6. Gọi chương trình khởi tạo ngắt tim1 trước vòng lặp while trong file main.c.

    Gọi lệnh đảo trạng thái led mỗi lần nhảy vào ngắt trong file srm32f3xx_it.c

    Ý nghĩa một số câu lệnh:

    • Dòng lệnh HAL_TIM_Base_Start_IT(&htim1); cho phép khởi động TIM1 ở chế độ ngắt. Tương tự đối với các timer khác.
    • HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9); : cho phép đảo trạng thái led ở chân PB9 mỗi lần xảy ra sự kiện ngắt tràn TIM1.
    • HAL_TIM_IRQHandler(&htim1); chương trình con này cho phép kiểm tra trạng thái, tác động đến các thanh ghi của timer1…. Chương trình con này mặc định được sinh ra bởi MXCUBE.
  7. Bài tập
    1. Viết chương trình xảy ra ngắt tràn trên TIM1 với chu kì 1s, mỗi lần nhảy vào ngắt đảo trạng thái led ở chân PB9. Cấu hình clock division là 9, quan sát sự thay đổi so với ví dụ mẫu.
    2. Viết chương trình xảy ra ngắt tràn trên các timer còn lại với chu kì 1s, mỗi lần nhảy vào ngắt đảo trạng thái led ở chân PB9. Lưu ý sự khác biệt giữa TIM1 và các timer còn lại.


Link tải ví dụ demo timer base