Đọc ADC nhiều kênh trên SMT32 sử dụng DMA

Trong bài viết trước, TAPIT đã giới thiệu và hướng dẫn đến các bạn chức năng ADC trên vi điều khiển STM32F103C8T6 sử dụng Interrupt trên một kênh. Bài viết này sẽ hướng dẫn các bạn đọc giá trị ADC nhiều kênh khác nhau, kết hợp với chức năng DMA để lưu kết quả vào bộ nhớ. 

[HỌC ONLINE: LẬP TRÌNH VI ĐIỀU KHIỂN STM32, VI XỬ LÝ ARM CORTEX – M]

Multichannel (scan), single conversion mode là mode được sử dụng để đọc nhiều kênh sau mỗi lần bắt đầu, còn Multichannel (scan) continuous, conversion mode cũng là mode được sử dụng để đọc nhiều kênh ADC, tuy nhiên dữ liệu ADC sẽ được đọc liên tục sau khi bắt đầu.

Đầu tiên, các bạn cần cấu hình ADC và DMA của vi điều khiển STM32F103C8T6 trên phần mềm STM32CubeMX và sau đó sinh code qua những bước sau:
Bước 1: Tạo project, tại thẻ Pinout, các bạn cấu hình chọn các chân PA0, PA1, PA2 thành các kênh input ADC IN0, IN1, IN2. Và các bạn đừng quyên chọn SYS -> Serial Wire để cấu hình 2 chân nạp code thông qua mạch ST-Link V2. 


Bước 2: Tại thẻ Configuration, các bạn chọn ADC1 để cấu hình cho chức năng ADC như hình dưới, trong ví dụ này mình disable Continuous Conversion Mode, sau đó trong code bên Keil C mình sẽ cho cập nhật ADC 0.5s một lần.

– Tại mục Rank, các bạn chọn thứ tự để đọc giá trị các kênh analog cho các channel mà bạn muốn, channel nào có rank 1 thì sẽ được đọc đầu tiên. Ở ví dụ này mình dùng 3 channel nên sẽ có 3 rank, channel PA0 có vị trí rank là 1, PA1 là rank 2 và PA3 là rank 3, tốc độ lấy mẫu của cả 3 kênh là 1.5 cycles. Lưu ý với tốc độ lấy mẫu là 1.5 cycles thì những câu lệnh trong hàm while(1) sẽ không được thực hiện vì thời gian lấy mẫu quá nhanh nên MCU sẽ thực hiện lấy mẫu ADC liên tục, vì vậy đối với các project không đòi hỏi cập nhật giá trị ADC liên tục thì các bạn nên tăng thời gian lấy mẫu lên.

Bước 3: Trong thẻ Configuration, các bạn tiến hành thêm DMA cho ADC1 với cấu hình như bên dưới, lưu ý độ rộng dữ liệu là Half Word. 


Sau khi cấu hình xong, các bạn sinh code và chọn Toolchain/IDE tương ứng, ở đây mình code bằng Keil C nên chọn MDK ARM V5. Sau khi sinh code xong, các bạn mở project Keil C lên và tiền hành thêm các bước sau:
Bước 1:  Các bạn khai báo một biến mảng để nhận dữ liệu DMA từ ADC, có số lượng phần tử bằng số lượng kênh ADC mà các bạn muốn scan. Kiểu dữ liệu của biến này là uint16_t khớp với cấu hình độ rộng dữ liệu DMA half word đã cấu hình trên phần mềm CubeMX.


Bước 2: Tại vòng lặp vô hạn trong hàm main(), các bạn gọi bắt đầu chuyển đổi ADC_DMA và truyền vào các tham số như hình. Để hiểu rõ ý nghĩa của từng tham số, các bạn complie code sau đó nhấn chuột phải vào hàm và chọn Go to definition of “….” để xem.
Các bạn thêm HAL_Delay(500); để có thời điểm dừng cho chúng ta quan sát kết quả cập nhật trên giao diện debug ở bước tiếp theo. 


Cuối cùng, các bạn compile code và bật Debug sau đó bấm run để để xem thành quả.
Các bạn kiểm tra bằng cách lần lượt cắm các chân PA0, PA1, PA2 lên nguồn trong khi 2 chân còn lại nối đất.


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.

Thuong Nguyen