Trong các ứng dụng vi điều khiển – hệ thống nhúng, bộ chuyển đổi tương tự-số (ADC) là 1 thành phần rất quan trọng để có thể chuyển đổi các dữ liệu dạng analog từ môi trường (nhiệt độ, độ ẩm, độ sáng,…) sang dạng digital để vi điều khiển có thể xử lý được. STM32F103C8 có tích hợp sẵn các bộ chuyển đổi ADC với độ phân giải 12bit. Có 12 kênh cho phép đo tín hiệu từ 10 nguồn bên ngoài và 2 nguồn nội bên trong. Trong bài này, chúng ta sẽ cùng tìm hiểu về chế độ đơn kênh với STM32, sử dụng Interrupt để báo quá trình chuyển đổi hoàn tất.
[HỌC ONLINE: LẬP TRÌNH VI ĐIỀU KHIỂN STM32, VI XỬ LÝ ARM CORTEX – M]
Trong bộ chuyển đổi ADC, có 2 thuật ngữ mà chúng ta cần chú ý đến, đó là độ phân giải (resolution) và thời gian lấy mẫu (sampling time)
– Độ phân giải (resolution): dùng để chỉ số bit cần thiết để chứa hết các mức giá trị số (digital) sau quá trình chuyển đổi ở ngõ ra. Như trên biểu đồ:
- Màu xanh tương ứng thể hiện độ phân giải của bộ chuyển đổi này là 3 bit, tương ứng với 8 sự thay đổi ở đầu ra số (23=8). Khi đưa vào điện áp tương tự, bộ chuyển đổi sẽ thực hiện một công đoạn lượng tử hóa để đưa các kết quả tương ứng từ điện áp tương tự về số ở ngõ ra.
- Màu tím tương ứng với độ phân giải của bộ chuyển đổi 16 bit. Dễ dàng nhận thấy với một bộ chuyển đổi có độ phân giải càng thấp, quá trình chuyển đổi sẽ cho ra kết quả là một điện áp càng biến dạng ở ngõ ra so với ngõ vào và ngược lại. Bộ chuyển đổi ADC của STM32F103 có độ phân giải mặc định là 12 bit, tức là có thể chuyển đổi ra 212 = 4096 giá trị ở ngõ ra số.
– Thời gian lấy mẫu (sampling time) là khái niệm được dùng để chỉ thời gian giữa 2 lần số hóa của bộ chuyển đổi. Như ở hình trên, sau khi thực hiện lấy mẫu, các điểm tròn chính là giá trị đưa ra tại ngõ ra số. Dễ nhận thấy nếu thời gian lấy mẫu quá lớn thì sẽ làm cho quá trình chuyển đổi càng bị mất tín hiệu ở những khoảng thời gian không nằm tại thời điểm lấy mẫu. Thời gian lấy mẫu càng nhỏ sẽ làm làm cho việc tái thiết tín hiệu trở nên tin cậy hơn.
Trong bài này chúng ta sẽ thông qua công cụ CubeMX để có thể cấu hình thời gian lấy mẫu tại module ADC1
Ở trên kit gồm có 10 channel ADC, chúng ta sẽ sử dụng channel 1 để đọc điện áp từ một biến trở đưa vào
Bước 1:
- Khởi động CubeMX
- Chọn chip
- Bắt đầu khởi tạo project mới
Bước 2:
Cấu hình việc nạp code ở module SYS sang Serial Wire
Bước 3:
Chọn channel 0 của ADC1 (như ta thấy, chân PA0 đã được cấu hình) (nếu như muốn chọn các channel khác, các chân tại port A tương ứng sẽ được cấu hình theo, ví dụ như channel 2 sẽ là PA2, channel 3 sẽ là PA3,…)
Bước 4:
Chuyển sang mục Analog -> ADC1 -> Configuration để thay đổi các thông số của module ADC1
Bước 5:
Ở mục Mode, chỉ có 1 chế độ Independent Mode nên chúng ta sẽ giữ nguyên
Bước 6:
Bộ ADC của STM32F103 có độ phân giải là 12bit mà ta sẽ phải cần lưu trữ vào một thanh ghi 32 bit, do đó sẽ còn thừa 20 bit. Chúng ta sẽ cấu hình việc căn lề cho 12 bit này nằm bên phải hay bên trái trong thanh ghi 32 bit đó tại mục Data Aligment
Bước 7:
Mục Scan Conversion Mode sẽ được sử dụng để “quét” qua lần lượt các kênh ADC trong quá trình đọc dữ liệu, vì ta đang sử dụng chế độ đơn kênh nên chế độ này sẽ không có tác dụng, ta giữ nguyên
Bước 8:
- Mục Continous Conversion Mode sẽ quyết định cho bộ ADC của chúng ta có sử dụng chế độ chuyển đổi liên tục hay không.
- Chọn Enabled
Nếu chúng ta không enable mode này, sau mỗi lần chuyển đổi, ta sẽ phải gọi lại lệnh đọc giá trị ADC để bắt đầu quá trình chuyển đổi mới
Bước 9:
Tại mục Sampling Time, chúng ta sẽ chọn thời gian lấy mẫu trong quá trình số hóa. Tùy vào ứng dụng mà chúng ta có thể chọn thời gian lấy mẫu cho phù hợp.
**Lưu ý: thời gian lấy mẫu càng ngắn, việc tái thiết tín hiệu càng chính xác nhưng năng lượng tiêu tốn sẽ càng cao
Bước 10:
Chuyển sang tab NVIC Settings , sử dụng chế độ Interrupt để báo hiệu việc chuyển đổi đã hoàn tất nên ta sẽ enable interrupt ADC
Bước 11:
Sau khi hoàn thành các bước trên:
- Chọn OK để xác nhận và đóng hộp thoại cấu hình
- Chuyển sang mục Setting để cài đặt việc tạo code cấu hình từ CubeMX
Bước 12:
- Chọn toolchain/IDE là MDK-ARM V5
- Đặt tên project
- Chọn ok để xác nhận và sinh code
Bước 13:
Tạo trước một biến int 16 bit để lưu giá trị của điện áp đọc vào từ biến trở trong file main.c
Bước 14:
Để sử dụng module ADC1 ở chế độ Interrupt, chúng ta cần phải khởi động nó.
- Mở tab Function, mở file stm32f1xx_hal_adc.c lên
- Tìm đến hàm HAL_ADC_Start_IT(1), và chọn copy hàm đó
Bước 15:
- Paste phần đó vào trong hàm main tại file main.c
- Sửa đổi tham số truyền vào thành &hadc1 (vì chúng ta đang cần khởi động module ADC1)
Bước 16:
Sau khi quá trình chuyển đổi số tại 1 thời điểm lấy mẫu thành công, chúng ta sẽ cần có một thông báo để bắt đầu lưu dữ liệu vào một biến, trong trường hợp này, chúng ta sẽ sử dụng một ngắt để báo hiệu.
- Tìm đến hàm HAL_ADC_ConvCpltCallback(2)
- Copy hàm đó
Bước 17:
- Paste hàm này vào file main.c và bên ngoài hàm main (vì đây là một IRQ Handle), thêm một lệnh if như dưới vào để kiểm tra xem ngắt báo hiệu chuyển đổi thành công đến từ ADC1 hay ADC2.
- Sau khi hàm này được gọi, hàm HAL_ADC_GetValue(3) sẽ được gọi để đọc giá trị số hóa và lưu vào biến adc_value
Bước 18:
Thực hiện Build Project
Bước 19:
Thực hiện chức năng Debug để quan sát sự thay đổi của biến adc_value
**Chú thích các hàm cơ bản:
(1) HAL_ADC_Start_IT:
-Chức năng: Khởi động module ADC với ngắt báo hiệu chuyển đổi thành công (ngắt ở đây là End Of Conversion (EOC)
-Tham số truyền vào: Địa chỉ của module ADC cần được khởi động
(2) HAL_ADC_ConvCpltCallback:
-Chức năng: IRQ Handle, được gọi khi có quá trình chuyển đổi thành công từ một module ADC bất kỳ
(3) HAL_ADC_GetValue:
-Chức năng: Đọc giá trị số hóa sau khi đã hoàn thành chuyển đổi
-Tham số truyền vào: Địa chỉ của module ADC cần lấy dữ liệu
-Trả về: Giá trị sau khi đã hoàn thành chuyển đổi
Chúc các bạn thành công!
Xem thêm: Tổng hợp các bài hướng dẫn Lập trình vi điều khiển STM32 tại đây.
Nhóm Tapit ARM R&D