CEtut – Part 7: Timer – Counter Mode

Tiếp nối các chế độ của Timer trong bài trước, hôm nay chúng ta tiếp tục làm quen với chế độ Counter của Timer và các ứng dụng của loại chế độ này.
Share

Tiếp nối các chế độ của Timer trong bài trước, hôm nay chúng ta tiếp tục làm quen với chế độ Counter của Timer và các ứng dụng của loại chế độ này.

1. Chế độ đếm lên

Trong chế độ đếm lên, bộ đếm tăng từ 0 đến giá trị giá trị ngưỡng (Auto-Reloaded Value) (được cài đặt trong thanh ghi TIMx_ARR), sau đó khởi động lại từ 0 và tạo ra sự kiện tràn trên bộ đếm (Counter Overflow Event). Nếu sử dụng bộ đếm lặp lại (Repeatition Counter), sự kiện cập nhật (Update Event – UEV) được tạo ra sau khi đếm lên được lặp lại số lần được lập trình trong thanh ghi bộ đếm lặp lại cộng một (TIMx_RCR+1). Nếu không, sự kiện cập nhật được tạo ra tại mỗi lần xảy ra sự kiện tràn bộ đếm. Khi xảy ra sự kiện cập nhật, tất cả các thanh ghi được cập nhật và cờ cập nhật (Update Interrupt Flag – UIF) được thiết lập mức cao.

Hình 7. 1. Ví dụ đếm lên cho các tần số xung nhịp khác nhau khi TIMx_ARR=0x36 và bộ chia tần số có giá trị là 1

Hình 7. 2. Ví dụ đếm lên cho các tần số xung nhịp khác nhau khi TIMx_ARR=0x36 và bộ chia tần số có giá trị là 2

Hình 7. 3. Ví dụ đếm lên cho các tần số xung nhịp khác nhau khi TIMx_ARR=0x36 và bộ chia tần số có giá trị là 4

2. Chế độ đếm xuống

Trong chế độ đếm xuống, bộ đếm sẽ đếm từ giá trị giá trị ngưỡng (Auto-Reloaded Value) (được cài đặt trong thanh ghi TIMx_ARR) xuống giá trị 0, sau đó khởi động lại từ giá trị ngưỡng và tạo ra sự kiện tràn dưới bộ đếm (Counter Underflow Event). Nếu sử dụng bộ đếm lặp lại (Repeatition Counter), sự kiện cập nhật (Update Event – UEV) được tạo ra sau khi đếm xuống được lặp lại số lần được lập trình trong thanh ghi bộ đếm lặp lại cộng một (TIMx_RCR+1). Nếu không, sự kiện cập nhật được tạo ra tại mỗi lần xảy ra sự kiện tràn dưới bộ đếm. Khi xảy ra sự kiện cập nhật, tất cả các thanh ghi được cập nhật và cờ cập nhật (Update Interrupt Flag – UIF) được thiết lập mức cao.

Hình 7. 4. Ví dụ đếm xuống cho các tần số xung nhịp khác nhau khi TIMx_ARR=0x36 và bộ chia tần số có giá trị là 1

Hình 7. 5. Ví dụ đếm xuống cho các tần số xung nhịp khác nhau khi TIMx_ARR=0x36 và bộ chia tần số có giá trị là 2

Hình 7. 6. Ví dụ đếm xuống cho các tần số xung nhịp khác nhau khi TIMx_ARR=0x36 và bộ chia tần số có giá trị là 4

3. Chế độ đếm giữa

Trong chế độ căn giữa, bộ đếm tăng từ 0 đến giá trị ngưỡng -1, tạo ra một sự kiện tràn trên bộ đếm (Counter Overflow Event), sau đó giảm từ giá trị ngưỡng xuống 1 và tạo ra một sự kiện tràn dưới bộ đếm (Counter Underflow Event). Sau đó nó bắt đầu khởi động lại từ 0. Chế độ căn giữa được kích hoạt khi các bit CMS trong thanh ghi TIMx_CR1 khác với ’00’. Cờ ngắt so sánh đầu ra của các kênh được cấu hình ở chế độ đầu ra được thiết lập khi: bộ đếm giảm (Chế độ căn giữa 1, CMS = “01”), bộ đếm tăng (Chế độ căn giữa 2, CMS = “10”), bộ đếm tăng và giảm (Chế độ căn giữa 3, CMS = “11”). Khi xảy ra sự kiện cập nhật, tất cả các thanh ghi được cập nhật và cờ cập nhật được thiết lập mức cao.

Hình 7. 7. Ví dụ đếm giữa cho các tần số xung nhịp khác nhau khi TIMx_ARR=0x36 và bộ chia tần số có giá trị là 4

4. Bộ đếm lặp

Đơn vị cơ sở thời gian mô tả cách tạo ra sự kiện cập nhật (UEV) liên quan đến các sự kiện tràn/tràn âm bộ đếm. Trên thực tế, sự kiện này chỉ được tạo ra khi bộ đếm lặp lại đạt giá trị bằng không. Điều này có thể hữu ích khi tạo ra tín hiệu PWM.

Bộ đếm lặp lại được thiết lập:

  • Tại mỗi lần tràn trên bộ đếm trong chế độ đếm lên.
  • Tại mỗi lần tràn dưới bộ đếm trong chế độ đếm xuống.
  • Tại mỗi lần tràn trên và tràn âm bộ đếm trong chế độ căn giữa.

Hình 7. 8. Ví dụ về thiết lăp chu kì cho bộ đếm lặp lại

5. Thực hành ứng dụng Timer – Counter Mode với UART/ trên STM32F103C8T6

5.1. Chuẩn bị linh kiện

Trong nội dung thực hành lần này, chúng ta sẽ sử dụng USB to TLL CP2102 để truyền dữ liệu hiển thị số đếm và màu sắc điều khiển LED thông qua giao tiếp UART đến console của STM32CubeIDE. Sử dụng chế độ đếm lên để điều khiển Led 3 màu.

STM32F103C8T6
3 DIODE LED 5MM 3 MÀU KHÁC NHAU
3 Trở 100 Ohm ¼ W
Dây cắm breadboard các loại
Breadboard  
USB 2.0 to TTL CP2102
STLINK-V2

5.2. Sơ đồ kết nối

Hình 7. 9. Sơ đồ kết nối thực hành ứng dụng Timer – Counter Mode

5.3. Cài đặt và cấu hình console trên STM32CubeIDE

  • Bước 1: Các bạn tải driver cho USB to TTL CP2102 tại đây.
  • Bước 2: Sau khi giải nén thư mục driver vừa được tải, các bạn cắm USB to TTL CP2102 vào máy tính và mở Device Manager, lúc này trong mục Other device sẽ hiện biểu tượng dấu chấm thang. Các bạn chỉ cần update driver cho USB này bằng cách trỏ tới thư mục driver vừa được giải nén. Sau khi thiết lập driver USB hoàn tất trong COM sẽ hiện ra thiết bị USB CP2102 và cổng COM đang được kết nối

Lưu ý: Hãy nhớ số của cổng COM này để có thể thiết lập trong phần mềm Hercules nhé!

  • Bước 3: Chọn vào biểu tượng New Console trong Console View trong giao diện STM32CubeIDE và click chuột vào Command Shell Console.
  • Bước 4: Chọn Connection TypeSerial PortEncodingUTF-8. Sau đó chọn ô New để tạo mới cổng kết nối được cấu hình như hình dưới và chọn Finish để hoàn thành.
  • Bước 5: Sau khi hoàn thành cấu hình cổng COM, các bạn hãy chọn cổng COM vừa được cài đặt và nhấn OK.
  • Bước 6: Các bạn sẽ thấy giao diện khung Console được kết nối với cổng COMUSB CP2102.

Mẹo: Các bạn hãy nhấn vào biểu tượng Pin Console để có thể giữ giao diện này khi nạp code vào STM32 nhé! Nếu không nhận USB, các bạn hãy gỡ ra và gắn lại. USB CP2102 sẽ báo đèn led đỏ ngay chân GND là các bạn đã kết nối thành công rồi nhé!

5.4. Cấu hình trong giao diện STM32CubeIDE

  • Bước 1: Chọn vào biểu tượng STM32CubeIDE trên Desktop, điền đường dẫn Folder thích hợp cho Workspace và chọn Launch
  • Bước 2: Chọn ô Start new STM32 Project để tạo mới Project
  • Bước 3: Sau khi hiện lên STM32 Project, các bạn hãy điền và chọn đúng vi xử lý STM32F103C8T6, chọn Next
  • Bước 4: Điền tên Project, tích vào các Option cần thiết và chọn Finish
  • Bước 5: Các bạn chờ để phần mềm tải Package cho STM32F1 nhé
  • Bước 6: Sau khi chờ loading lên giao diện STM32CubeIDE, các bạn vào mục System Core để bật Debug bằng STLINK-V2
  • Bước 7:  Các bạn tiếp tục cấu hình các chân GPIO cho các 3 LED 3 màu khác nhau nhé
  • Bước 8: Trong bước này các bạn sẽ cấu hình USART1 với chế độ Bất đồng bộ – Asynchronous.
  • Bước 9: Cấu hình TIM2 với Internal Clock Source cùng chế độ đếm lên. Vì chúng ta cần thời gian chu kì UEV3s nên UEV sẽ là 1/3, đếm lên từ 0 – 599, xung hệ thống là 8Mhz. Như vậy ta cần Prescaler39999 + 1. (Áp dụng công thức)
  • Bước 10: Nhấn SaveGenerate Code. Bạn đã cấu hình thành công!

5.5. Code và giải thuật

Ý tưởng: Chúng ta sẽ cho STM32F103C8T6 truyền dữ liệu màu led đang bật tắt đến Console của STM32CubeIDE qua UART với Polling. Vì sử dụng chế độ đếm lên của Timer nên chúng ta cần có 3s cho một chu kì với mỗi đèn led sáng là 1s.

  • Bước 1: Trong file main.c, chúng ta sẽ thêm thư viện stdio.h và khai báo các buffer toàn cục để giao tiếp UART có thể truyền dữ liệu từ những buffer này.
/* USER CODE BEGIN Includes */
#include “stdio.h”
/* USER CODE END Includes */
 
/* USER CODE BEGIN 0 */
char counter_red_tx[20];
char counter_blue_tx[20];
char counter_green_tx[20];
/* USER CODE END 0 */
  • Bước 2: Trong vòng lặp While, các bạn gọi các hàm bật tắt các chân GPIO và hàm truyền dữ liệu màu UART đến máy tính với điều kiện là mỗi đèn led sẽ sáng sau 200 lần đếm
/* USER CODE BEGIN WHILE */  
while (1) {        
if(TIM2 -> CNT > 399) {            
sprintf(counter_blue_tx, “blue – %ld\r\n”, TIM2 -> CNT);            
HAL_UART_Transmit(&huart1, counter_blue_tx, 20, 100);
HAL_GPIO_WritePin(LED_BLUE_GPIO_Port, LED_BLUE_Pin, 1);
HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, 0);      
} else if(TIM2 -> CNT > 199) {            
sprintf(counter_green_tx, “green – %ld\r\n”, TIM2 -> CNT);            
HAL_UART_Transmit(&huart1, counter_green_tx, 20, 100);
HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, 1);
HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, 0);      
} else if(TIM2 -> CNT >= 0) {   
sprintf(counter_red_tx, “red – %ld\r\n”, TIM2 -> CNT);            
HAL_UART_Transmit(&huart1, counter_red_tx, 20, 100);
HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, 1);
HAL_GPIO_WritePin(LED_BLUE_GPIO_Port, LED_BLUE_Pin, 0);      
}      
/* USER CODE END WHILE */  
   
/* USER CODE BEGIN 3 */  
}  

Giải thích: Trong bài thực hành lần này chúng ta cần quan tâm đến TIM2 -> CNT đây là biến chứa giá trị đếm hiện tại của bộ Timer tương ứng với nó. Như vậy cứ sau 200 lần đếm là một led tương ứng với nó sẽ sáng. Từ 0 đến 199 là Led đỏ, từ 200 đến 399 là led xanh lá, từ 400 đến 599 sẽ là led xanh dương. Vì đây là chu kì UEV có thời gian là 3s nên mỗi lần sáng led sẽ là 1s và truyền màu led + biến đếm đến Console qua UART. Ngoài ra, hàm sprintf cho phép các bạn định dạng một danh sách ký tự đã được khai báo. Chúc các bạn thành công với bài thực hành đơn giản này.

5.6. Video demo

Các bạn xem video demo tại đây.