No Image

Бегущие огни на микроконтроллере

СОДЕРЖАНИЕ
1 993 просмотров
21 января 2020

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

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

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

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

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

TRISB = 0x00;

PORTB = 0x00;

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

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

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

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

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

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

#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) добавим код в бесконечный цикл

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);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Читайте также:  Nissan teana или toyota camry

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

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

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

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

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

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

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

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

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

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

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

PICkit — MC

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

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

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

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

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

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

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

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

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

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

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

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

20 комментариев на “ PIC Урок 3. Бегущие огни ”

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

Судя по программе, можно, но если кто-то перепутает инверсию, то до свидания — контроллер.

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

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

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

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

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

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

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

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

Читайте также:  Керамическое покрытие своими руками

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

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

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

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

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

Вы не объяснили назначение регистров,какой же это урок для начинающих?
TRIS – регистр выбора направления данных в каналах порта ввода/вывода, если соответствующий бит регистра «0», то линия вывода работает на выход, если «1» то на вход. По умалчиванию порт настроен на вход.
PORT – регистр порта , считывает логическую информацию с выводов порта.

Во первых, я нигде не заявлял, что уроки эти для начинающих.
1 предъява не принимается.
Назначение данного регистра очевидна и мы в этом убедились практически.

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

Так как мне будет для работы необходим другой контроллер — PIC16F73, то и эту программу я переписала для него (пока для части ног портов B и C потому что в дальнейшей работе будут задействованы именно они) — заодно для проверки работоспособности имеющихся у меня контроллеров вообще (так как более сложный проект сразу не получился).
Резисторы в вашей схеме чуть увеличила — поставила 270 Ом. Плюс ещё добавила светодиод с сопротивлением 330 Ом непосредственно на питание (между + и — на входе).
И столкнулась с неожиданными для меня явлениями.
1) сразу после прошивки программы в контроллер (программатор у меня PICkit3, но не фирменный. Но MPLab его «видит»),контроллер НЕ перезагружается и выполнение программы НЕ начинается. Хотя питание на схему программатор подаёт и после прошивки. Пробовала на нескольких экземплярах контроллеров. Может быть нужно специально подать контроллеру какой-то сигнал?
2) Если после прошивки питание от программатора отключить и подать иное внешнее питание, то выполнение программы начинается, но бесконечный цикл выполняется не бесконечно, а несколько раз (от 1-2-3 — чаще всего до нескольких десятков изредка). Т.е. огоньки пробегают несколько раз и больше не бегут — гаснут, хотя питание по прежнему подано. От чего именно зависит кол-во повторений так и не поняла. Думала, что от конкретного экземпляра контроллера, но многократные повторения с разными экземплярами контроллеров показали, что не только от этого.
3) После того как огоньки погасли, снятие и повторная подача напряжения далеко не всегда приводит к тому, что они снова побегут. Чаще всего они НЕ бегут. Что приводит к мысли, что контроллер как-то испортился. Но через некоторое время (проведённое контроллером при выключенном питании) часто снова начинают бежать.

Что же это за проблемы? И как их решить?? Особенно
волнуют 2 и 3.
Всё имеющиеся у меня контроллеры «дохлые»?
Что-то не так с питанием? Источник даёт недостаточный ток питания? Пробовала USB порт компьютера и блок питания зарядного устройства (который вроде может выдавать до 1А).
Может велико напряжение питания? Оба доступных мне внешних источника, судя по мультиметру, выдают напряжение 6В. (А по инструкции к контроллеру максимальное напряжение питания — 5.5). Программатор при установке в MPLab 5В выдаёт тоже 6В по мультиметру. Поэтому при прошивке ставлю в настройках 4.5В, тогда на выходе на контроллер намеревается 5.5В.

Посоветуйте пожалуйста мне что-нибудь…

Елена, не превышайте напряжения питания выше 5 В. Если внешний кварц — проверте генерацию, не срывается ли? Сложно давать советы более детальные не видя схему и текст программы.

Подскажите зачем с портом А при инициализации делать такие финты:
TRISA &=

0x03;
Я так понимаю что это:
1. сначала инвертирует (

0x03) и мы получаем: 1111 1100.
2. TRISA после любого ресета имеет 00011111 (так как порт имеет 5ть выводов)
3. Далее мы делаем поразрядное И и записываем в TRISA — таким образом насильно записываем в два младших 00, и получаем 0x1C в регистре. Это можно сделать и сразу: TRISA = 0xFC (TRISA = 0x1C).
PORTB — тоже. Но там после включении питания состояние неопределенно и логически было бы его обнулить.
После других ресетов состояние портов не меняется и после &= в PORTA мы не меняем 2, 3, 4 бит но насильно сбиваем в 0 младшие, которые используем. В данной схеме это не нужно, но на будущее это хороший трюк. Но зачем это делать с TRISA, и почему мы не делаем єто с PORTB?
Если мое предположение с сохранением предыдущего состояния верно,то: зачем делать инвертирование?

Компилятор ругается: Unable to resolve identifier __delay_ms
помогает следующая строка:
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))

Читайте также:  Видеорегистраторы 3 в 1

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

Этот автомат световых эффектов позволяет управлять тринадцатью светодиодами, которые подключены через токоограничивающие резисторы прямо к портам микроконтроллера ATtiny2313.Как уже было сказано выше, в памяти микроконтроллера зашиты 11 различных самостоятельных комбинаций световых рисунков, а так же есть возможность последовательного однократного перебора всех 11 комбинаций, это уже будет 12-ая программа.

Кнопка SA3 позволяет осуществлять переключение между программами.

Кнопками SA1 и SA2 можно управлять скоростью движения огней либо частотой мерцания каждого светодиода (от постоянного свечения до легкого мерцания). Все это зависит, в каком положении находится переключатель SA4. При верхнем по схеме положении переключателя SA4 регулируется скорость бегущих огней, а при нижнем частота мерцания.

При монтаже светодиодов в линейку следует соблюдать очередность такую же, как пронумеровано на схеме от HL1 до HL11.

Микроконтроллер ATtiny2313 тактируется от внутреннего генератора с частотой 8 МГц.

При прошивки ATtiny2313, фьюзы следует выставить следующим образом:

Данные фьюзы указаны для программы PonyProg. Следует помнить, что для CodeVisionAVR указание битов инверсное.

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

Видео работы: Бегущие огни на светодиодах

Скачать прошивку (1,1 Mb, скачано: 3 832)

Форум по AVR

Моим первым устройством на микроконтроллере была схема бегущих огней. Линейка из 15-ти светодиодов, которые попеременно загораются. Принципиальная схема такого устройства предельно проста. По сравнению с макетной платой здесь появились только 15 светодиодов, у которых анод общий, а катоды подсоединены к портам ввода/вывода микроконтроллера и столько же токоограничительных резисторов R3-R17 по 360 Ом.

Светодиоды управляются низким уровнем на выводе микроконтроллера (так как для низкого уровня микроконтроллер может выдать больший ток, около 20мА, чем для высокого, но не стоит забывать про суммарный ток, который может выдать порт).

Линейка светодиодов у меня организована на SMD компонентах, но это дело вкуса.

Теперь рассмотрим порты ввода/вывода. У ATtiny2313 есть 15 линий ввода/вывода, которые сгруппированы в 2 порта: PortB – 8 выводов и PortD – 7 выводов. Вся работа микроконтроллера состоит из правильного шевеления ножками, а искусство программирования – заставить его так делать. Также ножки портов по совместительству могут выполнять другие функции: быть входом встроенного АЦП, внешнего прерывания, выходом USART’а и множество других функций, но их использование рассмотрим немного попозже. Для использования портов ввода вывода их нужно сперва сконфигурировать, за это отвечают регистры PORTX и DDRX, где X – имя порта. Приведем табличку их возможных состояний (n=0..7 – номер вывода в порту):

Как видно из таблицы при значении DDRXn =1 порт работает как выход, и логический уровень на его выходе равен биту PORTXn. При значении DDRXn =0 вывод PXn будет работать на вход, а бит PORTXn определяет, подключен ли к входу внутренний подтягивающий резистор или нет. Логический уровень на выводе PXn можно считать из бита PINXn. Перейдем к практике, предлагаю написать программу, которая будет по очереди зажигать каждый из 15 светодиодов, сперва напишем программу на С, а потом для разнообразия на ассемблере. Программа на С выглядит так:

»). Функция unsigned char _BV(b) возвращает байт, в котором бит под номером b устрановлен в единицу, а все остальные равны 0. Например, _BV(2)==0x04.
Попробует теперь написать аналогичную программу на ассемблере:

Секция Define chapter сопоставляет имена регистров с именами переменных. В секции Const chapter задаются константы, которые влияют на скорость бегущих огней. Далее идет сегмент кода Code segment в котором собственно и содержится код нашей программы. В коде программы сперва инициализируем стек, порты ввода/вывода конфигурируем как выхода, после чего в вечном цикле по одному светодиоды перебираем. Структура кода очень похожа на написанную выше программу С. Код на С более прост для понимания и компактен, но по размеру программы ассемблер обгоняет С (оптимизация не включена): 84 против 312 байт кода у С. Если же включить максимальную оптимизацию для С, то получим 184 байт кода, но придется совсем под другому переписать функцию задержки. Итого имеем, ассемблер более сложен, но код компактен и быстр, а С более прост, но код получившейся программы значительно больше. В заключение привожу видео готового устройства:

Советую не ограничиваться просто бегущим огоньком, а немного поэкспериментировать:

Комментировать
1 993 просмотров
Комментариев нет, будьте первым кто его оставит

Это интересно
No Image Автомобили
0 комментариев
No Image Автомобили
0 комментариев
No Image Автомобили
0 комментариев
Adblock
detector