Дисципліни:
Курсова робота
На тему:

Спряження МCS-51 з індикаторами: рідкокристалічним індикатором НТ1810 та світлодіодним індикатором АЛС318С.

Дисципліна: Цифрові пристрої та мікропроцесори
ВНЗ:НУ «ЛП»
Формат: Word Doc

Переглядів: 1387 Додано: 2015-02-28




Частина тексту

Вступ

Як нам відомо,система, в якій використовується мікроконтролер, повинна не тільки щось вимірювати або чимось керувати але і, як правило, щось відображати. У більшості випадків в якості вузла відображення використовуються знакосинтезуючі індикатори. Останні можуть бути рідкокристалічними або світлодіодними. За способом формування символів індикатори можуть бути семисегментними або матричними. Далі, багато з них, особливо РК забезпечені самостійними мікроконтролерами, істотно спрощують роботу з ними. У цьому випадку в обов'язки розробника входить лише організація передачі інформації від основного МК в контролер індикатора, а все, що пов'язано з відображенням переданих символів, здійснюється останнім. Світлодіодні індикатори забезпечуються самостійними контролерами набагато рідше, так як робота з ними набагато простіша. При цьому для роботи з ними використовуються системи динамічної індикації.

З перерахованого вище очевидно, що будь-яких стандартних правил поєднання МК з індикаторами не існує, і в кожному конкретному випадку воно виконується по-своєму.

Основна частина

Спряження МК-51 з рідкокристалічним індикатором на основі контролера типу НТ1611

Рідкокристалічний індикатор на основі контролери типу НТ1611 достатньо простий в сенсі апаратного та програмного спряження з призначеним для користувача МК.

Зовнішній вигляд індикатора наведено на рис. 1.

Він являє собою двосторонню друковану плату, з одного боку якої вмонтований 10-розрядний 7-сегментний РК-дисплей, а з іншого нечисленні обслуговуючі його електронні компоненти - контролер, кварц, кілька ємностей. Розмір індикатора-67x36x6 мм. Відзначимо, що індикатор розроблений для використання в телефонних апаратах середнього класу, і саме там ці вироби зустрічаються найчастіше. Згадане призначення визначило їх деякі технічні особливості - відсутність десяткової коми, півторавольтне живлення і вкрай низьке енергоспоживання. Подібні індикатори добре підходять для систем з автономним живленням.

У нижній частині індикатора розташовані 8 контактних майданчиків, призначених для подачі живлення і керуючих сигналів. Три з них не не відіграють для нас важливого значення. А за допомогою п'яти,що залишилися ми організуємо роботу індикатора.

Схема з'єднання індикатора з мікроконтролером наведена на рис. 2. Напругу живлення (номінальна 1,5 В) подається на вхід VDD індикатора, загальний провід з'єднаний з висновком VSS. На вхід

НК також потрібно подати нульовий потенціал, це переводить мікроконтролер індикатора в режим зовнішнього управління. Передача інформації здійснюється за двома сигнальним лініях – D1 і SК.На вхід D1 наш МК передає потрібну для відображення інформацію, біт за бітом, а на вхід SК - тактові імпульси, що інформують індикатор про готовність біта на D1. Сказане ілюструється рис. 3.. Останнім часом такий послідовний обмін став надзвичайно популярним в силу вкрай малих апаратних і програмних витрат, що вимагаються для його реалізації (для з'єднання МК і пристроя необхідні всього два дроти!). До речі,такий інтерфейс ще іноді називають двопровідним (забуваючи, правда, про ще одну пару проводів, живлення і землі).

Як випливає з рис. 3, спочатку наш МК повинен передати індикатору чотирьохрозрядний код цифри, яка повинна відображатися в крайньому зліва розряді. За ним передається код цифри, що відображається у другому зліва розряді і т. д., аж до останнього, десятого. По завершенні передачі SК потрібно встановити в 1. До речі, хоча і можна після закінчення передачі залишити як в нульовому, так і в одиничному стані, краще в подібних випадках залишати його в 1. Чому? Тому, що може так статися, що, наприклад, вивід, по якому ви вкрай не часто передаєте в індикатор дані, вам доведеться задіяти в якості приймаючого.

Таблиця відповідності переданих кодів відображуваним цифрам наведена на рис. 4. Вибір невеликий - десяток цифр, знак мінус, літери F і Р, та ще 2 ні з чим не асоціюючі символи.

Як вже говорилося вище, номінальна напруга живлення на індикаторі - 1,5 В. Ми формуємо його в колі, що складається з резистора і двох включених в прямому напрямку кремнієвих діодах широкого застосування. При струмі через діоди в межах 2 ... 3 мА падіння напруги на них в сумі становить близько 1,4 В, що на практиці цілком прийнятно.

Ще один поширений варіант - використовувати замість двох звичайних діодів включений в прямому напрямку червоний світлодіод. Чому червоний? Тому що на всіх випущених в недавньому минулому червоних світлодіодах падіння напруги в прямому напрямку становило приблизно 1,6 В, в той час як на зелених і жовтих воно було 1,9 В. Однак в останні роки набули широкого поширення червоні світлодіоди, виконані за новою технологією, більш яскраві, але з падінням напруги в прямому напрямку на рівні 1,9 ... 2 В, а це для розглянутого індикатора вже забагато.

Ще один аспект: сигнали управління, які формуються нашим мікроконтролером - пятивольтові. У той же час на наш напів-торавольтовий індикатор вони повинні приходити з амплітудою не більше 1,7 В. Узгодження за рівнями здійснюється за допомогою резисторів опором 43 ... 68 кОм, включених між виходами мікроконтролера і входами індикатора. Оскільки входи останнього, як видно з рис. 5, захищені діодами, величина одиничного сигналу на цих входах не може виявитися більш, ніж Vdd + 0,3 В.

Фрагмент підпрограми ІNDVІV, здійснюючий програмне спряження індикатор НТ1610 з нашим МК, наведено на рис. 6. Для визначеності передбачається, що на індикатор виводяться два чьотирьохрядні числа, цифри яких (у двійково-десятковому поданні) зберігаються у внутрішньому ОЗП в комірках пам'яті з адресами від АD00 +3 (старший розряд першого числа) до АD00 (молодший розряд; в даному прикладі символьній адресі АDОО присвоюємо чисельне значення З0Н, АD00 +1 - відповідно 31H, і т. д.), і з адресами від АD00 +7 (старший розряд другого числа) до АD00 +4 (молодший розряд; АD00 +4 - це 34Н, АD00 +7 - відповідно 37H). Перше число виводимо в 4 правих розряди індикатора, друге - в 4 лівих, а в два середніх (п'ятий і шостий) виводимо пробіли (тобто там не відображаються жодні символи).

Таким чином, якщо комірка з адресою З0Н містить число 07 Н, З1Н - число 02Н, 32Н - число 05Н, ЗЗН - число 04Н, а в наступних чотирьох комірках (з адреси 34Н по 37Н) зберігаються відповідно числа 08Н, 00Н, 01Н і 02Н, то при запуску підпрограми I NDV IV на індикаторі НТ1610 ви побачите (зліва направо) числа 2108 і 4527, розділені двома пробілами.

АD00 може бути будь-яким із діапазону від 20Н до 78Н. Зверніть увагу, молодші розряди відображуваних чисел зберігаємо в комірці з молодшими адресами (АD00 і А000 +4), а старші розряди - в комірках зі старшими адресами (АD00 +3 і АD00 +7)

Тепер з приводу самої підпрограми INDVIV. Вона організована таким чином. Командами MOV A, ADOO + n ми заносимо в акумулятор цифри, які необхідно переслати в індикатор, а потім командами ACALL SIMB0L1 викликаємо підпрограму, організуючу пересилку. Виклик підпрограми здійснюється командою ACALL, а не LCALL. Власне, викликати необхідну підпрограму можна було б і знайомою нам командою LCALL, але ACALL значно коротша, виконується трохи швидше, але застосовується тільки в тих випадках, коли викликаючи підпрограма знаходиться в тому ж двохкілобайтному відрізку памяті програм, що і команда, яка її, викликає. До тих пір, поки вся написана вами програма буде менше 2 кбайт, можете не замислюючись викликати підпрограми командою ACALL а не LCALL.

Тепер щодо того, як числа виводяться командою ACALL з акумулятора в індикатор. Ми повинні вивести старший біт відображуваного числа на вхід DI індикатора і перепадом з 1 в 0 на вхід SК зафіксувати його в НТ1610. Потім потрібно вивести на DI наступний біт і «звести» (встановити з 0 в 1) сигнал на SK. Скинувши потім SK в 0, ми зафіксували в індикаторі другий біт відображуваного числа, і далі по тому ж алгоритму - третій і четвертий.

Як це реалізовано в підпрограмі SIMB0L1? Зверніть увагу на ту її частину, яка йде після мітки SIМВ12. Вже знайома вам команда SWAP А обмінює місцями старші і молодші 4 біта акумулятора, тобто переносить виведене число в старшу його тетраду. Далі викликається підпрограма BIT (ACALL ВIT). Перша її команда (RLC А) здійснює так званий циклічний зсув акумулятора вліво через перенос. При цьому зсуві найстарший, сьомий біт акумулятора, пересилається в біт перенесення СУ, шостий - у сьомий, п'ятий - в шостій і т. д., аж до нульового, який після цього зсуву опиниться в першому біті. Ну а на місце нульового буде пересланий біт, що зберігався до зсуву в СУ. Таким чином, можна уявити собі, що біт перенесення в цій команді виступає в ролі «найстаршого», 9-го біта такого собі розширеного до 9 біт акумулятора, і в цій складній конструкції здійснення зміщення вмісту кожного біта на одну позицію вліво - з нульовою в першу, з першої - у другу, ..., з шостої - в сьому, з сьомої - у восьму. Ну а що вміст восьмого біта? Природно, на звільнене місце в біті 0. Сказане наочно ілюструється рис. 7.

Командою SWAP А ми обміняли місцями старші і молодші 4 біта акумулятора, розмістивши виведене в індикатор число відповідно в 7-й, 6-й, 5-й і 4-й його розряди. Далі команда RLC А в підпрограмі ACALL BIT перенесла старший біт відображуваного числа з сьомого розряду акумулятора в біт переносу. Команда MOV DATIND, переносить біт з CY на лінію 0 порта Р1 або, що те ж саме, на вхід DI індикатора (DAT I ND. EQU P1.0). А далі команда SETB CLKI ND «зводить» сигнал на вході SK індикатора, після чого команда CLR CLK IND «фіксує» виведений біт в індикаторі. Все, підпрограма AC ALL ВIТ перенесла з акумулятора в індикатор старший біт відображуваного числа.

А як виводиться другий біт числа?Команда RLC А в підпрограмі ACALL ВIТ не тільки перенесла старший біт відображуваного числа з сьомого розряду акумулятора в біт перенесення, а й також перекинула на місце сьомого біта наступний за ним шостий, тобто саме той, який нам потрібно тепер вивести в індикатор. При цьому нам просто потрібно ще раз викликати підпрограму ACALL BIT, і вона виведе в індикатор другий розряд числа, що зберігався після виконання команди SWAP А в шостому розряді акумулятора.

Після другого виклику підпрограми ACALL ВIТ в сьомому розряді акумулятора виявиться третім біт відображуваного числа, збережений після виконання команди SWAP А в п'ятому розряді акумулятора. Як неважко здогадатися, викликавши втретє ACALL BIT, ми і його благополучно виведемо в індикатор. Ну а четвертий виклик ACALL BIT завершить пересилку всієї цифри. На цьому підпрограма ACALL SIMB0L1 завершується, про що свідчить команда RET, що йде після четвертого виклику ACALL BIT.

Отже, ми вже зрозуміли, що підпрограма INDVIV командами M0V А, ADOO + N заносить в акумулятор цифри, які необхідно переслати в індикатор, а потім командами ACALL SIMB0L1 здійснює необхідну пересилку. Останнє реалізується тією частиною підпрограми SIMB0L1, яка йде після мітки SIМВ12. А що робить, та її частина, яка розміщується між цією міткою і початком підпрограми?

Згадаймо, що в двійково-десятковому поданні 0 - це 0000В, 1 - це 0001В, 2 - це 0010В і т. д. У той же час з таблиці відображуваних символів індикатора НТ1610 (рис. 3) випливає, що у нього 0000В - це пробіл, а для того, щоб на ньому відобразився 0, в нього потрібно переслати 1010В. Таким чином, нуль перед відображенням потрібно перекодувати. Іншими словами, якщо підпрограма перед відображенням зустріне 0000В, вона повинна замінити його на 1010В, і тільки після цього здійснити пересилку символу в індикатор. Подивимося, як це реалізовано в підпрограмі SIMB0L1.

Першою командою ми зануляємо старші 4 біти,які знаходяться в акумуляторі відображуваного числа - цифра в двійково-десятковому представленні повинна бути чотирьохбітною, від 0000В до 1001В, відповідно. З цією командою ми вже знайомі. А от наступна для нас ще нова. CJNE - це абревіатура виразу Compare and Jump No Equal, що в перекладі означає «порівняти і перейти, якщо не дорівнює». У ході виконання цієї команди мікроконтролер порівнює вміст акумулятора з нулем (саме з цифрою 0, про що нам нагадує символ # перед нею), і якщо А не дорівнює 0, то переходить на виконання тієї частини програми, яка йде після мітки SIМВ11. Перехід туди здійснюється в тому випадку, якщо виведене з акумулятора в індикатор число – не нуль. Ну а якщо в ньому нуль (який потрібно перекодувати)? Тоді МК виконує команди, що йдуть безпосередньо за CJNE А, # 0, SIМВ11:

Спряження MCS-51 з світлодіодним індикатором АЛС318

АЛСЗ18 - найбільш зручний для розгляду багаторозрядний семисегментний світлодіодний індикатор. Розібравшись з тим, як використовувати його, ви без особливих зусиль адаптуєте розлянуті апаратні і програмні засоби під будь-який семисегментний індикатор, чи то панель, набрана з десятка одиночних індикаторів з великими цифрами або малогабаритний (в 14-виводному D1Р'е) п’ятирозрядний АЛС328.

Нагадаю, що семисегментні світлодіодні індикатори випускаються або з об'єднаними анодами, або з об'єднаними катодами. АЛС318 належить до останніх. Його анодами зазвичай керує дешифратор типу КР514IД1. Управління катодами можна організувати по-різному - з використанням другого дешифратора або безпосередньо від мікроконтролера. Ми розглянемо перший варіант - він вимагає використання меншого числа виводів мікроконтролера.

Схема спряження нашого МК з індикатором АЛС318 наведена на рис. 8. Вона включає в себе два дешифратора DDЗ (КР514IД1) і 01) і DD4 (К555ІД7) і половинку мікросхеми з відкритим колектором DD2 (КР155ЛЛ2). Остання, як буде показано нижче, управляє десятковою комою. Природно, цілком можливо замість всіх цих трьох мікросхем використовувати запрограмовану відповідним чином ПЛІС, яка буде виконувати всі свої функції абсолютно ідентично тому, як це зробили б три перечислені мікросхеми. Але при цьому загубиться ясність, чому ми саме так, а не інакше побудували нашу програму зв'язку МК з індикатором, і як змінити програму, якщо щось змінено у схемі спряження. Тому ми і розглянемо схему на дискретних елементах, нехай навіть дещо архаїчну, але найбільш зручну для початкового знайомства. А розібравшись з нею, ви будете робити те, що для вас легше, простіше, елегантніше - коли знаєш, що і як зробити, придумати десяток варіантів на будь-який смак нескладно.

Отже, розглянемо схему на рис. 8. Для роботи з індикатором використовуємо порт Р1. Чотири його молодші позиції (Р1.0-Р1.3) виводять на дешифратор DDЗ код відображуваної цифри: 0000Б - 0; 0001В - 1; ...; 1001В - 9. Виходи дешифратора DDЗ з'єднані з однойменними входами індикатора (відповідними анодами сегментів). Катоди сегментів кожного розряду, як згадувалось, об'єднані всередині індикатора і управляються виходами другого дешифратора (DD4). На інформаційні входи останнього надходять сигнали з трьох старших ліній порту Р1 (Р1.5-Р1.7). Вони дозволяють управляти індикатором, мають до 8 індукованих розрядів. Залишилася лінія (Р1.4) використовується для управління десяткової коми - розрядом h індикатора. Установка цієї лінії в 1 запалює кому в тому розряді,катодний вивід якого встановлений в 0 відповідним виходом дешифратора DD4.

Як видно, для управління 8-розрядним семисегментним світлодіодним індикатором нам знадобилося 8 ліній виводу-весь порт Р1. У попередньому випадку, з НТ1610, лінії вводу / виводу використовувалися більш економно. Але нічого не поробиш, це плата за відсутність всередині індикатора АЛС318 додаткового мікроконтролера.

Якщо вам потрібно управляти не восьми-, а 16-розрядним індикатором, вам необхідно в якості 004 використовувати дешифратор «4 в 16». Відповідно, для управління їм знадобляться не 3, а 4 лінії порту. Логічніше всього використовувати для цього Р1.4-Р1.7 (внісши відповідні зміни в наведену нижче програму). Ну а управління десяткової коми, якщо вона вам необхідна, доведеться здійснити з якої-небудь лінії іншого порту, наприклад, по РЗ.0.

Будемо вважати, що перед нами стоїть те ж завдання, що і в попередньому випадку - відобразити підпрограмою IZ0ВR на індикаторі два чотирьохрозрядних числа, що зберігаються в двійково-десятковому представленні у внутрішньому ОЗП МК в комірках пам'яті з адресами від АD00 + 3 (старший розряд першого числа) до АDОО (молодший розряд; в даному прикладі, як і раніше, символічній адресі АDОО ми присвятили чисельне значення ЗОН, АDОО +1 - відповідно 31Н і т. д.), і з адресами від АD00 +7 (старший розряд другого числа) до А000 +4 (молодший розряд; АD00 +4 - це 34Н, АD00 +7 - відповідно 37Н). Перше число виводимо в 4 правих розряди індикатора, другий - в 4 лівих, а в середній (індикатор-то 9-розрядний) виводжу пробіл.

Таким чином, якщо комірка з адресою З0Н містить число 07Н, 31Н - число 02н, 32Н - число 05Н, ЗЗН - число 04Н, а в наступних чотирьох комірках (з адреси 34Н по 37Н) зберігаються відповідно числа 08Н, ООН, 01Н і 02н, то при запуску підпрограми IZ0ВR на індикаторі АЛС318 ви побачите (зліва направо) числа 2108 і 4527, розділені пропуском.

А як бути, якщо нам потрібно відобразити не 2108 і 4527, а 2,108 і 45,27? Дуже просто. Згадаймо, що відображувані цифри, які зберігаються в АD00 +0- АD00 +7, чотирьохбітних (від 0000В до 1111В), а старше 4 біта кожній з цих цифр зберігають незначущі нулі. П'ятий біт в кожній з комірок пам'яті АD00 +0- АD00+7 відповідає за десяткову кому, що йде безпосередньо за відповідною відображуваною цифрою. У нашому прикладі в числі 2,108 кома повинна відображатися разом з двійкою, тобто в осередку з адресою 37Н повинно зберігатися не 02Н, а 12Н. Відповідно, в числі 45,27 десяткова кома йде після п'ятірки, тобто вона зберігається у вигляді одинички в п'ятому за рахунком розряді числа в комірці 32Н - там замість 05Н має перебувати 15Н. У решту комірках, що зберігають цифри 1, 0 і 8 числа 2,108 і 4, 2, 7 числа 45,27, всі 4 старших біта раніше повинні зберігати незначущі нулі.

Відповідно, при відображенні на індикаторі тієї чи іншої цифри ми у відповідній підпрограмі повинні не тільки її перенести з чотирьох молодших бітів комірки АD00 + n в 4 молодших розряду порту Р1 (тобто Р1.0-Р1.3), а й перенести також п'ятий біт осередку АО00 + п в п'ятий розряд Р1 (в Р1.4). Ось тоді ми зможемо на індикаторі побачити не тільки 2108 і 4527, а й 2,108 і 45,27.

І ще, на що я хочу звернути вашу увагу. Як ми домовлялись, дешифратор 004 може управляти вісьмома розрядами індикатор. Водночас АЛС318 - 9-розрядний, і ми хочемо, щоб середній (п'ятий з будь-якого краю) розряд був завжди погашений. Як пога ¬ сить розряд, на управління яким у нас вже немає вільного виходу дешифратора? Правильно, подати на його катод одиничний рівень. А якби ми захотіли погасити найстарший (лівий) розряд індикатора, а в молодших 8 розрядах відображати число від 00000000 до 99999999? Природно, потрібно було б подати одиничку на катод старшого розряду, а з виходами дешифратора з'єднати решту 8 катодів. Природно, не забувши зробити відповідні зраді ¬ ня в наведеній нижче програмі ...

Ну а тепер перейдемо безпосередньо до програми IZOBR

Вона реалізує відображення методом динамічної індикації. Нагадаю, що при цьому однойменні (у нашому випадку анодні) сегменти різних розрядів індикатора об'єднані між собою, і внаслідок цього код відображуваного символу одночасно подається на аноди всіх розрядів. Відображається ж цей символ у тому разряді, катоди якого знаходяться під нульовим потенціалом, при цьому всі інші розряди індикатора виявляються погашені. Відповідно, якщо ми на дешифратор DD3 подамо код символу, який повинен бути відображений у першому розряді, то для того, щоб він висвітився саме в потрібному місці, на входи другого дешифратора (DD4) треба подати такий код, щоб на його виході, з'єднаному з катодом першого розряду, з'явився логічний 0. Давши невелику затримку, далі на DD3 подамо код символу, який повинен відобразитися в другому розряді, а на входи DD4 - такий код, щоб логічний нуль з'явився на його виході, з'єднаному з катодом другого розряду. Процедуру повторимо до тих пір, поки не переберемо всі розряди індикатора і не висвітлимо в кожному з них відповідну цифру, потім ще раз, ще, ще і т. д.

Звернімося ще раз до схеми на рис. 8. Зауважте, що крайній правий розряд ми поєднуємо з виходом 0 дешифратора DD4, другий справа - з виходом 1, третій - з виходом 2 і т. д. Це означає, що при відображенні цифри, що стоїть в самому правому розряді , на входах DD4 повинен бути присутнім код 000В, при відображенні цифри у другому праворуч розряді - код 001В, в третьому праворуч - код "010В, в четвертому - 011В, в шостому (п'ятий відключений подачею на його катоди одиниці) - 100В , в сьомому - 101В, у восьмому - 110В і в дев'ятому, крайньому зліва - 111В. Згадаймо також, що цифра, яка повинна відобразитися в крайньому праворуч розряді, зберігатися в комірці з адресою AD00 +0, наступна - з адресою AD00 + 1 і т. д. Таким чином, для реалізації відображення методом динамічної індикації ми, по-перше, повинні десь в мікроконтролері мати лічильник, послідовно перебираючий значення 0-1 -2-3-4-5-6-7-0 -1 - ... По-друге, коли значення цього лічильника дорівнює 0, то потрібно відображати цифру з комірки AD00 +0, коли 1 - з комірки AD00 +1 і т. д. Іншими словами, якщо значення лічильника рівне n, то відображувана цифра повинна бути залучена з комірки АDОО + n. І по-третє, разом з відображуваної цифрою ми повинні на входи дешифратора DD4 (тобто на лінії Р1.5-Р1.7) вивести поточний значення згаданого лічильника. Ось, власне, і все, що повинна зробити наша програма.

Як це реалізовано в IZ0BR? У комірці пам'яті CNSKI ND організований лічильник, значення якого в початковий момент встановлюється в 0 командою MOV CNSKIND, # 0. У ході виконання програми воно безперервно збільшується - команда MOV A, CNSKIND переносить його вміст в акумулятор, потім команда INC А збільшує його на 1, а MOV CNSKIND, А повертає інкрементоване значення назад в комірку CNSKI ND. Команда ANL А, # 00000111В зануляє п'ять старших бітів цього лічильника, точніше залишену в акумуляторі його копію. Навіщо? Після виконання цієї команди в акумуляторі залишаються або 0, або 1, або 2, або 3, або 4, або 5, або 6, або 7. Ніякої іншої цифри там залишитися не може. Щоб усвідомити це, уявіть, що до виконання команди ANL А, # 00000111В в ньому була вісімка. Згадаймо, що 8 - це 00001000В. Занульте її 5 старших біт, і отримайте 0. Від дев'ятки (00001001В) після занулення 5 старших біт залишеться 1, від десятки (00001010В) - двійка і т. д. до 15 (00001111В), які при цьому залишать сімку . А ось від послідовного після 15 числа 16 (00010000В) - зверніть на це увагу - занулення 5 старших біт залишить знову 0. Від 17 залишиться одиниця, від 18 - двійка і т. д.

Таким чином, в результаті виконання вищезазначених команд в акумуляторі послідовно, один за одним, виявляються О, 1, 2, 3, 4, 5, 6, 7. Потім ці цифри знову повторюються в тій же послідовності, потім ще і ще, поки не завершиться виконання програми. А адже саме це нам і потрібно! Далі ми повинні це число,яке зберігається в акумуляторі перенести в три старших розряди порту Р1, і крім цього додати його до AD00. Знайдену суму ми візьмемо в якості адреси комірки, звідки винесемо відображену цифру (вона знаходиться в молодших чотирьох бітах цієї комірки) і виведемо її в чотири молодших розряди Р1. Згадаймо ще, що в п'ятому біті згаданої комірки, як ми домовлялися, зберігається розряд десяткової коми. Його потрібно вивести на ту лінію порту, яка управляє сегментом h індикатора, тобто в розглянутому випадку - в Р1.4. Якщо все це зрозуміло, то дивіться, як це реалізовано далі в програмі.

Отримане після виконання команди ANL А, # 000001118 значення реалізованого програмним шляхом лічильника ми зберігаємо в регістрі R0 (команда MOV R0, А), потім викликаємо підпрограму DISPLEY. Остання завантажує в акумулятор число # AD00 і командою ADD A, R0 підсумовує його зі значенням лічильника, що зберігається в R0. Отримана сума зберігається в регістрі R1 (MOV R1, А).

Далі йде поки ще не дуже нам знайома команда MOV A, @ R1. Що вона робить?

Нагадаємо, що команда M0VX A, @ DPTR вказує мікроконтролеру прочитати в акумулятор дані з комірки зовнішньої пам'яті, адреса якої зберігається в DPTR. Згадавши це, ви здогадаєтеся, що MOV A, @ R1 змусить наш МК прочитати в акумулятор дані з комірки пам'яті, адреса якої зберігається в R1. Згадайте також, що при розгляді команди M0VX A, @ DPTR було зазначено, що X на кінці команди M0VX говорить про те, що читання має здійснюватися із зовнішньої пам'яті даних. У команді ж MOV A, @ R1 цього X немає, що говорить про те, що читання має бути здійснено з внутрішньої пам'яті даних. Отже, MOV A, @ R1 наказує МК знайти, яку адресу зберегти в регістрі R1, після чого перенести в акумулятор дані з тієї комірки внутрішнього ОЗП, адреса якої знайдена в R1. Зазначимо, що команда MOV @ R1, А змушує МК здійснити зворотну дію - перенести дані з акумулятора в комірку внутрішньої пам'яті, адреса якої зберігається все в тому ж R1. До речі, подібний метод адресації, коли адреса комірки пам'яті, яка бере участь в обміні даними, знаходиться в якому-небудь регістрі, носить назву непрямої адресації (адресу ми знаходимо за допомогою R1 або DPTR), на відміну від прямої адресації (наприклад, MOV A, R1), де адреса, регістр R1 прямо, тобто в явному вигляді вказаний в команді.

Тепер повернемося до нашої програми. Трохи раніше ми знайшли адресу комірки пам'яті, де зберігається цифра, відповідна значенню лічильника сканування (тобто лічильника, який послідовно перебирає значення 0-1-2-3-4-5-6-7-0-1 - .. .). Ця адреса, рівна AD00 + n, ми зберегли в R1. Потім ми викликали команду MOV A, @ R1. Oчевидно, що після виконання останньої в акумуляторі перебуватиме та сама цифра, яку нам треба відобразити. Але цифра ця зберігається в чотирьох молодших бітах акумулятора, а в п'ятому зберігаються 1 або 0, засвічуючи або гасять десяткову кому після відображуваної цифри. Три ж старших біта поки не несуть корисної інформації. Занулимо їх для більшої надійності командою ANL А, # 000111118, після чого розмістимо в цих старших трьох бітах значення лічильника сканування ( воно зберігається в R0, і в нашому випадку дорівнює 000,001,010, ..., 110 або 111).

Операція занесення лічильника сканування в старші біти акумулятора також досить проста. Спочатку ми зберігаємо значення акумулятора все в тому ж регістрі R1 (командою MOV R1, А). Замість цього числа ми переносимо в акумулятор лічильник сканування з R0 (MOV A, R0). Навіщо? Та тому що значення лічильника сканування збережеться в трьох молодших бітах R0, а нам потрібно перенести його в три старші бити. А подібне перетворення ми можемо зробити тільки в акумуляторі, у зв'язку з чим нам і довелося його спочатку звільнити, а потім перенести в нього значення лічильника сканування.

Перенесення з молодших бітів в старші ми здійснимо за допомогою трьох команд циклічного зсуву акумулятора вправо (RRА). При виконанні цієї команди старший, сьомий біт акумулятора, переміститься в шостий, шостий в п'ятий і т. д., аж до першого. Перший же переміститься на місце нульового біта, а «виштовхнутий» з акумулятора нульовий біт пересилаєтся на місце старшого, сьомого. Сказане пояснюється рис.10, що показує стан акумулятора до виконання команди RR А, після виконання першої з них, а потім другої і третьої. Неважко переконатися, що застосувавши її три рази, ми доб'ємося бажаного ефекту - лічильник сканування з трьох молодших біт переміститься в три старших. При цьому в п'яти молодших бітах знаходитимуться нулі.

Тепер нам залишилося тільки скласти вміст акумулятора і регістра R1. Робиться це за допомогою вже знайомої нам команди ADD A, R 1. Нулі в трьох старших розрядах R1 не спотворять при складанні з акумулятором зберігаються в його старших трьох розрядах біти лічильника сканування. П'ять же молодших розрядів акумулятора, що зберігали нулі, при складення з п'ятьма бітами R1, зберігаючими відображувану цифру, в результаті підсумовування будуть саме її і зберігати (рис. 11). Після цього нам нічого не залишається, як вивести це число в порт Р1 (командою MOV Р1, А), і необхідна цифра загориться в потрібному розряді АЛС318. Давши їй погоріти певний час (поки МК буде виконувати поставлені для реалізації затримки команди NOP), контролер здійснить повернення з підпрограми DISPLEY, інкрементує лічильник сканування і приступить до відображення наступної цифри.

Висновок

Ми познайомилися з тим, як сполучати мікроконтролер з різними типами знакосинтезуючих індикаторів. Як вже згадувалося вище, останні можуть бути рідкокристалічними або світлодіодними (решта, наприклад люмінісцентні або електроннопроменеві, практично вийшли з ужитку). За способом формування символів індикатори можуть бути семисегментними або матричними. Далі, як ми мали змогу переконатися, багато з них, особливо РК забезпечені самостійними мікроконтролерами, помітно спрощують роботу з ними. Саме такими були обидва розглянутих у цій главі рідкокристалічних індикатора. В обох випадках нам довелося лише організувати передачу інформації від основного МК в контролер індикатора, а все, що пов'язано з відображенням переданих символів, здійснювалося вже без нашого втручання. Світлодіодні індикатори, які ми розглянули, не мали вбудованих контролерів. При цьому для роботи з АЛС318 нам довелося використовувати в ланцюгах сполучення кілька додаткових мікросхем. Програми, написані для роботи зі світлодіодними індикаторами, виявилися помітно складніше, ніж аналогічні для РК-індикаторів.