
Частоту работы таймера я еще не настроил, потому что еще нету кварца на таймер, поэтому там два значения которые напрямую зависят от частоты я написал "от балды". Вот сама программа (для амеги64):
Код
;программа электронных часов
;16.06.2011г.
;Черепанов Сергей Андреевич
;для ATMega64
.device ATMega64;
.nolist;
.include "C:\Program Files\Atmel\AVR Tools\AvrAssembler2\Appnotes\m64def.inc";
.list;
.def temp=r16;
.def seconds=r17;
.def minutes=r18;
.def hours =r19;
.def incr =r20;
.def min_ed =r21;
.def min_des=r22;
.def hs_ed =r23;
.def hs_des =r24;
;===============================================================
;здесь находятся макросы
.macro pushf;
push r16;
in r16,sreg;
push r16;
.endm
.macro popf;
pop r16;
out sreg,r16;
pop r16;
.endm;
.macro delenie_min;
;первый макрос-раскидывает значение minutes по переменным, а именно:
;десятки минут в переменную min_des, а единицы в min_ed
push minutes ;сохраняем первоначальное значение minutes;
pushf;
loop:
cpi minutes,10;
brmi ostatok ;если число >10, то вылезет флаг отриц. числа, и произойдет переход
sbci minutes,10;
inc min_des;
jmp loop;
ostatok:
mov min_ed,minutes;
popf;
pop minutes ;вытаскиваем обратно значение minutes
.endm;
.macro delenie_hs ;аналогично только работает со значениями hours, hs_ed, hs_des
push hours;сохраняем первоначальное значение hours;
pushf;
loop:
cpi hours,10;
brmi ostatok ;если число меньше 10, то вылезет флаг отриц. числа, и произойдет переход
sbci hours,10;
inc hs_des;
jmp loop;
ostatok:
mov hs_ed,hours;
popf;
pop hours;вытаскиваем обратно значение hours
.endm;
.macro select ;выбирает правильный код, который выводится на индикатор
pushf;
cpi temp,0;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
cpi temp,1;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
cpi temp,2;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
cpi temp,3;
brne pc+2;
ldi temp,0b00111111;
rjmp exit;
cpi temp,4;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
cpi temp,5;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
cpi temp,6;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
cpi temp,7;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
cpi temp,8;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
cpi temp,9;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
exit:
popf;
.endm;
;===============================================================
;===============================================================
.cseg;
.org 0xff;видимо с 250-ой строки начинается eeprom, и вылетает ошибка,
;поэтому код начинается со строки 0xff
;таблица прерываний:
.org 0x0000 jmp Init; Reset Handler
.org 0x0002 reti; IRQ0 Handler
.org 0x0004 reti; IRQ1 Handler
.org 0x0006 reti; IRQ2 Handler
.org 0x0008 reti; IRQ3 Handler
.org 0x000A reti; IRQ4 Handler
.org 0x000C reti; IRQ5 Handler
.org 0x000E reti; IRQ6 Handler
.org 0x0010 reti; IRQ7 Handler
.org 0x0012 reti; Timer2 Compare Handler
.org 0x0014 reti; Timer2 Overflow Handler
.org 0x0016 reti; Timer1 Capture Handler
.org 0x0018 reti; Timer1 CompareA Handler
.org 0x001A reti; Timer1 CompareB Handler
.org 0x001C reti; Timer1 Overflow Handler
.org 0x001E reti; Timer0 Compare Handler
.org 0x0020 rjmp timer_ok; Timer0 Overflow Handler
.org 0x0022 reti; SPI Transfer Complete Handler
.org 0x0024 reti; USART0 RX Complete Handler
.org 0x0026 reti; USART0,UDR Empty Handler
.org 0x0028 reti; USART0 TX Complete Handler
.org 0x002A reti; ADC Conversion Complete Handler
.org 0x002C reti; EEPROM Ready Handler
.org 0x002E reti; Analog Comparator Handler
.org 0x0030 reti; Timer1 CompareC Handler
.org 0x0032 reti; Timer3 Capture Handler
.org 0x0034 reti; Timer3 CompareA Handler
.org 0x0036 reti; Timer3 CompareB Handler
.org 0x0038 reti; Timer3 CompareC Handler
.org 0x003A reti; Timer3 Overflow Handler
.org 0x003C reti; USART1 RX Complete Handler
.org 0x003E reti; USART1,UDR Empty Handler
.org 0x0040 reti; USART1 TX Complete Handler
.org 0x0042 reti; Two-wire Serial Interface Handler
.org 0x0044 reti; SPM Ready Handler
rjmp init;
;===============================================================
;подпрограмма срабатывающая при прерывании, инкрементирует значение incr,и
;сравнивает с определенной константой, зависящей от частоты работы таймера
;в случае равенства incr сбрасывается, а seconds инкрементируется
timer_ok:
pushf;
inc incr;
cpi incr,100;вот эта сотня по идее и написана "от балды"
breq equal;
jmp exit;
equal:
clr incr;
inc seconds;
exit:
popf;
reti;
;===============================================================
init:
clr r16; на всякий случай подчистим регистры
clr r17;
clr r18;
clr r19;
clr r20;
clr r21;
clr r22;
clr r23;
clr r24;
out sreg,temp;
LDI R16,Low(RAMEND);инициализируем стек |
OUT SPL,R16; |
; |
LDI R16,High(RAMEND); |
OUT SPH,R16; ____|
ldi temp,0x99;грузим значение, до которого будет бегать таймер (0х99-число абсолютно случайное, я его потом поменяю)
out ocr0,temp;
ldi temp,(WGM01<<1)|(WGM00<<0)|(CS02<<1)|(CS01<<1)|(CS00<<1);поставил таймер в
out tccr0,temp; режим СТС и прескалер =1024
ldi temp,(TOIE0<<1);разрешам прерывания локально
out TIMSK,temp;
ldi temp,(TOV0<<1);
out tifr,temp;
;===============================================================
Start:
;на всякий случай еще раз разрешам прерывания локально:
ldi temp,0b00000001;
out TIMSK,temp;
out TIFR,temp;
;эта часть кода выводит на индикаторы значение минут и секунд
delenie_min;
delenie_hs;
cpi min_ed,10; ;brmi может не достать до инит, поэтому юзать jmp
brmi pc+2 ;brmi работает по принципу Rd-const, и если min_ed>10 то
rjmp init; ;получится положительное число, чего быть не должно
;значит программа сбилась...
mov temp,min_ed ;т.к. макрос работает только с темп, то туда и грузим значение
select;
out porta,temp ;на выходе получаем в качестве темр нужное число
cpi min_des,10 ;здесь аналогичная проверка
brmi pc+2;
rjmp init;
mov temp,min_des;в след. трех случаях аналогично используем макрос
select;
out portb,temp;
cpi hs_ed,10 ;здесь аналогичная проверка
brmi pc+2;
rjmp init;
mov temp,hs_ed;
select;
out portc,temp;
cpi hs_des,10 ;здесь аналогичная проверка
brmi pc+2;
rjmp init;
mov temp,hs_des;
select;
out portd,temp;
;здесь уже начинается проверка на увеличение переменных
;
cpi seconds,60;
breq pc+2 ;здесь срабатывает если прошла одна минута
rjmp start ;значит еще не прошла одна минута
clr seconds;
inc minutes;
cpi minutes,60;
breq pc+2 ;срабатывает если прошел один час
rjmp start ;еще не прошел один час
clr minutes;
inc hours;
cpi hours,24;
breq pc+2 ;аналогично
rjmp start;
clr hours;
rjmp start;
;16.06.2011г.
;Черепанов Сергей Андреевич
;для ATMega64
.device ATMega64;
.nolist;
.include "C:\Program Files\Atmel\AVR Tools\AvrAssembler2\Appnotes\m64def.inc";
.list;
.def temp=r16;
.def seconds=r17;
.def minutes=r18;
.def hours =r19;
.def incr =r20;
.def min_ed =r21;
.def min_des=r22;
.def hs_ed =r23;
.def hs_des =r24;
;===============================================================
;здесь находятся макросы
.macro pushf;
push r16;
in r16,sreg;
push r16;
.endm
.macro popf;
pop r16;
out sreg,r16;
pop r16;
.endm;
.macro delenie_min;
;первый макрос-раскидывает значение minutes по переменным, а именно:
;десятки минут в переменную min_des, а единицы в min_ed
push minutes ;сохраняем первоначальное значение minutes;
pushf;
loop:
cpi minutes,10;
brmi ostatok ;если число >10, то вылезет флаг отриц. числа, и произойдет переход
sbci minutes,10;
inc min_des;
jmp loop;
ostatok:
mov min_ed,minutes;
popf;
pop minutes ;вытаскиваем обратно значение minutes
.endm;
.macro delenie_hs ;аналогично только работает со значениями hours, hs_ed, hs_des
push hours;сохраняем первоначальное значение hours;
pushf;
loop:
cpi hours,10;
brmi ostatok ;если число меньше 10, то вылезет флаг отриц. числа, и произойдет переход
sbci hours,10;
inc hs_des;
jmp loop;
ostatok:
mov hs_ed,hours;
popf;
pop hours;вытаскиваем обратно значение hours
.endm;
.macro select ;выбирает правильный код, который выводится на индикатор
pushf;
cpi temp,0;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
cpi temp,1;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
cpi temp,2;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
cpi temp,3;
brne pc+2;
ldi temp,0b00111111;
rjmp exit;
cpi temp,4;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
cpi temp,5;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
cpi temp,6;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
cpi temp,7;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
cpi temp,8;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
cpi temp,9;
brne pc+3;
ldi temp,0b00111111;
rjmp exit;
exit:
popf;
.endm;
;===============================================================
;===============================================================
.cseg;
.org 0xff;видимо с 250-ой строки начинается eeprom, и вылетает ошибка,
;поэтому код начинается со строки 0xff
;таблица прерываний:
.org 0x0000 jmp Init; Reset Handler
.org 0x0002 reti; IRQ0 Handler
.org 0x0004 reti; IRQ1 Handler
.org 0x0006 reti; IRQ2 Handler
.org 0x0008 reti; IRQ3 Handler
.org 0x000A reti; IRQ4 Handler
.org 0x000C reti; IRQ5 Handler
.org 0x000E reti; IRQ6 Handler
.org 0x0010 reti; IRQ7 Handler
.org 0x0012 reti; Timer2 Compare Handler
.org 0x0014 reti; Timer2 Overflow Handler
.org 0x0016 reti; Timer1 Capture Handler
.org 0x0018 reti; Timer1 CompareA Handler
.org 0x001A reti; Timer1 CompareB Handler
.org 0x001C reti; Timer1 Overflow Handler
.org 0x001E reti; Timer0 Compare Handler
.org 0x0020 rjmp timer_ok; Timer0 Overflow Handler
.org 0x0022 reti; SPI Transfer Complete Handler
.org 0x0024 reti; USART0 RX Complete Handler
.org 0x0026 reti; USART0,UDR Empty Handler
.org 0x0028 reti; USART0 TX Complete Handler
.org 0x002A reti; ADC Conversion Complete Handler
.org 0x002C reti; EEPROM Ready Handler
.org 0x002E reti; Analog Comparator Handler
.org 0x0030 reti; Timer1 CompareC Handler
.org 0x0032 reti; Timer3 Capture Handler
.org 0x0034 reti; Timer3 CompareA Handler
.org 0x0036 reti; Timer3 CompareB Handler
.org 0x0038 reti; Timer3 CompareC Handler
.org 0x003A reti; Timer3 Overflow Handler
.org 0x003C reti; USART1 RX Complete Handler
.org 0x003E reti; USART1,UDR Empty Handler
.org 0x0040 reti; USART1 TX Complete Handler
.org 0x0042 reti; Two-wire Serial Interface Handler
.org 0x0044 reti; SPM Ready Handler
rjmp init;
;===============================================================
;подпрограмма срабатывающая при прерывании, инкрементирует значение incr,и
;сравнивает с определенной константой, зависящей от частоты работы таймера
;в случае равенства incr сбрасывается, а seconds инкрементируется
timer_ok:
pushf;
inc incr;
cpi incr,100;вот эта сотня по идее и написана "от балды"
breq equal;
jmp exit;
equal:
clr incr;
inc seconds;
exit:
popf;
reti;
;===============================================================
init:
clr r16; на всякий случай подчистим регистры
clr r17;
clr r18;
clr r19;
clr r20;
clr r21;
clr r22;
clr r23;
clr r24;
out sreg,temp;
LDI R16,Low(RAMEND);инициализируем стек |
OUT SPL,R16; |
; |
LDI R16,High(RAMEND); |
OUT SPH,R16; ____|
ldi temp,0x99;грузим значение, до которого будет бегать таймер (0х99-число абсолютно случайное, я его потом поменяю)
out ocr0,temp;
ldi temp,(WGM01<<1)|(WGM00<<0)|(CS02<<1)|(CS01<<1)|(CS00<<1);поставил таймер в
out tccr0,temp; режим СТС и прескалер =1024
ldi temp,(TOIE0<<1);разрешам прерывания локально
out TIMSK,temp;
ldi temp,(TOV0<<1);
out tifr,temp;
;===============================================================
Start:
;на всякий случай еще раз разрешам прерывания локально:
ldi temp,0b00000001;
out TIMSK,temp;
out TIFR,temp;
;эта часть кода выводит на индикаторы значение минут и секунд
delenie_min;
delenie_hs;
cpi min_ed,10; ;brmi может не достать до инит, поэтому юзать jmp
brmi pc+2 ;brmi работает по принципу Rd-const, и если min_ed>10 то
rjmp init; ;получится положительное число, чего быть не должно
;значит программа сбилась...
mov temp,min_ed ;т.к. макрос работает только с темп, то туда и грузим значение
select;
out porta,temp ;на выходе получаем в качестве темр нужное число
cpi min_des,10 ;здесь аналогичная проверка
brmi pc+2;
rjmp init;
mov temp,min_des;в след. трех случаях аналогично используем макрос
select;
out portb,temp;
cpi hs_ed,10 ;здесь аналогичная проверка
brmi pc+2;
rjmp init;
mov temp,hs_ed;
select;
out portc,temp;
cpi hs_des,10 ;здесь аналогичная проверка
brmi pc+2;
rjmp init;
mov temp,hs_des;
select;
out portd,temp;
;здесь уже начинается проверка на увеличение переменных
;
cpi seconds,60;
breq pc+2 ;здесь срабатывает если прошла одна минута
rjmp start ;значит еще не прошла одна минута
clr seconds;
inc minutes;
cpi minutes,60;
breq pc+2 ;срабатывает если прошел один час
rjmp start ;еще не прошел один час
clr minutes;
inc hours;
cpi hours,24;
breq pc+2 ;аналогично
rjmp start;
clr hours;
rjmp start;