Це наш 9-й підручник з вивчення мікроконтролерів PIC за допомогою MPLAB та XC8. До цього часу ми розглянули багато основних підручників, таких як початок роботи з MPLABX, світлодіодне блимання за допомогою PIC, таймери в PIC, взаємодія з РК, взаємодія з 7-сегментами тощо. Якщо ви абсолютно новачок, відвідайте повний перелік підручників з PIC тут і починайте вчитися.
У цьому підручнику ми дізнаємося, як користуватися АЦП з нашим мікроконтролером PIC PICF877A. Більшість проектів мікроконтролера будуть задіяні в ньому АЦП (аналого-цифровий перетворювач), оскільки це один із найбільш часто використовуваних способів зчитування даних із реального світу. Майже всі датчики, такі як датчик температури, датчик потоку, датчик тиску, датчики струму, датчики напруги, гіроскопи, акселерометри, датчик відстані та майже кожен відомий датчик або перетворювач виробляють аналогову напругу від 0 до 5 В на основі показань датчиків. Наприклад, датчик температури може видавати 2,1 В при температурі 25 ° С і підніматися до 4,7 при температурі 60 ° С. Для того, щоб знати температуру в реальному світі, MCU повинен просто прочитати вихідну напругу цього датчика температури і зв'язати її з температурою в реальному світі. Отже, АЦП є важливим робочим інструментом для проектів MCU і дозволяє дізнатися, як ми можемо використовувати його на нашому PIC16F877A.
Також перевірте наші попередні статті про використання АЦП в інших мікроконтролерах:
- Як використовувати АЦП в Arduino Uno?
- Підручник з ADC Raspberry Pi
- Зв'язок ADC0808 з мікроконтролером 8051
АЦП в мікроконтролері PIC16F877A:
Доступно багато типів АЦП, і кожен із них має власну швидкість та роздільну здатність. Найпоширенішими типами АЦП є спалах, послідовне наближення та сигма-дельта. Тип АЦП використовується в PIC16F877A називається як АЦП послідовного наближення або SAR коротше. Тож давайте дізнаємось трохи про SAR ADC, перш ніж ми почнемо його використовувати.
Послідовний апроксимаційний АЦП: АЦП SAR працює за допомогою компаратора та деяких логічних розмов. Цей тип АЦП використовує еталонну напругу (яка є змінною) і порівнює вхідну напругу з опорною напругою за допомогою компаратора, а різниця, яка буде цифровим виходом, зберігається з найбільш значущого біта (MSB). Швидкість порівняння залежить від тактової частоти (Fosc), на якій працює PIC.
Тепер, коли ми знаємо деякі основи роботи з АЦП, давайте відкриємо нашу таблицю та дізнаємося, як користуватися АЦП на нашому MCU PIC16F877A. PIC, який ми використовуємо, має 10-розрядний 8-канальний АЦП. Це означає, що вихідне значення нашого АЦП буде 0-1024 (2 ^ 10), а на нашому MCU є 8 контактів (каналів), які можуть зчитувати аналогову напругу. Значення 1024 отримується через 2 ^ 10, оскільки наш АЦП дорівнює 10 бітам. Вісім контактів, які можуть зчитувати аналогову напругу, згадані в таблиці. Давайте подивимось на малюнок нижче.
Для вас виділено аналогові канали AN0 - AN7. Тільки ці висновки зможуть зчитувати аналогову напругу. Отже, перед зчитуванням вхідної напруги ми повинні вказати в коді, який канал потрібно використовувати для зчитування вхідної напруги. У цьому підручнику ми будемо використовувати канал 4 з потенціометром для зчитування аналогової напруги на цьому каналі.
Модуль A / D має чотири регістри, які повинні бути налаштовані для зчитування даних зі вхідних штифтів. Це регістри:
• Високий регістр A / D результатів (ADRESH)
• Низький регістр A / D результату (ADRESL)
• Реєстр A / D контролю 0 (ADCON0)
• Реєстр A / D контролю 1 (ADCON1)
Програмування для АЦП:
Програма для використання АЦП з PIC мікроконтролерів дуже проста, ми просто повинні зрозуміти ці чотири регістри, а потім читає будь-аналогове напруга буде простим. Як зазвичай, ініціалізуємо біти конфігурації і почнемо з void main ().
Усередині void main () ми повинні ініціалізувати наш АЦП, використовуючи регістри ADCON1 та ADCON0. Регістр ADCON0 має такі біти:
У цьому реєстрі ми повинні увімкнути модуль ADC, зробивши ADON = 1, і увімкнути годинник перетворення A / D, використовуючи біти ADCS1 і ADCS0, інші поки що не встановлюються. У нашій програмі годинник АЦП обраний як Fosc / 16, ви можете спробувати власні частоти і подивитися, як змінюється результат. Повна інформація доступна на сторінці технічного листа 127. Отже, ADCON0 буде ініціалізовано наступним чином.
ADCON0 = 0b01000001;
Тепер регістр ADCON1 має такі біти:
У цьому реєстрі ми повинні зробити A / D Format Format Select bit bit high by ADFM = 1 і зробити ADCS2 = 1, щоб знову вибрати Fosc / 16. Інші біти залишаються нульовими, оскільки ми планували використовувати внутрішню опорну напругу. Повна інформація доступна на аркуші даних на сторінці 128. Тому ADCON1 буде встановлено наступним чином.
ADCON1 = 0x11000000;
Тепер після ініціалізації модуля ADC всередині нашої основної функції, давайте потрапимо в цикл while і почнемо читати значення ADC. Щоб прочитати значення АЦП, слід виконати наступні кроки.
- Ініціалізуйте модуль АЦП
- Виберіть аналоговий канал
- Запустіть АЦП, зробивши Перехід / Готово трохи високим
- Зачекайте, поки біт Go / DONE закінчиться
- Отримайте результат ADC з реєстру ADRESH та ADRESL
1. Ініціалізація модуля АЦП: Ми вже дізналися, як ініціалізувати АЦП, тому ми просто викликаємо цю функцію нижче, щоб ініціалізувати АЦП
Функція void ADC_Initialize () має такий вигляд.
порожнеча ADC_Initialize () {ADCON0 = 0b01000001; // ADC ON і вибрано Fosc / 16 ADCON1 = 0b11000000; // Вибрано внутрішню опорну напругу}
2. Виберіть аналоговий канал: Тепер ми повинні вибрати, який канал ми будемо використовувати для зчитування значення АЦП. Дозволяє створити функцію для цього, так що це буде легко для нас, щоб перемикатися між кожним каналом всередині в той час циклу.
unsigned int ADC_Read (unsigned char channel) {// **** Вибір каналу ** /// ADCON0 & = 0x11000101; // Очищення бітів вибору каналу ADCON0 - = канал << 3; // Встановлення необхідних бітів // ** Вибір каналу завершено *** ///}
Потім канал, який потрібно вибрати, надходить всередину змінного каналу. У рядку
ADCON0 & = 0x1100101;
Попередній вибір каналу (якщо такий є) буде видалено. Це робиться за допомогою побітового та оператора “&”. Біти 3, 4 і 5 змушені бути рівними 0, тоді як інші залишаються в попередніх значеннях.
Потім бажаний канал вибирається, тричі пересуваючи номер каналу і встановлюючи біти за допомогою побітового або оператора “-”.
ADCON0 - = канал << 3; // Встановлення необхідних бітів
3. Запустіть ADC, зробивши біт Go / Done bit високим: Після вибору каналу ми повинні розпочати перетворення ADC, просто зробивши GO_nDONE біт високим:
GO_nDONE = 1; // Ініціалізує A / D перетворення
4. Зачекайте, поки біт Go / DONE знизиться: Біт GO / DONE буде залишатися високим, поки не буде завершено перетворення АЦП, отже, нам доведеться почекати, поки цей біт знову не знизиться. Це може бути зроблено за допомогою той час як цикл.
в той час як (GO_nDONE); // Чекаємо завершення A / D перетворення
5. Отримати результат ADC з реєстру ADRESH та ADRESL: Коли біт Go / DONE знову стає низьким, це означає, що перетворення ADC завершено. Результатом АЦП буде 10-бітове значення. Оскільки наш MCU є 8-бітовим MCU, результат ділиться на верхній 8-бітний і нижній 2-бітні. Верхній 8-бітний результат зберігається в регістрі ADRESH, а нижній 2-бітний - у регістрі ADRESL. Отже, ми повинні складати їх у регістри, щоб отримати наше 10-бітове значення ADC. Цей результат повертається функцією, як показано нижче:
повернення ((ADRESH << 8) + ADRESL); // Повертає результат
Повна функція, яка використовується для вибору каналу АЦП, запуску АЦП і повернення результату, показана тут.
unsigned int ADC_Read (канал без знака char) {ADCON0 & = 0x11000101; // Очищення бітів вибору каналу ADCON0 - = канал << 3; // Встановлення необхідних бітів __delay_ms (2); // Час придбання для зарядки утримуючого конденсатора GO_nDONE = 1; // Ініціалізує A / D перетворення в той час як (GO_nDONE); // Чекаємо завершення A / D перетворення ((ADRESH << 8) + ADRESL); // Повертає результат}
Тепер у нас є функція, яка прийме вибір каналу як вхідний і поверне нам значення АЦП. Отже, ми можемо безпосередньо викликати цю функцію всередині нашого в той час циклу, так як ми тут аналогове напруга від каналу 4 в цьому керівництві, виклик функції буде виглядати наступним чином.
i = (ADC_Read (4)); // зберігаємо результат adc у “i”.
Для того, щоб візуалізувати результати нашого АЦП, нам знадобляться якісь модулі відображення, такі як РК-дисплей або 7-сегментний. У цьому посібнику ми використовуємо 7-сегментний дисплей для перевірки результату. Якщо ви хочете знати, як користуватися 7-сегментним зображенням, дотримуйтесь підручника тут.
Повний код наведено нижче, і процес також пояснюється в відео в кінці.
Налаштування та тестування обладнання:
Як зазвичай імітують код за допомогою Proteus, перш ніж насправді йти з нашим обладнанням, схеми проекту показані нижче:
З'єднання 4-розрядного семисегментного дисплейного модуля з мікроконтролером PIC такі ж, як і в попередньому проекті, ми щойно додали потенціометр до висновку 7, який є аналоговим каналом 4. Змінюючи пот, змінна напруга буде надіслана на MCU який буде зчитуватися модулем АЦП і відображатись на 7-сегментному модулі дисплея. Перегляньте попередній підручник, щоб дізнатись більше про 4-значний 7-сегментний дисплей та його взаємодію з PIC MCU.
Тут ми використовували ту саму плату мікроконтролера PIC, яку ми створили в підручнику, що блимає світлодіодами. Після забезпечення з’єднання завантажте програму в PIC, і ви побачите такий результат
Тут ми прочитали значення АЦП з бака і перетворили його на фактичну напругу, відобразивши вихід 0-1024 як 0-5 вольт (як показано в програмі). Потім значення відображається на 7-сегменті та перевіряється за допомогою мультиметра.
Ось і все, тепер ми готові використовувати всі аналогові датчики, доступні на ринку, спробуйте і спробуйте це, і якщо у вас виникнуть проблеми, як зазвичай, використовуйте розділ коментарів, ми будемо раді вам допомогти.