- Кругова діаграма:
- Мікроконтролер PIC PIC16F877A Світлодіодний блимаючий код послідовності та робоче пояснення:
У нашому попередньому підручнику ми дізналися про миготіння світлодіода за допомогою мікроконтролера PIC і побудували ту ж схему на платі Perf. Потім ми використали PICkit 3, ICSP та MPLAB IPE для скидання програми на нашу плату Perf. Тепер, у цьому підручнику ми перейдемо до використання більшої кількості контактів на мікроконтролері PIC. Ми будемо використовувати 7 виходів (світлодіодів) та один вхід. Для цього підручника ми використаємо стару дошку Perf (показано нижче) і додамо палички berg, щоб витягнути необхідні шпильки на другу світлодіодну дошку. Наприкінці цього підручника ми створимо послідовність миготіння світлодіодів за допомогою мікроконтролера PIC PIC16F877A та навчимося використовувати кілька входів і виходів, деякі основи циклу for і виклику функцій.
Світлодіодна плата - це не що інше, як інша плата, на якій ми будемо припаювати світлодіоди за допомогою струмообмежуючого резистора (показано нижче). Ми також додамо кнопку для ініціювання мигання світлодіода послідовності.
Кругова діаграма:
Мікроконтролер PIC PIC16F877A Світлодіодний блимаючий код послідовності та робоче пояснення:
Повний код наведено нижче (перевірте в кінці), тут ми будемо отримувати його по рядках. Цей код почне світити світлодіоди послідовно при натисканні кнопки. Щоб зрозуміти послідовності, перегляньте відео в кінці підручника. Я б порекомендував вам порівняти результати, показані у відео, з кодом нижче і спробувати зрозуміти програму.
Давайте розглянемо код рядка за рядком. Перші кілька рядків стосуються налаштування бітів конфігурації, про що було пояснено в попередньому підручнику, тому наразі я їх пропускаю. Найкращий спосіб зрозуміти будь-яку програму - це почати з основної функції ( void main () ), тож давайте це зробимо
TRISB0 = 1; // Вкажіть MCU, що контакт PORTB 0 використовується як вхід для кнопки. TRISD = 0x00; // Інструктуємо MCU, що всі висновки виведені PORTD = 0x00; // Ініціалізуємо всі шпильки до 0
Слово TRIS використовується, щоб визначити, чи використовується штифт як вхід / вихід, а слово PORT - для виведення піна High / Low. Рядок TRISB0 = 1 зробить 0-й штифт PORT B як вхід. Це буде наша кнопка. Рядки TRISD = 0x00; PORTD = 0x00; зробить усі штифти порту D вихідними і присвоїть цим штифтам початкове значення LOW.
Оскільки ми сказали, що B0 використовується як вхід, ми підключимо один кінець кнопки до штифта B0, а інший кінець до землі. Тоді кожного разу, коли ми натискаємо кнопку, штифт буде утримуватися на землі, як показано на схемі підключення вище. Але щоб це сталося, ми повинні використовувати підтягуючий резистор, щоб штифт був високо піднятий, коли кнопка не натиснута. Підтягуючий резистор приблизно такий.
Але наш мікроконтролер PIC має внутрішній слабкий підтягуючий резистор, який може бути активований програмним забезпеченням, таким чином економить багато клопоту (коли потрібно підключити більше кнопок).
Що таке слабкий підтягуваний резистор?
Є два типи підтягує резистора, один є слабким Pull Up і іншої сильної тяга вгору. Слабкі підтягуючі резистори мають велике значення і, таким чином, дозволяють проходити слабкому струму, а сильні підтягуючі резистори мають низьке значення, що дозволяє сильному струму протікати. Всі мікроконтролери в основному використовують слабкі підтягуючі резистори. Для того, щоб активувати це в нашому PIC MCU, ми повинні заглянути в наш паспорт даних для OPTION_REG (реєстру опцій), як показано на знімку нижче.
Як показано, біт 7 має справу зі слабким підтягуючим резистором. Для активації його слід встановити нуль. Це робиться за допомогою OPTION_REG <7> = 0 . Це конкретно стосується біта 7, залишаючи інші біти значеннями за замовчуванням. З цим ми потрапляємо в наш цикл while, де він перевіряє, чи натиснута кнопка, використовуючи if (RB0 == 0). Якщо умова виконана, ми викликаємо нашу функцію з параметрами 1, 3, 7 і 15.
моргання (1); // ФУНКЦІОНАЛЬНИЙ ВИКЛИК 1 з параметром 1 sblink (3); // ФУНКЦІОНАЛЬНИЙ ЗВОНК 3 із параметром 3 sblink (7); // ФУНКЦІОНАЛЬНИЙ ВИКЛИК 7 з параметром 7 sblink (15); // ФУНКЦІОНАЛЬНИЙ ВИКЛИК 4 із параметром 15
Чому ми використовуємо функції?
Функції використовуються для зменшення кількості рядків у нашому коді. Це те, що знали б більшість з нас. Але чому нам потрібно зменшувати кількість рядків, особливо якщо мова йде про програмування MCU. Причиною є обмеженим простором в нашій пам'яті програми. Якщо ми не оптимізуємо код належним чином, у нас може закінчитися місце в пам'яті. Це стане в нагоді, коли ми напишемо довгі сторінки кодів.
Будь-яка функція матиме Визначення функції ( sblink (int get) у нашому випадку) та функцію Call ( sblink (1) у нашому випадку). Необов’язково мати декларацію функції, щоб її уникнути, я розмістив своє визначення функції перед тим, як викликати функцію до своєї основної функції.
Параметри функції - це значення, яке буде передано від виклику функції до визначення функції. У нашому випадку цілочисельні значення (1, 3, 7, 15) є параметрами, які передаються із виклику функції, а змінна "get" отримує значення параметрів у визначенні функції для їх обробки. Функція може мати більше одного параметра.
Після виклику функції виконуються наведені нижче рядки у визначенні функції.
for (int i = 0; i <= 7 && RB0 == 0; i ++) {PORTD = get << i; // Переміщення світлодіода Ліва послідовність __delay_ms (50); } for (int i = 7; i> = 0 && RB0 == 0; i--) {PORTD = get << i; // Переміщення світлодіода Ліва послідовність __delay_ms (50); }
Тепер цей рядок здається дивним: PORTD = get << i . Я поясню, що насправді тут відбувається.
"<<" - оператор лівого зсуву, який зміщує всі біти в ліве положення. Тепер, коли ми викликаємо функцію sblink (int get) з параметром '1' як sblink (1), вона зробить значення 'get' рівним 1, що в двійковій формі дорівнює 0b00000001. Отже, цей рядок буде виглядати як PORTD = 0b00000001 << i .
Значення "i" буде варіюватися від 0 до 7, оскільки ми використовували 'for loop' для (int i = 0; i <= 7 && RB0 == 0; i ++). Значення "i" від 0 до 7 змінить результат наступним чином:
Як бачите, ми вмикали по одному світлодіоду за раз (зліва направо), залишаючи решту ВИМК. Наступний 'цикл for' для (int i = 7; i> = 0 && RB0 == 0; i--) , також зробить те ж саме, але цього разу світлодіод буде ввімкнено справа наліво послідовно, оскільки ми починали з 7 і опускалися до 0. Ми використовували затримку 200 мс, щоб ми могли візуалізувати світлодіод, який вмикається і вимикається.
Тепер, коли ми передаємо значення 3 у функцію sblink (int get) , то функція sblink (3) буде виконана, що робить значення 'get' як 0b00000011, отже, результат на PORTD буде:
Отже, цього разу два світлодіоди буде ввімкнено в будь-який момент за допомогою sblink (3). Так само для sblink (7) та sblink (15) три та чотири світлодіоди будуть ввімкнені послідовно. Як тільки це буде завершено, ми зробимо так, щоб усі світлодіоди світились, використовуючи лінію PORTD = 0xFF . Перегляньте відео нижче для повної демонстрації.
Сподіваюся, ви зрозуміли код і, отже, навчились використовувати функції, цикли 'for' та 'while', щоб отримати бажані результати. Тепер ви можете налаштувати код, щоб отримати іншу послідовність блимання світлодіодів. Продовжуйте компілювати свій код і скидати його на ваш MCU і насолоджуватися результатами. Ви можете скористатися розділом коментарів, якщо десь застрягли. Я також додав сюди файли моделювання та програми.
На цьому в нашому наступному уроці ми дізнаємось, як використовувати таймери PIC16F877A замість того, щоб використовувати функції затримки. Ви можете переглянути всі підручники з мікроконтролера PIC тут.