CETut – Part 10: ADC – Analog to Digital Converter

Trong thế giới công nghệ số hóa, ADC (Analog-to-Digital Converter) đóng vai trò không thể thiếu khi chuyển đổi tín hiệu analog sang dạng số. Những ứng dụng của ADC rất phong phú, từ đo lường các tín hiệu điện đến điều khiển thiết bị. Có nhiều loại ADC khác nhau, mỗi loại phù hợp với từng ứng dụng cụ thể như: Flash ADC, Sigma-Delta ADC, và Successive Approximation ADC.
Share

Trong thế giới công nghệ số hóa, ADC (Analog-to-Digital Converter) đóng vai trò không thể thiếu khi chuyển đổi tín hiệu analog sang dạng số. Những ứng dụng của ADC rất phong phú, từ đo lường các tín hiệu điện đến điều khiển thiết bị. Có nhiều loại ADC khác nhau, mỗi loại phù hợp với từng ứng dụng cụ thể như: Flash ADC, Sigma-Delta ADC, và Successive Approximation ADC.

Để hiểu rõ hơn về hiệu suất và khả năng của ADC, chúng ta cần tìm hiểu một số thông số kỹ thuật quan trọng như sau:

  • Độ phân giải: Xác định độ chi tiết của tín hiệu số hóa, ví dụ 8-bit, 10-bit, 12-bit, v.v.
  • Thời gian lấy mẫu (Sample Time): Quyết định tốc độ thu nhận dữ liệu.

Chúng ta sẽ đi sâu vào tìm hiểu ADC trên vi điều khiển STM32F103C8T6, một trong những dòng chip phổ biến của STM32 với nhiều ứng dụng thực tế.

🔍 Những vấn đề sẽ khám phá:

  1. Sơ đồ khối của ADC: Cách thức hoạt động và các thành phần chính.
  2. Các hàm trong thư viện HAL: Những hàm cơ bản để khởi tạo ADC với từng mục đích khác nhau và đọc giá trị từ ADC.
  3. Cách cấu hình: Các bước thiết lập, cấu hình thông số của ADC trên STM32F103C8T6.

Để minh họa rõ ràng hơn hơn về lý thuyết trên, chúng ta sẽ bắt tay vào thực hành với hai ứng dụng phổ biến sau:

💡 Ví dụ 1: Điều khiển cường độ sáng của LED bằng biến trở. Ví dụ này hướng dẫn việc đọc và sử dụng giá trị ADC và ôn lại bài cũng về xung PWM cho các bạn.

🕹 Ví dụ 2: Điều khiển LED bằng joystick. Chúng ta sẽ đọc giá trị điện áp theo cả 2 trục X, Y của joystick, từ đó xác định hướng và điều khiển LED bật tắt theo hướng chuyển động của Joystick.

Vì nội dung về chủ đề ADC khá dài nên trong bài viết này chún ta sẽ chỉ tìm hiểu qua về Sơ đồ khối của ADC, các hàm hỗ trợ của thư viện HAL và cách cấu hình các thông số của ADC trên STM32F103C8T6. Phần hướng dẫn thực hành sẽ ở phần bài viết tiếp theo nhé.

1. Tổng quan về ADC

1. Giới thiệu về ADC

ADC (Analog-to-Digital Converter) là bộ chuyển đổi tín hiệu tương tự (analog) sang tín hiệu số (digital). ADC lấy mẫu tín hiệu tương tự tại các khoảng thời gian cố định và chuyển đổi chúng thành các giá trị số có thể xử lý bởi vi xử lý hoặc các thiết bị kỹ thuật số khác.

Hình 1. Minh họa 2 dạng tín hiệu
Hình 2. Chuyển đổi Analog to Digital (ADC)

2. Các khái niệm quan trọng

Độ 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. Độ phân giải phụ thuộc vào điện áp mẫu và độ dài của bit biểu diễn.

  • Công thức tính Step size (giá trị thay đổi của điện áp tương ứng với 1 đơn vị digital):
    • Step size = V điện áp mẫu / 2n
  • Ví dụ bộ chuyển đổi ADC của STM32F103C8T6 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ố và điện áp mẫu trên STM32F103C8T6 có giá trị là 3.3V, thì ta có giá trị Step size tương ứng là 0.805 mV và khi giá trị đạt 4096 tức điện áp là 3.3V.
Hình 3. Mô tả sự khác nhau của tín hiệu ra với từng số bit.

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 dưới, 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.

  • Tổng thời gian chuyển đổi tín hiệu được tính như sau
    • Tconv = (Sampling Time + Conversion Time) / ADC Clock.
      • Đối với STM32F103C8T6 thì Conversion Time là 12.5 Cycle và Sampling Time là các giá trị sau: 1.5 – 7.5 – 13.5 – 28.5 – 41.5 55.5 – 71.5 – 239.5 cycle và ADC Clock có giá trị tối đa là 14MHz.  
      • Ví dụ: Ta có ADC Clock = 5MHz và Sampling Time là 71.5 Cycle ta sẽ tính được tổng thời gian chuyển đổi tính hiệu như sau:
        • Tconv = (71.5+ 12.5)/ 5 = 17 us.
Hình 4. Mô tả sự khác nhau của tín hiệu với thời gian lấy mẫu khác nhau

3. Phân loại ADC và ứng dụng

  • Flash ADC
    • Nguyên lý hoạt động: Sử dụng một mạng điện trở và nhiều bộ so sánh (comparator) để chuyển đổi ngay lập tức tín hiệu đầu vào.
    • Ưu điểm: Tốc độ chuyển đổi rất nhanh.
    • Nhược điểm: Chi phí cao, tiêu thụ nhiều năng lượng.
    • Ứng dụng: Hệ thống cần tốc độ chuyển đổi cao như radar, video.
  • Successive Approximation Register (SAR) ADC
    • Nguyên lý hoạt động: Sử dụng một bộ lưu trữ và so sánh liên tục để dần dần tạo ra giá trị số gần nhất với tín hiệu đầu vào.
    • Ưu điểm: Cân bằng tốt giữa tốc độ và độ chính xác.
    • Nhược điểm: Tốc độ không cao bằng Flash ADC.
    • Ứng dụng: Hệ thống đo lường, giám sát, y tế và vi điều khiển.
  • Sigma-Delta ADC
    • Nguyên lý hoạt động: Sử dụng tích phân và điều chế mật độ xung để chuyển đổi tín hiệu đầu vào.
    • Ưu điểm: Độ chính xác rất cao.
    • Nhược điểm: Tốc độ chuyển đổi chậm.
    • Ứng dụng: Âm thanh, đo lường chính xác cao.
  • Dual-Slope ADC
    • Nguyên lý hoạt động: Sử dụng quá trình nạp và xả của tụ điện để đo tín hiệu đầu vào.
    • Ưu điểm: Độ chính xác cao và ổn định.
    • Nhược điểm: Tốc độ chuyển đổi chậm.
    • Ứng dụng: Đo lường điện áp trong đồng hồ vạn năng, các thiết bị đo đạc khác.

Tìm hiểu thêm về phân loại ADC và ứng dụng các loại tại: Types Of ADCs (monolithicpower.com)

2. ADC trên STM32F103C8T6

Hình 5. Sơ đồ khối ADC trên STM32F103C8T6
  • Analog Multiplexer (MUX): Chọn một trong các kênh đầu vào analog để kết nối với mạch Sample and Hold, cho phép ADC chuyển đổi tín hiệu từ nhiều nguồn khác nhau.
  • Sample and Hold Circuit: Lấy mẫu tín hiệu analog tại một thời điểm cụ thể và giữ giá trị đó trong suốt quá trình chuyển đổi, đảm bảo tín hiệu ổn định để quá trình chuyển đổi diễn ra chính xác.
  • SAR ADC Core: Thực hiện quá trình chuyển đổi tín hiệu analog sang số theo nguyên lý Successive Approximation Register (SAR), chuyển đổi tín hiệu analog thành giá trị số 12-bit.
  • Start & Stop Control: Điều khiển quá trình bắt đầu và dừng chuyển đổi, quản lý trạng thái hoạt động của ADC.
  • Regular Data Register: Lưu trữ giá trị số sau khi chuyển đổi từ các kênh đầu vào thông thường, cung cấp giá trị kết quả của quá trình chuyển đổi cho vi điều khiển.
  • Injected Data Register: Lưu trữ giá trị số sau khi chuyển đổi từ các kênh đầu vào được “injected”, sử dụng cho các kênh đầu vào có độ ưu tiên cao hơn và cần xử lý ngay lập tức.
  • DMA Request: Yêu cầu truyền dữ liệu ADC trực tiếp vào bộ nhớ mà không cần sự can thiệp của CPU, tăng hiệu quả và tốc độ xử lý dữ liệu.
  • Analog Watchdog: Giám sát các giá trị đầu vào analog và tạo ngắt nếu giá trị vượt quá ngưỡng đã cấu hình, bảo vệ hệ thống bằng cách phát hiện các tín hiệu bất thường.
  • Interrupt Generation: Tạo ngắt khi quá trình chuyển đổi hoàn thành hoặc khi có sự kiện đặc biệt xảy ra (ví dụ: giá trị vượt ngưỡng), thông báo cho vi điều khiển để xử lý dữ liệu hoặc sự kiện.Cấu hình và lập trình với ADC trên STM32F103C8T6

2.1. Cấu hình các thông số cần thiết

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.

Các mode hoạt động của ADC:

  • Single conversion mode: Trong chế độ này, ADC sẽ chỉ thực hiện 1 chuyển đổi cho tới khi người dùng cho phép chuyển đổi tiếp.
  • Continuous Conversion Mode: ở chế độ này, ADC sẽ ngay lập tức thực hiển 1 chuyển đổi khác khi chuyển đổi trước vừa kết thúc.
  • Scan Mode: Chế độ này được sử dụng để quét 1 nhóm các kênh. 1 chuyển đổi duy nhất được thực hiện cho mỗi kênh. Sau khi 1 kênh chuyển đổi xong, kênh tiếp theo sẽ tự động chuyển đổi.

  • Discontinuous Mode: Chế độ này được sử dụng để chuyển đổi n lần (n <= 8). Giá trị của n được xác định tại bit DISCNUM[2:0] trong thanh ghi ADC_CR1.

Lựa chọn các chân tín hiệu: 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,…)

Hình 6. Lựa chọn channel cho ADC

Mục Paramater Setting:

  • Mode: Chỉ code 1 Mode mặc định là Independent Mode nên ta giữ nguyên.
Hình 7. Lựa chọn mode cho ADC
  • Data Aligmet: 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 này
Hình 8. Cấu hình thông số Data Aligmet cho ADC
  • Scan conversion mode: được sử dụng để “quét” qua lần lượt các kênh ADC trong quá trình đọc dữ liệu. Ở chế độ bình thường, mục này luôn ở trạng thái Disable, khi ta thay đổi Number of Conversion (ở dưới) từ 2 trở đi, mục này sẽ được chuyển thành Enable.
Hình 9. Cấu hình Scan conversion mode cho ADC
  • Continous Conversion Mode: Mục này 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. 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
Hình 10. Cấu hình Continous conversion mode cho ADC
  • Number of Conversion, Sampling Time:
    • Number of Conversion dùng để chọn số chân mà mình sẽ nhận dữ liệu, tương ứng với số lượng chân mình đã chọn ở phần lựa chọn các chân tín hiệu
    • Sampling Time dùng để 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. Và nếu chúng ta sử dụng với DMA thì nên chọn thời gian lớn hoặc là lớn nhất (239.5 cycle), vì khi chọn thời gian quá nhở, dữ liệu dễ cũ dễ bị dữ liệu mới ghi đè lên vì chúng ta không đủ thời gian để xử lý dữ liệu cũ.
Hình 11. Cấu hình các thông số về lấy mẫu cho ADC

Mục NVVic Setting: Tại mục này ta sẽ lựa chọn có cần sử dụng ngắt sau khi quá trình chuyển đổi ADC đã hoàn tất hay không. Chúng ta có thể sử dụng ngắt để thực hiện tính toán giá trị mới dựa vào giá trị ADC đọc được.

Hình 12. Cấu hình ngắt cho ADC

Mục DMA Setting: Ở mục này ta sẽ Add thêm DMA cho ADC nếu cần tại mục Add như hình bên dưới. DMA là 1 phương thức khác để lấy dữ liệu ADC. Khi kết hợp ADC với DMA, dữ liệu từ các chuyển đổi ADC có thể được tự động lưu vào bộ nhớ mà không cần sự can thiệp của CPU.

  • Để DMA mới, ta bấm vào Add, tại đây nó sẽ đề xuất ADC1 cho chúng ta thêm vào (vì khi cấu hình ở phía chúng ta chỉ dùng ADC1)
  • Ở mục Mode, ta chọn Circular, việc này đảm bào rằng DMA sẽ không bao giờ dừng.

  • Ở mục Data Width ta chọn là Word. Bạn có thể chọn Half-Word nếu không căn chỉnh phải, trái cho dữ liệu ở phía trên. (1 Word = 32 bits)
Hình 13. Cấu hình DMA cho ADC

2.2. Những hàm quan trọng thường xuyên sử dụng

Hàm liên quan đến ADC

  • HAL_ADC_Start(_IT)
    • Chức năng: Bắt đầu quá trình chuyển đổi ADC ở chế độ polling.
    • Cú pháp: HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc);
  • HAL_ADC_PollForConversion
    • Chức năng: Kiểm tra quá trình chuyển đổi ADC đã hoàn thành hay chưa ở chế độ polling.
    • Cú pháp: HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout);
  • HAL_ADC_GetValue
    • Chức năng: Lấy giá trị chuyển đổi từ ADC.
    • Cú pháp: uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* hadc);
  • HAL_ADC_Stop
    • Chức năng: Dừng quá trình chuyển đổi ADC.
    • Cú pháp: HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc);

Hàm liên quan đến ADC với DMA

  • HAL_ADC_Start_DMA
    • Chức năng: Bắt đầu quá trình chuyển đổi ADC và truyền dữ liệu bằng DMA.
    • Cú pháp: HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);
  • HAL_ADC_Stop_DMA
    • Chức năng: Dừng quá trình chuyển đổi ADC và DMA.
    • Cú pháp: HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef* hadc);
  • HAL_ADC_ConvCpltCallback
    • Chức năng: Callback khi quá trình chuyển đổi ADC hoàn tất.
    • Cú pháp: void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc);

Tạm kết: Hy vọng với bài viết này, bạn đọc đã có những hình dung cơ bản về ADC, cách cấu hình một dự án về ADC. Trong bài viết tiếp theo, chúng ta sẽ cùng nhau thực hành lập trình ADC với các ví dụ đã nêu ở đầu bài.

Thực hiện bài viết bởi: Phan Ngọc Đức Thọ, Huỳnh Phúc Nhân