PIC Урок 3. Бегущие огни

 

 

 

Теперь у нас есть среда программирования и компилятор. Также у нас есть готовый проект. Поэтому теперь самое время заняться написанием какого-нибудь кода.

Ну и, по традиции, давайте напишем код, который будет управлять свечением светодиодов, подключенных к ножкам портов микроконтроллера. То есть за счёт поочерёдного поступления положительного потенциала от ножек портов на ножки светодиодов, а также нулевого номинала на другие ножки, мы создадим поочерёдное свечение и потухание светодиодов, за счёт чего произойдёт эффект бегущих огней. Почему именно нужно начинать с такого проекта? Да потому, что светодиоды, как ничто другое, позволяют наглядно оценить управление уровнями на ножках портов, в ту же очередь управление битами в регистрах специального назначения — а именно в регистрах портов ввода-вывода.

Сначала давайте соберём схему с контроллером PIC16F84A и подключенными через токоограничивающие резисторы светодиодами в программе-стимуляторе — Proteus

 

image00

 

Также мы обязаны подать питание на соответствующие ножки, а также на соответствующие ножки обязаны подключить кварцевый резонатор и конденсаторы на 15 пикофарад. Но, как известно, в проетусе этого делать необязательно. Всё и так будет работать. А в практической схеме, конечно, .об этом ни в коем случае нельзя забывать.

Далее откроем наш проект и настроим ножки портов, к которым подключены светодиоды, на выход. Делается это подобно тому, как мы это делали, когда работали с микроконтроллерами AVR. Также установим низкий уровень на этих ножках, так как в отличие от AVR при старте может быть любой случайный уровень, нам этого не нужно

 

void main(void) {

  TRISB = 0x00;

  PORTB = 0x00;

  TRISA &= ~0x03;

  PORTA &= ~0x03;

  while(1)

 

Чуть не забыл, давайте настроим конфигурационные биты. Это биты, без которых нам не обойтись. С помощью них мы настраиваем некоторые свойства нашего контроллера, подобна фьюзам в AVR. Для того, чтобы более удобно их настраивать, есть специальный инструмент в среде программирования MPLAB X IDE.

Проследуем по пунктам меню Window -> PIC Memory Views -> Configuration Bits и внизу у нас появятся настроики этих самых битов конфигурации. Настроим там следующие занчения

 

image01

 

Мы выбрали нужный кварцевый резонатор — это высокоскоростной резонатор от 4 мегагерц. Кстати, у нас будет установлен кварцевый резонатор именно на 4 мегагерца. Так как одна элементарная операция в нашем контроллере занимает 4 машинных цикла, то очень легко будет подсчитывать время. То есть операция будет выполняться ровно за 1 микросекунду.

Сохраним наши конфигурационные биты в удобочитаемый код с помощью нажатию на кнопку ниже

 

image02

 

и получим код в окне вывода информации

 

image03

 

Скопируем его и добавим в наш файл main.c сразу после подключения библиотеки и заодно сразу объявим частоту нашего резонатора, иначе у нас не будут работать корректно задержки

 

#include <xc.h>

 

#define _XTAL_FREQ 4000000

 

#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)

#pragma config WDTE = OFF // Watchdog Timer (WDT disabled)

#pragma config PWRTE = ON // Power-up Timer Enable bit (Power-up Timer is enabled)

#pragma config CP = OFF // Code Protection bit (Code protection disabled)

 

Теперь давайте с помощью удобных инструкций (написанных с помощью макросов в стандартной библиотеке PIC) добавим код в бесконечный цикл

 

while(1)

{

  PORTAbits.RA1 = 0;

  PORTBbits.RB0 = 1;

  __delay_ms(100);

  PORTBbits.RB0 = 0;

  PORTBbits.RB1 = 1;

  __delay_ms(100);

  PORTBbits.RB1 = 0;

  PORTBbits.RB2 = 1;

  __delay_ms(100);

  PORTBbits.RB2 = 0;

  PORTBbits.RB3 = 1;

  __delay_ms(100);

  PORTBbits.RB3 = 0;

  PORTBbits.RB4 = 1;

  __delay_ms(100);

  PORTBbits.RB4 = 0;

  PORTBbits.RB5 = 1;

  __delay_ms(100);

  PORTBbits.RB5 = 0;

  PORTBbits.RB6 = 1;

  __delay_ms(100);

  PORTBbits.RB6 = 0;

  PORTBbits.RB7 = 1;

  __delay_ms(100);

  PORTBbits.RB7 = 0;

  PORTAbits.RA0 = 1;

  __delay_ms(100);

  PORTAbits.RA0 = 0;

  PORTAbits.RA1 = 1;

  __delay_ms(100);

}

 

То есть мы поочерёдно включаем ножки, отключая при этом предыдущие. Всё просто.

 

 

Соберём код и попробуем его поотлаживать.

Для этого установим брейкпоинт на какую-нибудь строку

 

image04

 

Запустим отладку соответствующей кнопкой на тулбаре

 

image05

 

Программа остановится на заданной точке.

Давайте теперь посмотрим какие-нибудь регистры. Запустим сначала инструмент для просмотра всех регистров посредством команды меню Window -> PIC Memory Views -> File Registers

 

image06

 

Мы увидим все регистры, то есть всю память в обоих банках, предназначенную для данных. Давайте прошагаем до следующей строчки с помощью соответствующей кнопки на тулбаре

 

image07

 

У нас изменится только байт-счётчик, так как в бите RA1 у нас и так уже был ноль. Причём байт изменится в обоих банках ибо он банконезависимый

 

image08

 

Шагнём ещё один шаг

 

image09

 

И мы увидим что теперь байт по адресу 0x06 изменил своё значение

 

image10

 

Причём не обязательно искать в даташите, что это за адрес, достаточно поднести курсор мыши к значению и мы увидим всё в подсказке

 

image11

 

Только постоянно подносить курсор тоже не совсем удобно. Для этого есть другой инструмент, созданный именно для просмотра регистров специального назначения, который вызывается командой меню Window -> PIC Memory Views -> SFRs

 

image12

 

Шагнём ещё пару шагов и увидим изменение в регистре порта B

 

image13

 

Также существует ещё один интересный инструмент, позволяющий измерять время, за которое выполняется та или иная команда, а если поставить точку останова в другом месте и выполнить код сразу до неё, то и целого участка кода. Данный инструмент вызывается по команде меню Window -> Debugging -> Stopwatch. Вызовем его и шагнём одну команду

 

image14

 

Мы видим, что команда выполнилась за 1 микросекунду, то есть за 1 машинный цикл. Сбросим время кнопкой Clearstopwatch

 

image15

 

Время дожно будет сброситься

 

image16

 

Теперь прошагаем ещё одну команду. У нас как раз задерка, вот и измерим её время

 

image17

 

Всё точно. 100 милисекунд. Остановим отладку, перейдём в Proteus. Настроим свойства контроллера, добавив там 16-битную величину наших конфигурационных битов, а также показав путь к нашей прошивке и задав частоту тактирования

 

image18

 

Сохраним настройки и попробуем запустить проект. Мы должны увидеть, как светодиоды «побегут» сверху вниз

 

image19

 

Конечно, в статической картинке я показать этого не смогу, поэтому смотрите видеоурок.

А теперь посмотрим нашу практическую схему, которую я собрал на макетной плате

 

image20

 

Вместо десяти диодов была подключена светодиодная матрица, кварцевый резонатор подключен к ножкам контроллера 15 и 16 и от этих же ножек на общий провод подключены конденсаторы по 15 пикофарад каждый. Питать схему будем от программатора.

Программатор мы будем использовать PICkit2. У меня он клон. Настоящий фирменный у меня есть PICkit3, но так как для данной схемы достаточно и второго, да и не у всех есть третий, то будем использовать пока его.

А вот и программатор

 

image21

 

Подключается данный программатор к контроллеру по интерфейсу ICSP следующим образом

 

PICkit — MC

1 (VPP) — 4

2 (VDD) — 14

3 (VSS) — 5

4 (ICSPDAT) — 13

5 (ICSPCLK) — 12

6 (Aux) — в нашем случае не используется

 

Давайте так его и подключим (нажмите на картинку для увеличения изображения)

 

image23_0500

 

Теперь, чтобы нам прошить наш файл в контроллер и проверить результат нашей работы по написанию кода, нам необходима будет программа. Скачаем и установим программу PICkit2. Так как на официальном сайте вы её вряд ли уже найдёте, то я её прикреплю к странице внизу.

Скачаем программу, установим её и запустим, подключив перед этим программатор к схеме, а с другой стороны — к USB-разъёму компьютера. Если всё подключено правильно, то программа сама обнаружит и определит контроллер

 

image24

 

Покажем программе нашу прошивку, проследовав по пунктам меню File -> Import Hex и показав путь к файлу с прошивкой в файловом диалоге. Конфигурационные биты должны будут выставиться сами, как мы их и настраивали в среде программирования

 

image25

 

Включим питание, заранее выставив напряжение. Пойдёт и 5 вольт, но я всегда на всякий случай выбираю 4,8. Включение питание производится установкой галки в чекбокс On

 

image26

 

Прошьём нашу прошивку в контроллер с помощью кнопки Write, после чего контроллер должен будет перезагрузиться и программа должна будет начать выполняться, о чём будут свидетельствовать бегущие огни светодиодов в матрице

 

image27

 

Таким образом, мы сегодня написали исходный код, научились некоторым приёмам отладки программы, а также испытали работу кода как в программе Proteus так и на практике.

Всем спасибо за внимание!

 

Предыдущий урок Программирование МК PIC Следующий урок

 

Исходный код

 

 

Программа для прошивки PICkit2

 

 

Приобрести программатор PICKit3 (неоригинальный) можно здесь PICKit3

Приобрести программатор PICKit3 (оригинальный) можно здесь PICKit3

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

PIC Бегущие огни

13 комментариев на “PIC Урок 3. Бегущие огни
  1. Сергей:

    судя по программе…. можно резисторы убрать и заменить одним в цепь светодиодов на землю

  2. Сергей:

    и схема… так себе…. обычно светодиоды нулём зажигают, чтобы контроллер не перегружать…
    поэтому- катодами в контроллер …. аноды в кучу и один резистор на +5
    ну и программу переделать 🙂

    • Нет не так. Именно такая схема используется чаще. И токоограничивающие резисторы ставятся на каждую ножку порта, так как в случае зажигания нескольких светодиодов одновременно будет протекающий ток умножаться на количество зажжённых.

      • Сергей:

        это вы серьёзно? 🙂
        да хоть сотню светодиодов попробуйте зажечь…. один резистор в 250 ом — ни какому току не даст протечь 🙂
        просто светодиоды гореть не будут…
        я предложил упрощение схемы по вашей программе…..
        кстати- 250 ом… это 20ма на ножку…. если все одновременно «загорятся»- контроллер выдержит?

        • imperror:

          По вашей схеме каждый последующий зажженный светодиод будет влиять на яркость свечения предыдущих, так что ваш вариант схемы, мягко говоря, неудачен.

          • Это общепринятая схема. У каждой ножки порта есть предельный ток, который она может выдержать. Можете проверить. Зажечь сразу все светодиоды, а затем один. Будет яркость 1 и та же.

          • Кстати в официальном мануале по FreeRTOS «Mastering the FreeRTOS™
            Real Time Kernel» есть раздел 12.3 Stack Overflow. Может поможет.

          • Сергей:

            для данной программы- нормальный вариант…. один гасится- другой зажигается 🙂

  3. Сергей:

    добавлю…. по даташиту…. порт В имеет максимальную нагрузку 100-150ма если все сразу зажечь, то контроллеру может поплохеть….

    статья… для начинающих нормальная….
    не обижайтесь за критику- просто я разработкой больше 20 лет занимаюсь 🙂

  4. Сергей:

    программу поменять надо…
    сначала
    TRISA=0xFF;
    TRISB=0xFF;
    а по тексту:
    TRISBbits.TRISB4=0;
    PORTBbits.RB4=1;
    TRISBbits.TRISB4=1;

    и т.д.

    тогда точно одновременно не зажгутся

  5. Сергей:

    забыл про делей 🙂
    TRISBbits.TRISB4=0;
    PORTBbits.RB4=1;
    __delay_ms(100);
    TRISBbits.TRISB4=1;
    TRISBbits.TRISB5=0;
    PORTBbits.RB5=1;
    __delay_ms(100);
    TRISBbits.TRISB5=1;

  6. Сергей:

    кстати… неудобные посты… да и вообще все мои посты -можете удалить

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*