Продолжаем работу над программированием микроконтроллеров PIC.
И прежде чем продолжить заниматься остальными таймерами, давайте немного отдохнём и сделаем какой-нибудь проект, который позволит нам управлять отображением информации на светодиодном семисегментном индикаторе.
И, не отходя от наших традиций двигаться от простого к сложному, сначала рассмотрим статическую индикацию. Но так как в дальнейшем нам все равно придется заниматься и динамической индикацией, чтобы управлять, например четырьмя индикаторами или разрядами, то ножек портов контроллера PIC16F84A нам не хватит, поэтому теперь мы будем программировать уже другой контроллер — PIC17F876A, который у нас будет уже в 28-пинном корпусе и, следовательно, возможностей у нас будет больше. Также переход на такой контроллер обусловлен тем, что вскоре грядёт урок по другим таймерам и еще некоторой разнообразной периферии, которая просто-напросто отсутствует у контроллера PIC16F84A.
Начнём с того, что посмотрим назначение ножек контроллера PIC17F876A
Назначение ножек практически такое же, как и у рассмотренного нами в ранних уроках контроллера 64A, но только этих ножек уже больше и есть уже несколько новых обозначений, касающихся периферии, которая отсутствует у предыдущего контроллера. С назначением данных ножек мы будем знакомиться в процессе изучения данных видов периферии. И, так как программирование статической индикации — это ничто иное, как управление светодиодами сегментов с помощью ножек портов, а этим мы уже занимались на предыдущих занятиях, то теория нам в принципе по программированию для этого никакая больше не нужна.
Давайте тогда познакомимся с самим индикатором и принципом его работы. Хотя я это уже писал в уроках по программированию других контроллеров, которые вы, я надеюсь, тоже смотрите, тем не менее все равно проведу некоторый обзор.
Семисегментный индикатор представляет собой совокупность планарных светодиодов, определённым образом расположенных в корпусе с целью отображения в основном цифр, но также можно отображать некоторые другие символы. Каждый светодиод является сегментом индикатора и обозначать его принято особой буквой
Один контакт каждого светодиода сегмента выведены на определённую ножку, а вторые контакты соединены и выведены на одну общую ножку, приблизительно так же, как и на нашей схеме бегущих огней. Только существуют две разновидности. Первая — когда объединены аноды, а катоды выведены отдельно. Такой индикатор называется светодиодный семисегментный индикатор с общим анодом, а если наоборот — то с общим катодом.
У нас будет индикатор с общим анодом, поэтому данный общий анод мы подсоединим к проводу питания, а катодами мы уже будем управлять с помощью ножек портов, к которым мы их и подсоединим, конечно не в коем случае не забывая о токоограничивающих резисторах. Вы должны знать характеристики конкретного индикатора и подобрать для него резисторы нужного номинала, чтобы ток не превышал максимальный, а также чтобы не превысить максимальный ток, протекающий через ножку порта. Я, например, установил такие же резисторы, как и на бегущие огни — по 220 ом.
Для того, чтобы было легче данными сегментами управлять и выводить с помощью их свечения определённые цифры или символы, то мы соединим их по порядку с ножками одного порта — a с ножкой RB0, b — с RB1 и так далее по порядку и будем в уме постоянно себе представлять вот такое вот двоичное число
Давайте создадим новый проект в среде программирования MPLAB X с именем LED_STAT. Проект мы создавать умеем. Только надо будет выбрать другой контроллер
Как обычно, создадим в проекте файл main.c со следующим стандартным содержимым
main.c:
#include <xc.h>
#define _XTAL_FREQ 4000000
void main(void) {
while(1)
{
}
return;
}
Конфигурационные биты сконфигурируем следующим образом (назначение каждого бита разъяснено в комментариях)
#define _XTAL_FREQ 4000000
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
//--------------------------------------------------------------
Добавим переменную для счётчика, а также инициализируем ножки порта
void main(void) {
unsigned char i;
TRISB = 0x00;
PORTB = 0xFF;
Мы настроили ножки на выход и на всех ножках порта установили высокий уровень, так как индикатор у нас с общим анодом, и чтобы сегмент не светился, необходимо подавать на него высокий уровень, тогда разность потенциалов между анодом и катодом будет ноль, так как анод у нас также подключен к высокому уровню (шине питания), и сегмент светиться не будет.
Выше функции main() добавим функцию отображения определённой цифры на индикаторе
//--------------------------------------------------------------
void segchar (unsigned int seg)
{
switch (seg)
{
case 1:
PORTB = 0b11111001;
break;
case 2:
PORTB = 0b10100100;
break;
case 3:
PORTB = 0b10110000;
break;
case 4:
PORTB = 0b10011001;
break;
case 5:
PORTB = 0b10010010;
break;
case 6:
PORTB = 0b10000010;
break;
case 7:
PORTB = 0b11111000;
break;
case 8:
PORTB = 0b10000000;
break;
case 9:
PORTB = 0b10010000;
break;
case 0:
PORTB = 0b11000000;
break;
}
}
//--------------------------------------------------------------
В зависимости от пришедшего в функцию целого положительного однозначного числа мы попадаем в соответствующий ему кейс и включаем необходимые уровни на ножке порта B, соответственно единичку отправляем на ножку, которая управляет сегментом, который не должен светиться, и наоборот — ноль — на ножку, управляющую сегментом, который будет светиться.
Осталось нам лишь только написать код отправки цифр по порядку с некоторой задержкой в данную функцию в бесконечном цикле. Для этого мы воспользуемся циклом for, который нам и поможет считать от 0 до 9
while(1)
{
for(i=0;i<10;i++)
{
segchar(i);
__delay_ms(500);
}
}
Вот, собственно, и весь код. Мы будем инкрементировать счётчик раз в полсекунды, а как только он дойдёт до 9, то процесс опять повторится с нуля.
Соберём наш код. Соберем следующую схему в протеусе
Зайдём в свойства контроллера, выберем там прошивку, а также настроим частоту и конфигурационные биты
Сохраним настройки и запустим программу на выполнение
Счётчик наш прекрасно считает, значит мы всё сделали правильно.
Ну и теперь перейдём к настоящей практической схеме (нажмите на картинку для увеличения изображения)
Схема собрана также на макетной плате, также подключен кварцевый резонатор к соответствующим ножкам с конденсаторами и также подключен подтягивающий резистор на ножку MCLR. И также проведены провода для подключения программатора.
Мы видим также установленный на схеме индикатор, подключенный к контроллеру посредством токоограничивающих резисторов. У каждого отдельно-взятого индикатора схема распиновки своя. У моего она вот такая:
Запустим программу PICkit 2, у нас обнаружится наш контроллер. Включим питание аналогично как мы и делали в ранних занятиях, импортируем файл прошивки и прошьём наш контроллер. В результате мы получим счётчик от 0 до 9
Таким образом, мы сегодня создали цифровой счётчик на семисегментном светодиодном индикаторе, применив статическую индикацию, а также познакомились с контроллером PIC16F876A, на котором мы и применили данный способ статической индикации.
Спасибо за внимание!
Предыдущий урок Программирование МК PIC Следующий урок
Купить программатор (неоригинальный) можно здесь: PICKit3
Купить программатор (оригинальный) можно здесь: PICKit3 original
Семисегментный одноразрядный индикатор красный (с общим анодом или катодом на выбор) 10 шт
Смотреть ВИДЕОУРОК (нажмите на картинку)
В тексте упоминается контроллер PIC17F876A (который не находится в MPLAB), а на картнке PIC16F876A. Видимо, опечатка.