Hiện nay, hầu hết các dòng vi điều khiển đều được tích hợp khối ngoại vi chuyển đổi tín hiệu tương tự – số (ADC). Đây là một bộ phận quan trọng giúp vi điều khiển có thể đọc được với các tín hiệu analog từ bên ngoài như tín hiệu của các cảm biến loại analog trả về (cảm biến nhiệt độ, độ ẩm, biến trở, quang trở…).
Bài viết này sẽ giúp các bạn hiểu được chi tiết các chức năng của khối ADC trên vi điều khiển STM32F411 và thực hành với ví dụ đọc giá trị ADC, tính toán giá trị điện áp ngõ ra của biến trở.
[HỌC ONLINE: LẬP TRÌNH VI ĐIỀU KHIỂN STM32, VI XỬ LÝ ARM CORTEX – M]
NHỮNG CHỨC NĂNG CHÍNH CỦA KHỐI ADC:
Các đầu vào: Vi điều khiển STM32F411 được tích hợp bộ chuyển đổi ADC 12bit loại SAR. Bộ chuyển đổi này cho phép lựa chọn 1 trong 19 kênh đầu vào, trong đó có 16 kênh đầu vào ngoại (là các chân vi điều khiển) và 3 kênh đầu vào nội là điện áp nguồn cung cấp cho vi điều khiển, cảm biến nhiệt độ được tích hợp sẵn của vi điều khiển và một kênh đo điện áp chân V_BAT. Các kênh đầu vào này có thể chia làm 2 nhóm chuyển đổi: regular (thông thường) hoặc injected (chèn vào khi 1 ADC khác đang chuyển đổi)
Độ phân giải: Cho phép cấu hình độ phân giải: 12bit, 10bit, 8bit hoặc 6bit. Kết quả chuyển đổi của khối ADC sẽ được lưu trữ trong 16bit thấp của 1 thanh ghi, người dùng có thể lựa chọn lưu ở phần bit thấp hoặc bit cao. Kết quả này tương ứng với dải điện áp đầu vào của mỗi channel, và điện áp đầu vào phải nằm trong khoảng Vref- <= Vin <= Vref+, với Vref- và Vref+ có thể thiết kế được.
– Vref- là điện áp tham chiếu dưới, thường sử dụng VSSA = VSS (GND), khi giá trị điện áp đầu vào ADC nhỏ hơn hoặc bằng Vref- thì giá trị kết quả chuyển đổi là 0;
– Vref+ là điện áp tham chiếu trên, thường sử dụng VDDA = VDD(VCC), khi giá trị điện áp đầu vào ADC lớn hơn hoặc bằng Vref+ thì giá trị kết quả chuyển đổi sẽ là tối đa của số bit độ phân giải.
Các chế độ chuyển đổi: Quá trình chuyển đổi ADC của các kênh có thể được lựa chọn thực hiện theo các chế độ sau:
– Single Channel, single conversion mode – Chế độ chuyển đổi đơn kênh, chuyển đổi 1 lần: Ở chế độ này, kênh đầu vào được lựa chọn sẽ được thực hiện chuyển đổi một lần, kết quả được lưu vào thanh ghi kết quả (ADC_DR), cờ báo kết thúc quá trình chuyển được được bật lên, yêu cầu ngắt sẽ được sinh ra nếu người dùng cấu hình cho phép ngắt.
– Multichannel (scan), single conversion – Chế độ chuyển đổi nhiều kênh, chuyển đổi 1 lần: Ở chế độ này, bộ ADC sẽ lần lượt chuyển đổi một chuỗi các kênh đầu vào đã được cấu hình từ trước, tối đa có thể chuyển đổi được 16 kênh. kết quả chuyển đổi của kênh cuối cùng sẽ được lưu vào thanh ghi ADC_DR, cờ báo kết thúc quá trình chuyển được được bật lên, yêu cầu ngắt sẽ được sinh ra nếu người dùng cấu hình cho phép ngắt. Chế độ này cần được kết hợp với tính năng DMA để có thể nhận đầy đủ kết quả chuyển đổi của các kênh.
Thứ tự chuyển đổi của các kênh có thể được người dùng sắp xếp và thời gian lấy mẫu của các kênh có thể được cấu hình độc lập.
*Tính năng DMA (Direct Memory Access) hỗ trợ ngoại vi có thể chuyển dữ liệu trực tiếp đến bộ nhớ mà không cần sự can thiệp của CPU.
– Single-channel continuous conversion mode – Chế độ chuyển đổi đơn kênh, chuyển đổi liên tục: Ở chế độ này kênh được chọn sẽ được chuyển đổi liên tục mà không cần sự can thiệp của CPU trong mỗi lần chuyển đổi. Chức năng DMA với mode circular nên được sử dụng trong chế độ này để giảm tải cho CPU.
– Injected conversion mode – Chế độ chèn: Chế độ này được thiết kế để bộ ADC có thể chuyển đổi ngay tức thì channel đã được cấu hình hoạt động ở chế độ này. Nhóm kênh Injected có độ ưu tiên hơn nhóm kênh Regular nên nó có thể làm gián đoạn quá trình chuyển đổi của kênh thông thường.
– Analog watchdog -giám sát kết quả analog: Tính năng này cho phép tạo ngắt khi giá trị analog ra khỏi ngưỡng cho phép. Khi kết quả chuyển đổi ADC của điện áp đầu vào bé hơn ngưỡng dưới (LTR) hoặc lớn hơn ngưỡng trên (HTR) thì bit trạng thái báo hiệu vượt ngưỡng được bật lên và yêu cầu ngắt có thể được tạo ra nếu người lập trình cấu hình cho phép ngắt. Giá trị LTR và HTR cũng được người dùng cấu hình thông qua các thanh ghi.
Các tín hiệu kích hoạt bộ ADC bắt đầu chuyển đổi có thể là lệnh từ phần mềm để bật bit enable hoặc từ các ngoại vi khác như các bộ Timer hoặc ngắt ngoài ở line 11,15.
MỘT SỐ THANH GHI CỦA KHỐI ADC
Một số thanh ghi của khối ADC mà các bạn nên quan tâm để hỗ trợ cho việc debug hoặc can thiệp vào thư viện, lập trình ở mức thấp hơn
ADC_SR – Thanh ghi chứa các bit trạng thái của khối ADC:
– OVR: Overrun
– STRT: Regular channel start flag
– JSTRT Injected channel start flag
– JEOC: Injected channel end of conversion
– EOC: Regular channel end of conversion
– AWD: Analog watchdog flag
ADC_DR – Thanh ghi kết quả chuyển đổi ADC dành cho các kênh chuyển đổi thông thường, thanh ghi này có 32bit, tuy nhiên có 16bit thấp được sử dụng để lưu trữ kết quả chuyển đổi ADC, và kết quả có thể được lựa chọn ở phần thấp hoặc cao của 16bit này. (Tương tự như ADC_DR thì có các thanh ghi ADC_JDRx (x=1..4) để lưu kết quả chuyển đổi các Injected channel)
THỰC HÀNH 1 – ADC ĐƠN KÊNH, CHUYỂN ĐỔI 1 LẦN SỬ DỤNG CHẾ ĐỘ POLLING
Bài thực hành này sẽ sử dụng phần mềm STM32CUBEMX để cấu hình ADC channel 0 (Chân PA0) hoạt động với chế động Single channel – Continuous conversion mode. Giá trị ADC sẽ được xem thông qua giao diện debug.
Bước 1: Kích chọn dòng STM32F411VETx và sau đó chọn “Start Project”.
Bước 2: Chọn Serial Wire để nạp code
Bước 3: Click chuột phải vào chân PA0 sau đó tích vào ô ADC1_IN0
Bước 4: Chỉnh các thông số ADC của chân PA0
Chọn clock cho bộ Prescaler = PCLK2/2 = 16/2 = 8 MHz, độ phân giải = 12 bits.
Data Alignment = Right alignment: Dữ liệu sẽ được ghi vào phần thấp của thanh ghi ADC_DR
Vì bài viết này hướng dẫn các bạn đọc ADC ở chế độ đơn kênh, đọc liên tục nên Scan Conversion Mode sẽ bị Disabled còn Continuous Conversion Mode được Enabled. Các thông số còn lại giữ nguyên chế độ mặc định.
Lưu ý: Các bạn có thể thay đổi thứ tự lấy mẫu của các kênh ADC (đối với chuyển đổi ADC đa kênh) hoặc thời gian lấy mẫu ở mục ADC_Regular_ConversionMode -> Rank -> Channel/Sampling Time. 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.
Bước 5: Setting project và sinh code
Bước 6: Click chọn Open Project và chuyển qua tab Keil C.
Mở file main.c, tại mục /* USER CODE BEGIN PV */ ta khai báo biến value_adc để lưu giá trị ADC đọc được. Vì giá trị ADC mà ta đọc được có 12 bits nên biến value_adc có kiểu dữ liệu là uint16_t (số nguyên không dấu 16 bits)
Bước 7: Thực hiện project đọc giá trị ADC tại chân PA0, một giây lấy giá trị một lần và dùng debug để quan sát giá trị của biến value_adc.
Ở file main.c, ta gọi hàm HAL_ADC_Start để bắt đầu quá trình chuyển đổi ADC. Thông số truyền vào cho hàm này là địa chỉ của bộ ADC mà chúng ta đang sử dụng (hadc1)
Trong hàm while(1) ta thực hiện lấy giá trị đọc được từ hàm HAL_ADC_GetValue rồi lưu vào biến value_adc. Quá trình thực hiện sẽ được lặp lại sau 1s.
1 2 3 4 5 6 7 8 9 |
/* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ value_adc = HAL_ADC_GetValue(&hadc1); HAL_Delay(1000); } |
Bước 8: Tiến hành debug để xem giá trị ADC
Kích chọn biểu tượng Build ở trên thanh công cụ để compile chương trình, khi kết quả trả về 0 Error và 0 Warning thì các bạn kích chọn biểu tượng Debug (số 3)
Bấm biểu tượng Run để bắt đầu chương trình và quan sát dữ liệu của biến value_adc:
TAPIT ARM R&D