Только в этом месяце - скидки на паяльники и электронику с нашими кодами (123avr.com) :
![]() |
|
Совет - умейте правильно находить информацию!
|
Задача - упражнение 3 Цель задачи:1) Закрепить навыки программирования и работы в компиляторе CodeVisionAVR 2) Учиться моделировать работу электронного устройства в симуляторе VMLAB - подробности с картинками. 3) Сделать универсальный таймер на микроконтроллере ATmega8, с дискретной установкой времени.
Для выполнения задачи необходимо:
Кратенько:Может оказаться полезным простой, цифровой таймер - устройство включающее что либо по истечении определенного промежутка времени. Я решил сделать таймер с дискретной установкой времени.Время таймера устанавливается
с помощью двух "рояльных" (по 6
контактов в корпусе) переключателей - SW1
и SW2.
схема
таймера (58 Кб) Если вам захочется спаять таймер понадобятся следующие электронные компоненты == радио детали. Найти и купить их можно там. Их совсем не много:
Итак у нас всего 12 контактов, которыми можно замкнуть на "общий" провод (или "земля" - т.е. провод соединенный с выводами GND МК) устройства нужные выводы МК и таким образом закодировать 12 битное двоичное число. Это позволит сделать любую выдержку от 0 до 4095 ( это (2 в 12 степени) - 1) временных интервалов - отсчетов. Каждый отсчет я сделал по 0,2 сек. Значит таймер сможет отработать задержку до 13 минут 39 сек. с шагом в 0.2 сек. Конечно ВЫ можете изменить программу на другое время отсчета сделав другой шаг ! Таймер начинает счет при изменении состояния кнопки SW3. Если при включении питания таймера кнопка была разомкнута (например G-свич на модели ракеты) то таймер начнет отсчет после замыкания кнопки (например от перегрузки при старте ракеты) и будет считать уже не зависимо от состояния кнопки. Если при включении питания таймера кнопка была замкнута (например разрываемый при старте ракеты проводок) то таймер начнет отсчет после размыкания кнопки (значит ракета стартовала, проводок разорвался и кнопка "как бы" отжата) и тоже будет считать уже не зависимо от "состояния кнопки". Пишем программу. Так как программа будет проверяться в симуляторе VMLAB то сделаем одну папку c:\VMLAB\_timerM8 для всех нужных нам файлов симулятора и компилятора. Cоздание скелета программы и кода для начальной конфигурации МК с помощью мастера - генератора начального кода CodeWizardAVR 1) запускаем компилятор CodeVisionAVR и "кликаем" файл -> новый -> проект -> выбираем "кодвизад". Выбираем микроконтроллер ATmega8 и частоту 1 МГц
Однако погрешность отсчета времени будет до 3% - можно сделать таймер точнее добавив кварцевый резонатор и пару конденсаторов по 27 пФ от ножек кварца на "землю". 2) переходим в раздел порты
В этих
трех ярлыках-закладках устанавливаем направления работы
и PORTB
"Z" - означает вход с высоким сопротивлением - т.е. без подтяжки, считайте что его сопротивление более 10 МегаОм. PORTD
вход с подтяжкой (или pull-up - с англ. тянуть вверх) это вход "Z" к которому "как бы" подключен резистор примерно 40 КОм от + питания МК. PORTC
Других настроек для нашей задачи не требуется. Но вы видите сколько ярлыков есть в мастере и при необходимости можно настроить весь МК.
сохраните сгенерированный текст программы на Си c:\VMLAB\_timerM8\main.c и файл проекта c:\VMLAB\_timerM8\cv.prj , еще один создаваемый визадом файл нам не нужен, но дайте ему любое имя а то CVAVR не отстанет... :-) 4) Будем наращивать на созданный мастером скелет программы main.c - свой текст (код) который реализует работу таймера. Придумывать алгоритм будем по ходу работы. Программу я буду писать на голубом фоне. Так
как алгоритм работы еще не известен,
сделайте
заголовок полаконичней,
PORTC = 0x3F; Она
означает: присвоить переменной PORTC
значение
3Fh
или 0011 1111
Добавляем текст в программу:
Если
переключатель SW1 SW2 не замкнут то
подтяжка создает
Я делаю это с помощью поразрядного логического И с битовой маской : 0b00111111 В
результате биты числа на которое налагается
маска не изменятся После
наложения битовой маски состояние SW1
записывается в time_val Что
бы сделать это нужно сдвинуть в лево на 6
позиций число полученное << 6 После
сдвига полученное число складываем со
значением уже хранящимся Теперь
в битах 11_0 переменной time_val
содержится 12-битный
Подумайте
как еще можно обнулить биты 7 и 6 в числе ? Каковы биты 15_12 в time_val ? ... почему ? Проверка
исправности нагрузки Если нагрузка подключена и исправна то через неё будет протекать ток и напряжение на стоке транзистора будет близко к напряжению источника питания - это контакт 2 разъема питания J1. Напряжение
от стока транзистора поступает через
токо-ограничивающий Так как входное сопротивление PB2 более 10 МОм а резистор R4 имеет сопротивление 1 МОм мы можем быть уверенны что при напряжении питания на J1 более 6 вольт и подключенной и исправной нагрузке, МК будет видеть высокий уровень "1" на нем.
Добавим
в программу код проверяющий исправность
и наличие нагрузки
Добавим
код запускающий таймер при изменении SW3
while (PIND.6 == SW3_state) Условие выполнения цикла while() это результат сравнения значений считанных с ножки подключенной к SW3 (это PIND.6) и из переменной SW3_state хранящей прошлое состояние SW3. Пока эти значения равны - в скобках ( ) у while будет истина и тело цикла между { } будет выполнятся. Опрос кнопки происходит примерно каждые 20 мС. Эти промежутки времени подсчитываются и при насчете 700 мС происходит изменение состояния светодиода. При изменении состояния SW3 условие у while() станет "ложно" и программа покинет цикл ожидания этого изменения.
ctr++; и if (ctr > 5) { значение переменной ctr меняется от 1 до 6. А по куску программы: if (ctr < 2) { видно, что светодиод зажигается только при ctr равном 1. Значит светодиод будет гореть 1 прогон цикла while() - это 200 мС, а выключен он будет 5 раз по 200 мС т.е. целую секунду. Таким образом период мигания светодиода составит 1,2 Сек.
Нагрузку
можно включить на 2 секунды или "на
совсем" - т.е. пока подается питание на
МК. Определяет это ножка PD7 - если она
свободна то подтяжка на ней создает
"1" и нагрузка будет включаться на 2
секунды. Если PD7 замкнута на землю, на ней
будет "0" и нагрузка включится "на
совсем".
Завершение программы
5)
"делаем" проект, т.е.
компилируем программу нажав соотв. иконку: Получаем
сообщение об успешной компиляции и отсутствии ошибок и "вонингов".
Если нет,
то проверьте текст программы и
постарайтесь найти ошибки. - прошивка
main.hex остальные файлы можно удалить. Симуляция МК в VMLAB6) для проверки программы в VMLAB нужно создать файл проекта для VMLAB: c:\VMLAB\_timerM8\vmlab.prj В нем
будет описан применяемый МК и то, что в
нем и что к
нему подключено. Напомню, что комментарии в VMLAB пишутся в одну строчку после точки с запятой ! В начале как обычно заголовок
;
************************** Указываем
симулятору какой МК симулировать:
Указываем
симулятору в каких файлах содержится
Именно
такой файл __.c
текста программы на Си нужно
использовать, ведь к нему
привязаны данные в файле .cof Это время можно не указывать, но могут получаться очень большие файлы с результатами симуляции. Указываем
название узлов и напряжения питания и
"земли"
Таблица
дана только для ясности описания
резистора в VMLAB.
R0 VSS PD0 1
Использовали кнопку "0" на клавиатуре 4х4 в "Контрол пэнел" и подключили ее по схеме таймера - к ножке PD6 МК и "общему" проводу устройства. Кнопка с фиксацией (слово LATCHED), т.е. ее состояние меняется при каждом нажатии мышкой и остается таким до следующего нажатия.
В
начале симуляции кнопка разомкнута !
Для
моделирования подключения нагрузки
мы R20 VDD PB2 1M; В начале программы
кнопки разомкнуты и на ножку-вход PB2
будет поступает напряжение питания через
резистор 1 МОм - значит на ней будет лог.
"1" Если
нажать кнопку "С" то ее контакты
замкнутся и PB2 окажется заземленной Кнопку
"F" подключим к ножке PD7 позволяет
выбрать включать ли нагрузку только на 2
секунды или включить ее и не выключать.
Если
кнопку "F" нажать, то она замкнет
ножку PD7 на "землю" и транзистор
будет включен после отработки таймером
заданного времени "навсегда". Это
уникальный
инструмент ! PD6 - состояние SW3 PB2 - состояние нагрузки PB0 - светодиод: "0" - включен "1" - вЫключен PB1 - управление транзистором: "1" - включен "0" - вЫключен PD7 - выбор длительности вкл. транзистора.
Узлы
(точки) МК для подключения "щупов"
осциллографа
Вот
например для ATmega8 :
Конечно же вы можете отображать в SCOPE любые узлы симулируемой схемы. vmlab.prj - готов, можно симулировать программу.
Загрузите
архив с файлами для CVAVR и VMLAB Запускаем симулятор VMLAB: 1) В меню "прожект" выбираем "открыть проект":
и открываем файл проекта созданный чуть выше.
2) теперь проект нужно "отбилдить" - как я это называю. Меню "прожект" далее "ребилд ол-л" - должны получить сообщение об успехе:
Все готово к прогону программы.
3) для наблюдения по ходу работы программы за значениями в используемых нами переменных нужно открыть окно Watch
4) это окно
нужно настроить - щелкнув на нем правой
кнопкой мыши,
В нем помечаем переменные за которыми хотим наблюдать (я отметил все три) и в каком виде отображать содержимое переменных - я выбрал шестнадцатиричное и десятичное представление. Нажимаем "ОК". Теперь окошко выглядит так:
Так как программа не запущена, вместо значений переменных стоят знаки ? Мышкой можно придать удобную форму этому окну и разместить его на экране. Гораздо проще разместить все окна симулятора при разрешении экрана 1024х768 и более. Сделайте низким и не широким окно "Messages" - его выскакивать при симуляции не отключаемо. 5) Измерение времени выдержки таймера. По начальному положению кнопок в симуляторе у нас нагрузка транзистора исправна и SW3 разомкнут. Кроме того мы как бы выбрали переключателями число 140 соответствующее времени отсчета 28 секунд. Нам нужно
измерить время задержки таймера, т.е.
нужно while (time_val > 1){ записать на бумажку время с момента запуска программы - оно отображается в правом нижнем углу симулятора, например так:
дождаться завершения цикла и включения транзистора, сразу остановиться и опять записать время. Найдя разность двух записей мы определим реальную задержку отработанную таймером. Как в
VMLAB остановить симуляцию в нужном месте
программы на Си ? Слева от исполняемых строчек текста программы на Си где можно поставить точку останова , после загорания зеленого светофора появляются зеленые квадратики (в окне Code) - если клюкнуть по такому квадратику - он станет красным восьмиугольным знаком STOP - автомобилисты знают его: проезд без остановки запрещен!
Программа остановится выполнив строчку с "точкой останова" Остановится конечно и счет времени работы программы:
При этом строчка подсветится и главное! выскочит (обещанное мной ранее) окно "меседжей" в котором будет указано состояние программного счетчика и время с начала программы - причем точней на один знак чем в правом нижнем углу экрана. Точек останова может быть столько сколько вам нужно !
Точки
останова можно ставить и удалять в любое
Чтобы продолжить симуляцию и отсчет времени - нужно нажать одну из кнопок управления ходом симуляции:
Кнопки выполняют такие действия: светофор - запустить или продолжить работу МК. вторая кнопка - выполнить инструкцию, если это подпрограмма - то перешагнуть через нее не выполняя. третья кнопка - выполнить очередную инструкцию. четвертая кнопка перейти в конец подпрограммы. * Здесь речь идет об инструкциях и подпрограммах на ассемблере - так как МК выполняет непосредственно их. * Для пошагового исполнения программы кликайте третью кнопку или нажимайте клавишу F7.
Вам
не надо забивать голову ассемблером - Но если очень хочется взглянуть на исполнение ассемблерного кода - то конечно можно ! Для этого через меню "Window" откройте в низу списка выпавшего списка пункт 9 "Program memory" и насладитесь ассемблером. 6) давайте расставим пару точек останова. Первую "точку останова" поставим так как на третьем рисунке выше, т.е. перед началом цикла while отсчета времени таймером. Вторую "точку останова" поставим после включения транзистора, на строчке включения светодиода:
Запускаем программу: Кликнув на
иконку - "зеленый светофор":
Бабах! выскочило таки (обещанное мной ранее) окно "меседжей" в котором VMLAB начинает умничать: мол сторожевой таймер WDT вы не сбросили перед включением ...
а мы его и не включали! но симулятор об этом знать не может потому что не имеет информации о состоянии фьюзов в МК. Просто предупреждает на всякий случай!
7) Продолжаем
симуляцию опять кликнув на иконку - "зеленый
светофор":
Красота! программа работает... В правом нижнем углу экрана бежит время... РеалТайм одним словом... ляпота ! Посмотрите на
"контрол пэнел" зажегся светодиод!
Через небольшое время, после выполнения программой кода инициализации портов уровни принимают четкие значения 5 или 0 вольт в соответствии с заданной нами конфигурацией портов. А вот напряжения задаваемые внешними компонентами подключенными к МК (ножки PB2 и PB0) сразу приняли нужный уровень. Переход "1" в "0" (говорят: "спад", "спад сигнала" или "отрицательный фронт") на PB0 - это включение светодиода.
Обязательно разберитесь с виртуальным ЗАПОМИНАЮЩИМ осциллографом SCOPE Он же логический анализатор. Почитайте о его
возможностях в хелпе, Используйте ! Это
мощнейший инструмент электронщика -
он 7) и так... симуляция идет уже более 1 секунды, значит МК уже "засек" состояние нагрузки и SW3 - значит программа ждет изменения состояния переключателя SW3 (в симуляторе это кнопка 0) чтоб начать отсчет времени. Давайте
остановим программу красной кнопкой Внизу экрана время остановки программы 1659,1 мс. Давайте посмотрим окна: Code и Watch
Голубым
подсвечена последняя выполненная
строка программы. Интересна желтая подсветка - оказывается длина от левого края участка закрашенного желтым пропорциональна тому сколько времени программа при работе проводит в соответствующей строке! Причем "прокручивая" вертикально текст программы можно увидеть наиболее интенсивно увеличивающуюся желтую область и так определить где крутится или зависла программа. Теперь информация о содержимом переменных в окне Watch
8) Давайте проверим как поведет себя программа если выключатель будет SW3 замкнут при старте МК. Для этого нам нужен "глубокий сброс" МК - он эквивалентен отключению питания МК. Сделать это
можно кнопкой
Теперь поставим "точку останова" слева от строчки: ctr++; // увеличить значение...
Программа проверяет состояние SW3 через 1 секунду с небольшим после включения МК, т.е. в течении 1 секунды (к счастью в симуляторе это несколько секунд) нужно нажать кнопку "0" на Control panel а результат нажатия можно наблюдать в окне осциллографа Scope по поведению сигнала на ножке МК PD6 Итак сделайте видимым окно Scope, сделайте горизонтальное разрешение 50 мс и расположите поудобней кнопку 0 и нажмите светофор 2 раза. Не спешно кликните кнопку 0. Давайте дождемся остановки программы на поставленном ранее "брейк поинте". Остановилась симуляция! время 1034,52 мс Смотрите окно Scope , горизонтальной прокруткой отмотайте время назад чтоб обнаружить спад сигнала на PD6. Он из "1" стал "0" и главное остался таким после отпускания кнопки мыши, т.е. нас не обманули - кнопка и правда с фиксацией. Теперь посмотрите окно "Воч" - переменная SW3_state теперь равна 0. А в прошлый раз при разомкнутой кнопке была равна 1. Ну а значение 140 нас уже не удивляет. Похоже программа работает как было задумано.
9) Представим, что замкнутый SW3 это проволочная перемычка и таймер должен начать счет при обрыве этой проволочки, т.е. при размыкании SW3 - чтоб это изобразить нам надо всего лишь запустить симуляцию дальше и кликнуть по кнопке 0. Наконец
то проверим правильность отсчета
заданного Что для измерения надо мы уже знаем! поставим два "брейк поинта" и посчитаем сколько между ними прошло времени. Ставим "брейк поинты" слева от строчек программы здесь:
Запускаем продолжение симуляции кликом по светофору. Обратите внимание! Светодиод медленно мигает и соответственно ведет себя сигнал PB0 в окне Scope Сделайте самостоятельно: остановите симуляцию и измерьте время переключения с помощью установки курсоров 1 и 2 в SCOPE на перепадах сигнала - интервал времени между курсорами будет показан в окошечке.
Кликните по кнопке 0 (проводок как бы оборвался). Программа остановится на первом "брейк поинте". В окне "меседжей" есть время остановки. У меня 13187,12 мс. Опять запускаем симуляцию. Наблюдайте как в окне Watch уменьшается значение переменной SW3_state. Понаблюдайте, а при желании остановите симуляцию и измерьте курсорами, за миганием светодиодом - он должен гореть 200 мс и быть погашенным 1000 мс.
Ждемс...
Время в "Меседжах"
Итак считаем: 41187,44 - 13187,12 = 28000,32 мс Не плохая точность! любом случае точнее чем 3% точности встроенного в МК генератора на 1 МГц.
я имею ввиду что в строке программы : delay_ms(194); не сразу возникло число 194. Конечно я начал со 199 скомпилировал, посимулировал и посчитал что 194 в самый раз.
10) Давайте измерим время горения светодиода при отсчете времени таймером. - разверните окно SCOPE на весь экран. - установите горизонтальный масштаб 1 мс на деление - вертикальный масштаб 1 вольт на деление - прокрутками поместите спад (это включение светодиода) сигнала PB0 по центру экрана. - выберите курсор 1 и наведите перекрестие курсора на спад сигнала и кликните мышкой чтоб установить вертикаль времени. - выберите курсор 2 - горизонтальной прокруткой сместитесь вправо по сигналу до его фронта - это соответствует вЫключению светодиода - наведите перекрестие на фронт сигнала и кликните. Ха! как вам такой результат!
Ровно 200 мс - то что доктор прописал, точнее то, что запрограммировали... Обратите внимание! на картинке видно, что при включенном светодиоде напряжение на PB0 не 0 вольт, а примерно 0,5 вольт! Это довольно значительный ток протекающий через включенный светодиод не дает МК создать "чистый" 0 на ножке - т.е. симулятор пытается изобразить протекание процессов как в реальном устройстве. Кстати! Результат симуляции vмежду ертикальными метками в окне SCOPE вы можете сохранить в виде файла распространенного формата .CSV (данные разделенные запятыми - такой формат широко применяется в измерительной технике). Этот файл можно импортировать например в Excel и построить графики, либо обработать данные аналитически, а можно эти же данные завести на другой симулируемый МК ... Нажмите кнопку Export
Подробней смотрите пожалуйста в хелпе симулятора.
11) Конечно можно получить время горения и не горения светодиода сразу в цифровом виде - нужно в соответствующих местах поставить точки останова и считывать время в окне "меседжей" и посчитать на калькуляторе Windows в инженерном режиме.
Попробуйте прогнать программу сами - это полезно и пригодится вам.
Надеюсь вы самостоятельно проверите как поведет себя программа если цепь нагрузки транзистора окажется оборвана. И как изменится характер включения транзистора при замыкании на землю ножки PD7 МК. Я все это проверил, работает.
Задача завершена.Таймер собранный из исправных деталей и запрограммированный по рекомендациям на странице 7 курса должен работать по программе. Если вам что-то не понятно, пожалуйста перечитайте задачу еще раз просмотрите рекомендованный материал и тексты программ. Я проверил и отладил устройство в реальной схеме - все работает! |
|
Copyright 2009-2019 123avr.com