Ми в одному кроці від створення повноцінного вимірювального приладу. Все, що нам залишилося, це зробити результати вимірювання доступними за межами відладчика. Для цього є кілька способів. Один з них, виводити результат вимірювання на РК-дисплей, як це робиться в побутовій техніці. У цьому уроці, ми навчимося використовувати стандартний ЖК-модуль з LaunchPad. Так само, тут, ми вивчимо концепцію створення користувальницької бібліотеки. В кінці уроку ми отримаємо бібліотеку, яку ви зможете використовувати в своїх майбутніх проектах з ЖК-екраном, що скоротить витрачаються зусилля на написання коду.
ЖК-модуль (LCM)
Для цього уроку вам необхідний РК-дисплей, якого у вас може і не бути. Якщо немає, рекомендую купити один. Ці дисплеї дуже поширені і коштують не дорого. Вони бувають різних розмірів і типів, тут ми будемо використовувати стандартний текстовий 16х2 ЖК-модуль з інтерфейсом HD44780. Їх можна купити де завгодно, наприклад на eBay. можете вибрати будь-який, який вам подобається, але переконайтеся що, він працює від напруги 3.3 В і не перероблений для роботи по послідовному інтерфейсу (I2C / TWI). Якщо вам хочеться великий модуль (наприклад 20х4), як забажаєте, працюють вони однаково. Колір можете вибрати будь-який.
Підключення дисплейного модуля
Стандартний ЖК-модуль має 16 виводів (14 без підсвічування). Перші кілька призначені для харчування (можуть бути в двох місцях, при наявності підсвічування) і настройки контрасту. Висновок 1 (позначений як Vss) повинен бути з'єднаний з землею на вашому LaunchPad. Висновок 2 (Vdd) з'єднаний з харчуванням Vcc на вашому LaunchPad. Якщо ви використовуєте висновок підсвічування 15 (LED +), він так само приєднується до Vcc і висновок 16 (LED-) до землі. (Все це найпростіше розташовувати на макетної платі (breadboard)). Висновок 3 (V0), контролює контрастність екрану. Якщо у вас є змінний резистор на 10 кОм, надішліть листа з цього висновок до середнього контакту резистора, а два крайніх контакту з'єднайте з землею і харчуванням, і ви зможете налаштовувати контраст. Якщо резистора немає, просто заземлите цей висновок, буде виглядати не так добре як могло б, але працювати буде.
Залишається 11 висновків на контроль і дані. Три контрольних лінії, це висновки 4 (RS), 5 (R / W) і 6 (E). Висновок читання / запису (R / W) нам не знадобиться, і з'єднавши його з землею, ми включимо постійний режим читання у дисплея. Ми не зможемо що-небудь вважати з дисплея (на кшталт положення курсора, стану прапора зайнятості і т.д.), але це дасть нам один вільний висновок на MSP430. Для контролю дисплея ми будемо використовувати висновки Вибір Регістру - Register Select (RS) і Готовність - Enable (E). Останні висновки 7-14 (D0-D7), це шина даних. Можна вважати ці висновки такими ж, як і вісім висновків порту P1 на MSP430, - D0 це перший біт, D1 другий, і т.д. Якщо ми використовуємо повний порт введення / виводу на MSP430 для шини даних, просто з'єднаємо відповідний висновок порту з таким же за номером висновком шини даних, і позбавимо себе від складнощів створення віртуального порту з нестандартним розташуванням висновків всередині програми. Але, тому що на G2211 не вистачає портів для цього, ми просто використовуємо 4-бітний режим введення. Для нього використовуються висновки D4-D7 дисплейного модуля. Висновки D0-D3 залишаться приєднаними.
У програмі вимірювача ємності потрібно зробити заміну робочих висновків, через використання РК-модуля. Тепер ми будемо використовувати P1.1 як TA0.0 замість CA1. і використовуємо P1.2 / CA2 як неінвертуючий вхід компаратора. Висновок P1.0 контролюватиме RS. P1.3 контролювати E. висновки P1.4-P1.7 контролюватимуть D4-D7 відповідно.
Зверніть увагу на те, що висновок P1.3 в LaunchPad, з'єднаний з кнопкою, це не повинно заважати роботі програми, але тому що він підтягнутий резистором до харчування, це буде приводити до підвищеної витоку струму, коли ми будемо скидати E. На жаль, на LaunchPad не передбачена перемичка на кнопці S2, як на висновках P1.0 і P1.6 світлодіодів, так що залишимо це як є . І поки ми про це говоримо, переконайтеся, що зняли перемички з двох світлодіодів і TXD / RXD. (Тут вам повинно стати зрозуміло, чому в новому LaunchPad відсутня підтягаючий резистор на P1.3 - прим. Пер.)
Управління дисплейним модулем
Після того, як ми все з'єднали, посилка команд і символів на дисплей просте завдання. Насправді, це можна робити навіть руками, без мікроконтролера! Основний принцип тут, це запис інструкцій на висновки шини даних і подача імпульсу на E. Інструкція зчитується по спадающему фронту на E. ось чому необхідний імпульс. Якщо RS скинутий, то інструкція сприймається як команда контролеру ЖК-модуля, якщо RS встановлено, то як код символу для виведення.
Для прикладу, подивимося команди, необхідні нам для установки дисплейного модуля в 4-бітний режим. Інструкція «Вибір Функціоналу» в 8-бітному двійковому коді виглядає так: 0b001nnnxx. (Тут вказані значення, використовувані для вибору конфігурації і x. Позначає не використовуються біти, яке б у них не було значення, вони ні на що не впливають). Біт 4, в даній інструкції, встановлює спосіб взаємодії: 1 - встановлює 8-бітний інтерфейс, 0 - 4-бітний. Таким чином, посилаючи інструкцію 0b00100000 (або 0x20), ми конфігуруємо дисплейний модуль на прийом команд і символів за два 4-бітних посилу, замість одного 8-бітного. Ця команда, повинна бути надіслана першою, що б ми могли працювати з нашою 6-провідний схемою підключення. В першу чергу встановлюємо значення на шині даних командою P1OUT | = 0x20 (одночасно скинувши RS (значить це команда, а не символ) і скинувши E (необхідно в нашій схемі підключення)), а потім відправляємо команду імпульсом на E.
Дисплейний модуль не відповідає на команду моментально, є точні часові інтервали для його коректної роботи. Особливо, RS повинен бути скинутий в перебігу певного часу, до початку імпульсу на E. Лінії даних повинні бути встановлені за деякий час до виникнення спадаючого фронту імпульсу, і повинні зберігати свій стан достатній період від імпульсу. Потім, деякий певний час має пройти до того, як ми зможемо послати імпульс на E знову. На щастя для нас, точність тимчасової затримки важлива тільки між командними імпульсами. Решта тимчасові затримай, порядку декількох сотень наносекунд, і швидкість виконання команд MSP430 досить невелика, для того, що б ці затримки виникали природним чином. Час, необхідний для завершення посилу команди, перш ніж можна посилати наступну, має бути близько 150 мс. Його можна отримати через команди затримки delay ().
Резюмуючи все сказане вище, ось набір інструкцій для установки ЖК-модуля в 4-бітний режим:
Хоча встановити E можна до установки шини даних, зручніше поміняти порядок, щоб уникнути тимчасових розбіжностей. У разі, якщо ви використовуєте інший порядок з'єднання висновків, особливо якщо використовуєте кілька портів, цей код не запрацює. Це зручно використовувати висновки порту P1.4-P1.7 для висновків D4-D7 ЖК-модуля, але не обов'язково. Якщо ви поміняли порядок, наприклад у вас P1.4-P1.7 з'єднані з D7-D4 відповідно, то ви повинні записати 0b0100. а не 0b0010 в шину даних в цьому коді. Будьте уважні, використовуючи іншу конфігурацію висновків, ви повинні налаштувати кожен біт шини даних відповідно. Останній рядок обнуляє шину даних, щоб полегшити правильне введення наступної команди.
Посилка команд в 4-бітному режимі
Тепер наш дисплей готовий приймати команди в 4-бітному режимі. Цей режим працює через посилку порції з 4 старших бітів по пульсації E. Потім посилки другої порції з 4 молодших бітів, по другий пульсації. Для нашої схеми з'єднання ми можемо це зробити за допомогою такого коду:
Тут видно, що я зібрав всі команди відповідають за пульсацію Е. включаючи тимчасові затримки, в одну функцію void pulse (void). Звичайно вона підходить і для використання в 8-бітному режимі. Якщо ми зберемо описаний вище набір команд в функцію void SendByte (char). ми зможемо записати наступні команди ініціалізації таким чином:
Після введення цих команд, наш дисплей буде готовий відобразити будь-які символи або текст, що ми йому пошлемо. Важливо розуміти, що для відправки символів використовуються ті ж команди що і вище, але в P1OUT. повинен бути встановлений біт BIT0 (RS), що б дисплей знав, що це символ, а не команда. У своєму прикладі я, для цього зробив розширену функцію SendByte. яка дозволяє посилати як команди, так і символи. Так само, в ньому використовуються інші команди, такі як очищення дисплея і переміщення курсора. Якщо у вас є ЖК-дисплей, спробуйте цю програму самі. Із вибраними там затримками, вона не буде працювати з DCO швидше 2 мГц. Якщо будете експериментувати з кодом, врахуйте це. Далі розглянемо, як инкапсулировать цей код в бібліотеку, і як використовувати її в нашому вимірнику ємності.
(Так само, що б дізнатися про інші команди, рекомендується почитати інші статті про використання таких дисплеїв, наприклад ось і ось. - Прим. Пер.)
Лістинг програми (оригінал lcddemoG2211.c):
Додаємо нову бібліотеку
У нас є код, за допомогою якого можна легко послати текст на ЖК-дисплей, і який було б непогано мати у вигляді бібліотеки, що б його досить було просто підключити до проекту, і не займатися кожен раз копіпастінгом. Мова програмування Сі дозволяє це робити дуже легко. Так що подивимося, як засунути роботу з дисплеєм в бібліотеку, і як налаштувати CCS для використання цієї бібліотеки. В цю бібліотеку можна буде додавати будь-який код, який ви зібралися використовувати неодноразово.
По-перше, виберіть папку, де буде зберігатися бібліотека. Компілятору без різниці, але у вас повинен бути простий шлях для доступу до неї, що б вносити зміни і доопрацювання. З іншого боку, це повинно бути досить безпечне місце, що б ви випадково її НЕ стерли, не змінили, чи не перенесли і т.п. Я наприклад, просто створив папку "library" в моєму каталозі з проектами.
По-третє, скопіюйте залишився код функцій в окремий файл ".c" з таким же ім'ям як у заголовки (в нашому випадку simple_LCM.c). На початку цього файлу має бути додано #include <имя_файла.h>. де «имя_файла», це ім'я нашого заголовки. Увага: цей файл НЕ МАЄ містити функцію main ()!
По-четверте, в вашому новому проекті, правою КНОК клікніть на папці проекту і оберіть new → folder. Натисніть на кнопці [Advanced >>]. і виберете "Link to folder in the filesystem" додати посилання на каталог. Потім ви повинні знайти каталог своєї бібліотеки і додати його.
Тепер будь-які файли з папки бібліотеки, доступні для використання в програмі. Правда компілятору потрібно окремо вказувати шлях до цієї папки, що б він заробив. (Це те, що мені найбільше не подобається, потрібно це робити для кожного нового проекту, і я не знайшов способу, як зробити шлях до цієї папки вбудованим за замовчуванням, при створенні нового проекту CCS).
Отже, по-п'яте, клікніть правою кнопкою на папці проекту, і виберіть "properties" властивості. Відкрийте розділ "C / C ++ Build" і в "Tool Settings" настройках інструменту, знайдіть MSP430 Compiler → Include Options. а так же MSP430 Linker → File Search Path. В обох цих місцях, вкажіть шлях до каталогу бібліотеки, інакше ваш код не відкомпілюйте.
Раз бібліотека simle_LCM має шаблон для виведення рядків, що трапиться, якщо ми захочемо вивести цифрове значення, таке як час затримки таймера (з змінної long int time;)? Один, стандартний для Сі метод, це використовувати бібліотеку "stdio" і функцію sprintf (); з неї. Все що нам потрібно, це створити масив символів, наприклад print_time [10]. і використовувати sprintf (print_time, ".", time); що б помістити число в рядок print_time. а потім передати її в PrintStr () для виведення на екран. На жаль, цей метод має деякі недоліки, при використанні його для мікроконтролерів. По-перше, незважаючи на дуже хорошу оптимізацію коду компілятором CCS, будь-яка програма використовує функцію printf. вийде великий. Наша програма може перевищити 2 кБ, доступні в G2211. По-друге, оптимізація ускладнює отримання коректного форматированного виведення. В ідеалі, ми повинні використовувати форматування% 10d. для розміщення значення таймера точно в 10 байт змінної print_time. Ми не можемо зробити цього з включеною оптимізацією. Ми можемо змінити рівень оптимізації для printf у властивостях проекту, але це ще збільшить розмір коду.
На щастя, є методи впоратися з цією проблемою. З змінної типу integer. ми можемо витягти окремі цифри, використовуючи оператор цілочисельного ділення і оператор залишку від ділення. Так x% 10; поверне останню цифру числа, що зберігається в x. Потім x / = 10; видалить останню цифру з числа, залишивши інші. Запустивши цикл з таких операцій, до досягнення x == 0 (більше немає цифр), ми можемо витягти всі цифри з числа по одній і послати їх на друк. Кодова таблиця ASCII, яка використовується в дисплейному модулі, влаштована так, що ми можемо отримати код будь-цифри, просто додаючи її до однієї і тієї ж константі, так 0x30 + 0 буде "0", 0x30 + 7 буде "7" і т.д .
Недолік такого методу з циклом, в тому, що ми отримуємо цифри в зворотному порядку, справа наліво. У ЖК-модуля є режим роботи, коли він переміщує курсор справа наліво після друку символу, таким чином, є можливість виводити текст в такому порядку. (Насправді, так працює більшість звичайних калькуляторів). Загляньте в нашу програму, що б дізнатися, якими командами налаштовується такий спосіб виведення.
Отже, ми змогли створити завершений вимірювальний прилад, використовуючи MSP430. Ми використовували комбінацію таймера і компаратора з каліброваним генератором тактового сигналу, для вимірювання часу затримки в RC-ланцюга. Дисплей показує виміряне час в мікросекундах. Знаючи значення опору R і час, ми можемо порахувати реальне значення ємності C.
Вправа: Програма працює прекрасно, але чи не краще було б, маючи ЖК-екран, бачити відразу ємність замість часу? Ви можете робити операції з плаваючою комою на MSP430 (хоча неефективно), але як показати число з плаваючою комою на екрані? Якщо sprintf виявився завеликий для нашої програми, то даний функціонал, безсумнівно, займе дуже багато пам'яті. Чи зможете ви вивести ємність на екран, що не перевищивши ліміт в 2 кБ на G2211? Якщо у вас не виходить, один із способів показаний тут: CMeterLCMFull.c. У цій програмі так само реалізований авто-вибір одиниць виміру. Її код займає 1934 байта, якраз достатньо, що б вміститися в G2211.
Примітка перекладача: Щоб не збільшувати розмір тексту, я не став приводити повні листинги, а просто приєднав архів з файлами бібліотеки і двома прикладами її використання.