Краткий курс - Самоучитель - AVR - быстрый старт с нуля.

Задача - упражнение 3

 

Книги и учебники по электронике скачать там
 

Цель задачи: 

1) Закрепить навыки программирования и работы в 
     компиляторе CodeVisionAVR

2) Учиться моделировать работу электронного устройства 
     в симуляторе VMLAB  - подробности с картинками.

3) Сделать универсальный таймер на микроконтроллере ATmega8
     с дискретной установкой времени.

 

Если вы еще не скачали все примеры применения AVR  
от производителя МК - прошу вас, сделайте это как 
можно быстрей - ЭТО СПРАВОЧНИК для вас!

Для выполнения задачи необходимо:

- прочитать этот курс avr123.nm.ru

- установить компилятор Си для AVR CodeVisionAVR

- Data Sheet на
МК AVR ATmega8 

- архив с текстами программ Таймера для CodeVisionAVR и VMLAB (8 Кб)

- установить симулятор VMLAB для AVR

- изучить задачи-упражнения 1 и 2        

- свободное время и желание.

 

 

 

Кратенько:

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

Я решил сделать таймер с дискретной установкой времени. 

Время таймера устанавливается с помощью двух "рояльных" (по 6 контактов в корпусе) переключателей - SW1 и SW2.

схема таймера (58 Кб)      

архив с текстами программ Таймера (8 Кб)

 

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

Их совсем не много:

1) МК ATmega8

2) Транзистор полевой IRLZ24.  Вы можете использовать любой подходящий, желательно из серии IRLxxxx - это мощные полевые (MOSFET) транзисторы управляемые логическими уровнями т.е. прямо от ножки МК (выбор на rel.ru и chip-dip.ru) на ток в 3 и более раз превышающий тот который вы будете коммутировать.

3) конденсаторы керамические 0.1 мкФ  4 шт.

4) резисторы 0.125 вт и более 5 шт.

5) конденсаторы электролитические на 470 и 5 мкФ на 16 и 10 вольт соответственно - 2 шт.  

6) стабилизатор напряжения на 5 вольт 7805 или 78L05 

7) светодиод

8) диод любой на 200 мА и более - например D4001 ... D4007  или 4148

9) 6 штырьков в два ряда на плату для подключения разъема 
внутрисхемного (ISP) программирования МК по стр. 7

10) необязательно - "рояльные" переключатели всего на 12 контактов. Можно просто сделать нужные перемычки припоем  на плате устройства!  Так китайские товарищи часто делают в своих  супер-пупер массовых поделках. Или джамперы поставить. 

11) кусочек макетной платы

 

Вот мои Советы по изготовлению плат, пайке и монтажу

 

Итак у нас всего 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 МГц 


Частота тактирования 1 МГц нас устраивает и МК поставляется с завода именно с такой частотой внутреннего генератора (подробнее в ДШ: "System Clock and Clock Options" и на стр. 2 курса), т.е. не нужно будет изменять фьюзы и не нужен будет внешний кварц с конденсаторами. 

Однако погрешность отсчета времени будет до 3% - можно сделать таймер точнее добавив кварцевый резонатор и пару конденсаторов по 27 пФ от ножек кварца на "землю". 

 

2) переходим в раздел порты  

 

В этих трех ярлыках-закладках  устанавливаем направления работы и 
дополнительные параметры (режим) нужных ножек для  каждого порта МК :

 

PORTB

ножки режим работы сигнал назначение
PB0 выход  1 светодиод выключен
PB1 выход  0 транзистор выключен
PB2 ВХОД Z определение исправности цепи нагрузки

"Z" - означает вход с высоким сопротивлением - т.е. без подтяжки, 
          считайте что его сопротивление более 10 МегаОм.


PORTD

ножки режим работы сигнал назначение
PD0 ... PD5 вход   с 
подтяжкой 
зависит от SW1   разряды от 0 до 6 набора времени таймера
PD6 вход   с 
подтяжкой 
зависит от SW3  запуск таймера
PD7 вход   с 
подтяжкой 
зависит от подключения ножки  PD7 длительность включения нагрузки

вход   с подтяжкой (или pull-up - с англ. тянуть вверх) это вход "Z" к которому 
"как бы" подключен резистор примерно 40 КОм от + питания МК. 

 

PORTC

ножки режим работы сигнал назначение
PС0 ... PС5 вход   с 
подтяжкой 
зависит от SW2   разряды от 7 до 12 набора времени таймера

 

Других настроек для нашей задачи не требуется. 

 

Но вы видите сколько ярлыков есть в мастере
и при необходимости можно настроить весь МК. 

 

 


3)  нажмите: 
          файл    ->   "Генерэйт, сэйв энд экзит" 

 

сохраните сгенерированный текст программы на Си

c:\VMLAB\_timerM8\main.c  

и файл проекта

c:\VMLAB\_timerM8\cv.prj 

еще один создаваемый визадом файл нам не нужен, но дайте 
ему любое имя а то CVAVR не отстанет...  :-)

 

4)         Будем наращивать на созданный мастером скелет программы main.c  - свой текст (код) который реализует работу таймера. Придумывать алгоритм будем по ходу работы.

Программу я буду писать на голубом фоне.

Так как алгоритм работы еще не известен, сделайте заголовок полаконичней, 
а когда алгоритм будет полностью ясен из программы - нужно не поленится и обязательно описать его в заголовке программы !

     
 

/*************************************
AVR123.nm.ru  

Project : timer
Date : 06.05.2005
Author : Termo


Chip type : ATmega8
Clock frequency : 1,000000 MHz
**************************************/


#include <mega8.h>

//подключил библиотеку с описанием регистров МК 

#include <delay.h>
// добавил библиотеку выполнения пауз

// Declare your global variables here
//
Объявите глобальные переменные здесь

unsigned int time_val @10; 
/* число сколько раз надо отсчитать по 0,2 сек. 

Двух байтовая переменная  time_val

Младший байт числа будет в регистре 10 а старший в регистре 11 и при отладке можно будет увидеть состояние SW1  SW2 */


unsigned char SW3_state; 
// состояние SW3 - это напряжение на PD6

unsigned char ctr; 
// вспомогательная переменная для счетчика

 
     


Компилятор предложил  разместить глобальные переменные. Я думаю трех  хватит, но возможно нам потребуется еще по ходу написания программы.    Добавим ... 



Обязательная для программ на Си главная функция:

     
 

void main(void) {
// Declare your local variables here

// приглашение объявить локальные переменные, 
// но нам они не нужны.

// Дальше оставим без изменения то что написал 
// Мастер начальной конфигурации МК:

// Input/Output Ports initialization

PORTB=0x01;
DDRB=0x03;

PORTC=0x3F;
DDRC=0x00;

PORTD=0xFF;
DDRD=0x00;

// Пропускаю большой кусок кода

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off

MCUCR=0x00;
// настройка прерываний от внешних сигналов

//
Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// An.Comp. Input Capture by Timer_ 1: Off

ACSR=0x80;
SFIOR=0x00; 

 
     


Выше есть  код конфигурирующий порты МК. Рассмотрим строку:

PORTC = 0x3F;

Она означает: присвоить переменной PORTC значение 3Fh  или  0011 1111 
в сочетании с нулем в регистре
DDRC это включит подтяжку входов для ножек 
порт_С с 5-й по 0-ю или PC5_PC0  - что мы и заказывали визаду.


Разберите самостоятельно конфигурацию портов B  и  D

Посмотрите в ДШ описания регистров содержащихся в тексте

 

Добавляем текст в программу:

     
 

//////////////////////////////////////

// Program starts here
// ===================================


PORTB.0 = 0; // включить светодиод

delay_ms(1000); // пауза 1000 мС или 1 сек

 
     


Нам нужно определить 12 разрядов числа отсчетов интервалов времени по 200 мС по состоянию переключателей SW1 и SW2.   Максимальное время отрабатываемое таймером приблизительно 

4095 * 0,2 = 819 сек или 13 минут 39 сек.

Если переключатель в SW1 SW2 замыкает вывод на "землю" на этом выводе будет "0" и конечно "0" будет в соответствующем регистре PINx и в соответствующем разряде (бите) в 12 битном числе таймера.

Если переключатель SW1 SW2 не замкнут то подтяжка создает 
на  входе высокий логический уровень "1".

     
 

time_val = 0; // обнуляем переменную

// читаем SW1 - это 6 млад. бит порта_D
// и записываем в биты 5
_0  time_val
time_val = PIND & 0b00111111;


// читаем SW2 - это 6 младших бит порта_C
// и записываем в биты 11
_6  time_val
time_val = time_val + ((PINC & 0b00111111)<<6);

 
     


По схеме подключения переключателей SW1  и SW2  в числах взятых из регистров PIND и PINC нам нужно оставить только 6 младших бит - т.е. обнулить биты 7 и 6. 

Я делаю это с помощью поразрядного логического И с битовой маской :

0b00111111

В результате биты числа на которое налагается маска не изменятся 
напротив единиц в маске и обнуляются напротив нулей в маске. 

После наложения битовой маски состояние SW1 записывается в time_val

А вот состояние SW2 нужно записать в биты 11_6 переменной 
time_val

Что бы сделать это нужно сдвинуть в лево на 6 позиций число полученное 
после наложения маски на значение регистра
PINC - это делается вот так:

<< 6

После сдвига полученное число складываем со значением уже хранящимся 
в 
time_val  и результат помещаем (присваиваем) в  time_val 

Теперь в битах 11_0 переменной  time_val  содержится 12-битный 
результат опроса состояния переключателей SW1 и SW2. 

 

     
 

Строку со сдвигом можно записать сокращенно :

time_val + = ((PINC & 0b00111111)<< 6);

Смотрите "язык Си для МК"

 
     

 

Подумайте как еще можно обнулить биты 7 и 6 в числе ?
Есть несколько способов.

Каковы биты 15_12 в  time_val  ?  ... почему ?

 

 

Проверка исправности нагрузки

В схеме таймера предусмотрены элементы позволяющие проверить исправность цепи нагрузки подключенной к разъему J2. Если нагрузка отключена или не проводит ток, т.е. имеет обрыв и значит не исправна, то на стоке транзистора будет "0" создаваемый резистором R5. 

Если нагрузка подключена и исправна то через неё будет протекать ток и напряжение на стоке транзистора будет близко к напряжению источника питания - это контакт 2 разъема питания J1.  

Напряжение от стока транзистора поступает через токо-ограничивающий 
резистор R4 на ножку - вход МК PB2 - узнав уровень на ней программа может 
судить о состоянии нагрузки. 

Так как входное сопротивление PB2 более 10 МОм а резистор R4  имеет сопротивление 1 МОм мы можем быть уверенны что при напряжении питания на J1 более 6 вольт и подключенной и исправной нагрузке, МК будет видеть высокий уровень "1" на нем.

 

 
Каким будет напряжение на PB2 при 9 вольт на J1 ?
Подсказка на стр. 2 курса - устройство МК - входные сигналы.

 

 

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

     
 

// Нужно проверить исправность цепи 
// нагрузки полевого транзистора 


if (PINB.2 == 0) { /*
Если на PB2 лог. "0" - нагрузка неисправна или не подключена */

while (1)

// будем быстро мигать (период 0.3 сек
// до устранения неисправности и нового 
// включения питания таймера

delay_ms(150); // пауза 150 мС

PORTB.0 = 1;   // вЫкл светодиод

delay_ms(150); // пауза 150 мС

PORTB.0 = 0;   // вкл светодиод 

       };
// это закрыв. скобка для while
}
// это закрыв. скобка для if 


// Если мы в этом месте программы, значит 
// нагрузка исправна и на PB2 есть "1".

 
     


Код по-моему понятный, но конечно его можно было бы записать 
и по другому - например более компактно - вот так:

     
 

if (!PINB.2) { /* Если на PB2 лог."0" */

while (1)

// будем быстро мигать (период 0.3 сек
// до устранения неисправности и нового 
// включения питания таймера

PORTB.0 ++; // ПЕРЕ-ключить светодиод
// добавив 1 к биту PB0

delay_ms(150); // пауза 150 мС
       };
// это закрыв. скобка для while

}
// это закрыв. скобка для if 

//  Смотрите "язык Си для МК"

 
     

 

Реклама недорогих радиодеталей почтой:

 

 

Добавим код запускающий таймер при изменении SW3

Таймер должен начинать счет при изменении состояния кнопки SW3  - очевидно нужно определить ее состояние и затем ждать когда оно изменится. Процесс ожидания подтверждает так же что МК определил исправность и наличие нагрузки. Для индикации того что мы находимся в ожидании запуска таймера добавим медленное мигание светодиода с периодом 1.4 Сек.

     
 

// Нужно определить состояние SW3

SW3_state = PIND.6; 
/* Если SW3 разомкнут, то подтяжка создаст на PD6 уровень "1", а если SW3 замкнут то на PD6 будет потенциал GND - это "0". 

Значит в SW3_state будет записана 1 или 0     */


ctr = 0; // обнулить вспомогательный счетчик

/*  Теперь будем ждать изменения состояния 
SW3 и мигать не спешно (период 1,4 сек) 
светодиодом в цикле while  */ 


while (PIND.6 == SW3_state) { 
// пока SW3 не изменился ...


delay_ms(20); // пауза 20 мс 

ctr++; /* увеличить значение переменной на 1 т.е. посчитать еще один интервал в 20 мСек */ 

// каждые 700 мс ...
    if (ctr == 35){ 

/* если прошло 35 раз по 20 мСек */

ctr = 0;
/* обнулить счетчик для начала отсчета следующих 700 мСек */
PORTB.0 ^= 1; // ПЕРЕключить светодиод 
                  }; //
скобка для if 

};
// скобка для while 


/* Если мы в этом месте программы, значит 
        состояние SW3 изменилось */

 
     


Разберем строку: 

while (PIND.6 == SW3_state)

Условие выполнения цикла while() это результат сравнения значений считанных  с ножки подключенной к SW3 (это PIND.6) и из переменной  SW3_state  хранящей прошлое состояние SW3. Пока эти значения равны  -  в скобках ( ) у  while  будет истина и тело цикла между  {      }  будет выполнятся.

Опрос кнопки происходит примерно каждые 20 мС.   Эти промежутки времени подсчитываются и при насчете 700 мС происходит изменение состояния светодиода.  

При изменении состояния SW3 условие у  while() станет "ложно" и программа покинет цикл ожидания этого изменения. 

 


Теперь надо запустить отсчет интервалов в 0.2 сек столько раз сколько содержится в переменной    time_val

     
 

// необязательно, но я добавил 1 
//    к количеству отсчетов 

time_val++;

ctr = 0;
// обнулил счетчик

/* для отсчета времени таймера опять используем 
цикл while  - он будет выполняться пока 
переменная
time_val больше 1. */

while (time_val > 1){

delay_ms(194); 
// я делаю паузу 194 мС вместо 200, так как 
// различные вычисления тоже потребуют времени

// ++++++++++++++++++++++++++++++
/* Следующий кусок программы делает хитрое 
мигание светодиодом с коротким временем горения 
и длинным не горением. */


ctr++; // добавить к счетчику 1

if (ctr < 2) { 
PORTB.0 = 0; // включить светодиод 

else {
PORTB.0 = 1; // вЫключить светодиод
}; 

if (ctr > 5) { 
ctr = 0; // обнулить счетчик


// конец кода "хитрого" мигания
// ++++++++++++++++++++++++++++++


time_val--; 
// вычесть 1 из переменной  time_val 

};

 
     


В этом куске кода интересно мигание светодиодом с разным временем 
горения и не горения.   Посмотрите,  благодаря строкам:

ctr++;

и

if (ctr > 5) { 
ctr = 0; // обнулить счетчик

значение переменной  ctr  меняется от 1 до 6.  

А по куску программы: 

if (ctr < 2) { 
PORTB.0 = 0; // включить светодиод 

else {
PORTB.0 = 1; // вЫключить светодиод
}; 

видно, что светодиод зажигается только при  ctr  равном 1.  

Значит светодиод будет гореть 1 прогон цикла while() - это 200 мС,  а выключен он будет 5 раз по 200 мС  т.е. целую секунду. Таким образом период мигания светодиода составит 1,2 Сек.

 

 


Задержка отработана - нужно включать нагрузку

Для этого мы откроем полевой транзистор подав на его затвор 
уровень логической "1" и еще включим светодиод.

     
 

PORTB.1 = 1; // открыть транзистор
PORTB.0 = 0; // включить светодиод

 
     

 

Нагрузку можно включить на 2 секунды или "на совсем" - т.е. пока подается питание на МК. Определяет это ножка PD7  - если она свободна то подтяжка на ней создает "1" и нагрузка будет включаться на 2 секунды. Если PD7 замкнута на землю, на ней будет "0" и нагрузка включится "на совсем".  

     
 

// Если на PD7 "1"
if (PIND.7 == 1) {

// можно было бы так написать:   if (PIND.7) {
//  Вам понятно почему ?

delay_ms(2000); // сделать паузу 2 сек.

PORTB.1 = 0; // вЫключить транзистор
PORTB.0 = 1; // вЫключить светодиод

};

 
     

 

 

Завершение программы

     
 

// программа завершена

while (1); // делать эту строчку "вечно"

} // закрывающая скобка для  main()

 
     

 


 

 

5)   "делаем" проект,   т.е. компилируем

программу нажав соотв. иконку: 

             или "Шифт + F9"

 

Получаем сообщение об успешной компиляции и 
отсутствии ошибок и "вонингов".

Если нет,  то проверьте текст программы 
       и постарайтесь найти ошибки.

В папке c:\VMLAB\_timerM8\ появилось много разных файлов, нам нужны :

- прошивка     main.hex

- исходник Си связанный с файлом .cof   для симулятора   main__.c

- main.cof    файл для симуляции с движением по коду на Си. Он сожержит связь        
                       содержимого первых  двух файлов.

- cv.prj      - это файл проекта   CodeVisionAVR

остальные файлы можно удалить.

 

 

 

Симуляция МК в VMLAB

 

6)      для проверки программы в VMLAB 

нужно создать файл проекта для VMLAB:

c:\VMLAB\_timerM8\vmlab.prj

В нем будет описан применяемый МК и то, что в нем и что к нему подключено. 

В этом файле не рекомендуется использовать русский шрифт,  поэтому там все по аглицки но думаю понятно.

Напомню, что комментарии в VMLAB пишутся в одну строчку после точки с запятой !

В начале как обычно заголовок

; **************************
; Timer simulation CodeVision + VMLAB

; more info: http://proavr.narod.ru


; ***************************
; Micro + software running
; -----------------------------------

Указываем симулятору какой МК симулировать:

.MICRO "ATmega8"

.TOOLCHAIN "GENERIC"

Указываем симулятору в каких файлах содержится
необходимая для симуляции информация.


.TARGET "main.hex" ; Proshivka v MK
.COFF "main.cof"
.SOURCE "main__.c" 

Именно такой файл __.c  текста программы на Си нужно использовать, ведь к нему привязаны данные в файле .cof

Указываем симулятору частоту тактирования МК  -  у нас она  1МГц

.CLOCK 1meg

Указание виртуальному  ЗАПОМИНАЮЩЕМУ осциллографу хранить данные симуляции за последние 2000 мс до остановки симуляции.

.STORE 2000m

Это время можно не указывать, но могут получаться очень большие файлы с  результатами симуляции.

Указываем название узлов и напряжения питания и "земли"

.POWER VDD = 5 VSS = 0

     
 

Внимание !    в VMLAB питание и "общий провод" 
называются не так как у МК в ДШ. Запомните !

 
     


Описание подключения светодиода - от питания МК   ---|>|---   к резистору 430 Ом и другой вывод резистора к ножке PB0  МК

; =========================
; LED diodes D2 and current limiting resistor R1


D1 VDD res16 ; LED diode 1 on control panel.

R16 res16 PB0 430
название (обозначение) 
резистора 
на схеме
название узла схемы к которому подключен один вывод резистора название узла схемы к которому подключен второй вывод резистора Величина резистора
в Ом

Таблица дана только для ясности описания резистора в  VMLAB. 
Не пытайтесь вставить таблицу в файл проекта - вас не поймут !



Теперь зададим некоторое число определяющее время отсчета таймера 
при  симуляции - я выбрал число для задержки 28 сек:


; =======================
; 12-bit digit for timer 0000 1000 1100 = 140
; x 0,2 = 28 sec



Для имитации замкнутых контактов SW1 и SW2 будем использовать резисторы  1 Ом от "земли" ( VSS) к соответствующим ножкам МК. 

     
 

В  VMLAB  нет перемычек для соединения узлов схемы, но можно использовать резисторы 1 и 0.1 и даже 0.01 Ом - вполне натурально !

 
     


На ножках МК к которым ни чего не подключено (точнее подключены разомкнутые контакты SW1 и SW2) будут лог "1" за счет включенной "подтяжке" к + питания МК.

R0 VSS PD0 1
R1 VSS PD1 1

R4 VSS PD4 1
R5 VSS PD5 1

R6 VSS PC0 1

R8 VSS PC2 1
R9 VSS PC3 1
R10 VSS PC4 1
R11 VSS PC5 1



Добавляем кнопку SW3

; =======================
; SW3 === K0 on ControlPanal


K0 PD6 VSS LATCHED
; SW3 key toggles from open to closed as you press it.

Использовали кнопку "0" на клавиатуре 4х4 в "Контрол пэнел" и подключили ее по схеме таймера -  к ножке PD6 МК и "общему" проводу устройства.

Кнопка с фиксацией (слово LATCHED), т.е. ее состояние меняется при каждом нажатии мышкой и остается таким до следующего нажатия.

В начале симуляции кнопка разомкнута !

 

Если вы считаете эту информацию полезной, пожалуйста, помогите информировать в интернете о курсе - просто щелкните по банеру. Большое спасибо !


Electronic Banner Exchange (ElBE)

 

Для моделирования подключения нагрузки мы 
используем кнопку  "С" на клавиатуре 4х4   и  резистор 1 МОм


; =======================
; Load simulation


KC PB2 VSS LATCHED; 

R20 VDD PB2 1M;

;if but. "C" was pressed - load looks like was been broken!
;if but. "C" was pressed once more - load looks like was been good!

В начале программы кнопки разомкнуты и на ножку-вход  PB2 будет поступает напряжение питания через резистор 1 МОм - значит на ней будет лог. "1" 
значит программа будет считать что нагрузка исправна.

Если нажать кнопку "С" то ее контакты замкнутся и PB2 окажется заземленной 
на ней появятся физический 0 вольт и соответственно лог. "0" - это соответствует случаю не исправной цепи нагрузки.

 

 

Кнопку "F" подключим к ножке PD7 позволяет выбрать включать ли нагрузку только на 2 секунды или включить ее и не выключать.   

; =======================
; How long IRLxxxx will state ON


KF PD7 VSS LATCHED; 

; if button "F" was pressed - IRLxxxx 
; will turn ON forefer


Если кнопку "F" не трогать, то она будет разомкнута и значит к ножке PD7 ни чего не будет подключено, подтяжка создас на ней "1" и значит транзистор будет включаться только на 2 сек . 

Если кнопку "F" нажать, то она замкнет ножку PD7 на "землю" и  транзистор будет включен после отработки таймером заданного времени "навсегда". 


Сигналы которые будут выводится в окно виртуального осциллографа SCOPE симулятора VMLAB :

Это  уникальный  инструмент !

; =======================
; Signals that will be ploted in SCOPE window


.plot V(PD6) V(PB2) V(PB0) V(PB1) V(PD7)
 

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

PD6 - состояние SW3

PB2 - состояние нагрузки

PB0 - светодиод:  "0" - включен      "1" - вЫключен

PB1 - управление транзистором: "1" - включен      "0" - вЫключен

PD7 - выбор длительности вкл. транзистора.

Узлы (точки) МК для подключения  "щупов" осциллографа 
SCOPE описаны конечно же в HELP симулятора ! 
   

Вот например для ATmega8 :

RESET, AREF, PB0-PB7, PC0-PC6, PD0-PD7, ACO, TIM1OVF, ADC6, ADC7

     
 

Внимание ! Только VMLAB похоже позволяет подключится к некоторым цепям внутри МК !

Сигналы  ACO и TIM1OVF  не доступны для подключения 
реального осциллографа к реальному МК

 
     

Конечно же вы можете отображать в 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 - автомобилисты знают его: проезд без остановки запрещен!

Программа остановится выполнив строчку с "точкой останова" 

Остановится конечно и счет времени работы программы:

При этом строчка подсветится и главное! выскочит (обещанное мной ранее) окно "меседжей" в котором будет указано состояние программного счетчика и время с начала программы - причем точней на один знак чем в правом нижнем углу экрана. 

Точек останова может быть столько сколько вам нужно !

Точки останова можно ставить и удалять в любое 
время симуляции и до ее начала.

     
 

Досадно !  Но точки останова не сохраняются при изменении симулируемых файлов. 

Когда вы поправите прогу в компиляторе Си и перекомпилировав ее сделаете "ре-билд" в VMLAB вам придется заново ставить нужные точки останова. 

А вот PROTEUS сохраняет расстановку точек останова.

 
     

 

Чтобы продолжить симуляцию и отсчет времени - нужно нажать одну из кнопок управления ходом симуляции:

Кнопки выполняют такие действия: 

светофор - запустить или продолжить работу МК. 

вторая кнопка - выполнить инструкцию, если это подпрограмма - то перешагнуть через нее не выполняя.

третья кнопка - выполнить очередную инструкцию. четвертая кнопка перейти в конец подпрограммы.

* Здесь речь идет об инструкциях и подпрограммах на ассемблере - так как МК выполняет непосредственно их. 

* Для пошагового исполнения программы кликайте третью кнопку или нажимайте клавишу F7. 

 

Вам не надо забивать голову ассемблером - 
у вас есть Си и точки останова.

Но если очень хочется взглянуть на исполнение ассемблерного кода - то конечно можно !  Для этого через меню "Window" откройте в низу списка выпавшего списка пункт 9 "Program memory" и насладитесь ассемблером.


6) давайте расставим пару точек останова. 

Первую "точку останова" поставим так как на третьем рисунке выше, т.е. перед началом цикла while отсчета времени таймером.

Вторую "точку останова" поставим после включения транзистора, на строчке включения светодиода:

 

 

Запускаем программу:

Кликнув на иконку - "зеленый светофор": 

Бабах! выскочило таки (обещанное мной ранее) окно "меседжей" в котором VMLAB начинает умничать: мол сторожевой таймер WDT вы не сбросили перед включением ... 

а мы его и не включали! но симулятор об этом знать не может потому что не имеет информации о состоянии фьюзов в МК. Просто предупреждает на всякий случай!

     
 

Но VMLAB все равно хороший ... 

Если почитать наконец его HELP то выяснится что он имеет кучу настроек 
и после указания типа МК можно указать состояние фьюзов и другие тонкости касаемо вашего варианта применения конкретного МК.

 
     

 

7) Продолжаем симуляцию опять кликнув на иконку - "зеленый светофор": 

Красота! программа работает... 

В правом нижнем углу экрана бежит время...  

РеалТайм одним словом...  ляпота !

Посмотрите на "контрол пэнел" зажегся светодиод! 

И очень интересные напряжения отображаются в осциллографе SCOPE 

 


Сотрите ! Напряжения на неподключенных ножках МК PD6 PB1 PD7 в начале были по 2,5 вольта примерно - это соответствует Z-состоянию в которых они находятся после старта МК - реально напряжение на них не известно и симулятор просто показывает нечто среднее между напряжением питания и 0 вольт. 

Через небольшое время, после выполнения программой кода инициализации портов уровни принимают четкие значения 5 или 0 вольт в соответствии с заданной нами конфигурацией портов.

А вот напряжения задаваемые внешними компонентами подключенными к МК (ножки PB2 и PB0) сразу приняли нужный уровень.

Переход "1" в "0" (говорят: "спад", "спад сигнала" или "отрицательный фронт") на PB0 - это включение светодиода.

 

Обязательно разберитесь с виртуальным ЗАПОМИНАЮЩИМ осциллографом SCOPE 

Он же логический анализатор. 

Почитайте о его возможностях в хелпе
понажимайте кнопочки... 

Используйте !

Это мощнейший инструмент электронщика - он 
позволяет увидеть электрический сигнал! 


 

7) и так... симуляция идет уже более 1 секунды, значит МК уже "засек" состояние нагрузки и SW3 - значит программа ждет изменения состояния переключателя SW3 (в симуляторе это кнопка 0) чтоб начать отсчет времени.

Давайте остановим программу красной кнопкой  

Внизу экрана время остановки программы 1659,1 мс. Давайте посмотрим окна: Code и Watch

 

Голубым подсвечена последняя выполненная строка программы. 

т.е. счетчик
ctr уже увеличен на 1. 

Интересна желтая подсветка - оказывается длина от левого края участка закрашенного желтым  пропорциональна тому сколько времени программа при работе проводит в соответствующей строке!  

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

Теперь информация о содержимом переменных в окне Watch 

- Значение счетчика ctr = 30 мало информативно так как я остановил программу в произвольный момент времени, успокаивает что это значение не превышает числа 35, иначе это было бы странно...

- второе значение переменной SW3_state = 1 радует, программа правильно поняла что контакты разомкнуты и надеюсь запустит счет времени при замыкании SW3.

- третья переменная особенно хороша, ведь она содержит значение 140, т.е. мы правильно задали его код перемычками в файле проекта VMLAB (точнее это были резисторы по 1 Ом!) и главное его правильно прочитал МК.

 

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.

Наконец то проверим правильность отсчета заданного 
12 битным двоичным кодом промежутка времени.

Что для измерения надо мы уже знаем! поставим два "брейк поинта" и посчитаем сколько между ними прошло времени.

Ставим "брейк поинты" слева от строчек программы здесь:


и здесь:

 

Запускаем продолжение симуляции кликом по светофору.

Обратите внимание! Светодиод медленно мигает и соответственно ведет себя сигнал PB0 в окне Scope   

Сделайте самостоятельно: остановите симуляцию и измерьте время переключения с помощью установки курсоров 1 и 2 в SCOPE на перепадах сигнала - интервал времени между курсорами будет показан в окошечке.

 

Кликните по кнопке 0 (проводок как бы оборвался). Программа остановится на первом "брейк поинте". В окне "меседжей" есть время остановки. У меня 13187,12 мс. 

Опять запускаем симуляцию.  

Наблюдайте как в окне Watch уменьшается значение переменной SW3_state. 

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


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

Ждемс...


Опаньки, включился транзистор! Остановились на втором "брейк поинте" 

Время в "Меседжах"

Итак считаем: 41187,44 - 13187,12 = 28000,32 мс

Не плохая точность!  любом случае точнее чем 3% точности встроенного в МК генератора на 1 МГц.



Признаю, что достиг я ее не сразу! Я уже гонял программу в симуляторе, некоторые пояснения есть в тексте исходника программы main.c  

я имею ввиду что в строке программы :

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 курса должен работать по программе. 

 

Благодаря энтузиасту программисту VMLAB пополняется новыми компонентами
 
  • AVR Studio Stimulus/Logger - Создание входных и захват выходных сигналов и их сохранение при симуляции в стиле AVR Studio
     
  • Verilog VCD Logger - Компонент позволяет сохранять в файл данные длительной симуляции.
     
  • WAV Analog Stimulus/Logger - Позволяет вводить в схему сигналы из звукового файла WAV и сохранять в таком же виде результат.
     
  • Break On Edge - Точки останова по изменению сигнала - очень мощно для симуляции.
     
  • Digital Signal Delay - Цифровая пауза для сигналов - позволяет сдвигать сигнал на нужное время.
     
  • COM Port Exchanger - "Квази Уно Фантазия" теперь VMLAB может работать с ваши физическим COM портом в ПК !  Свершилось.  Раньше такое только PROTEUS мог вытворять. Но PROTEUS конечно прекрасен.
     
  • LED 7-Segment Display - 7-сегментный индикатор с десятичной точкой - несколько. Очень популярные и недорогие средства индикации.
     

 

 

Если вам что-то не понятно, пожалуйста перечитайте задачу еще раз просмотрите рекомендованный 
материал и тексты программ

Я проверил и отладил устройство  
в реальной схеме - все работает! 

 

 

 

Задачи упражнения по курсу AVR 

 

 

 

 

 

 

 

 

 

 

ключевые слова: программирование микроконтроллеров, как написать программу для микроконтроллера, обучение программированию микроконтроллеров, микроконтроллеры atmega128, как запрограммировать микроконтроллер, как прошить микроконтроллер, отладка программы для AVR, моделирование работы электронных схем, электронные проекты, хобби, язык си для микроконтроллеров, язык программирования си
AT76C712 , AT76C713 , AT90CAN128 , AT90CAN128 Automotive , AT90CAN32 , AT90CAN64 , AT90PWM2 , AT90PWM3 , AT90S1200 , AT90S2313 , AT90S2323 , AT90S2343 , AT90S4433 , AT90S8515 , AT90S8535 , ATmega128 , ATmega1280 , ATmega1281 , ATmega16 , ATmega161 , ATmega162 , ATmega163 , ATmega164 , ATmega165 , ATmega168 , ATmega168 Automotive , ATmega169 , ATmega2560 , ATmega2561 , ATmega32 , ATmega323 , ATmega324 , ATmega325 , ATmega3250 , ATmega329 , ATmega3290 , ATmega406 , ATmega48 , ATmega48 Automotive , ATmega64 , ATmega640 , ATmega644 , ATmega645 , ATmega6450 , ATmega649 , ATmega6490 , ATmega8 , ATmega8515 , ATmega8535 , ATmega88 , ATmega88 Automotive , ATtiny11 , ATtiny12 , ATtiny13 , ATtiny15L , ATtiny2313 , ATtiny25 , ATtiny26 , ATtiny28L , ATtiny45 , ATtiny85

 

 

Сайт управляется системой uCoz