/* * Monitor.asm * ATtiny13A * Created: 01.05.2013 20:12:46 * Author: sad */ .def temp=r16 ; директива .def назначает регистру temp имя temp .def temp1=r17 .def temp2=r18 .def temp3=r19 .def temp4=r20 .def temp5=r21 .dseg .org 0x60 digit: .byte 8 temporary: .byte 3 ;==================================================== ; Начало программы .cseg ; директива .cseg определяет начало сегмента, где будет расположен ; основной код программы. В AVR Studio 5 это директива не ; обязательна .org 0 ; начало первой строки программы rjmp Start ; относительный переход к метке Start (в PIC соответствует ; команде goto) rjmp INT_0 rjmp INT_1 rjmp Timer1_capt1 rjmp Timer1_comp1 rjmp Timer1_OVF1 rjmp Timer0_OVF0 rjmp UART_RX rjmp UART_UDRE rjmp UART_TX rjmp ANA_COMP INT_0: INT_1: Timer1_capt1: Timer1_comp1: ;счетчик Timer1_OVF1: Timer0_OVF0: UART_UDRE: UART_TX: UART_RX: ANA_COMP: reti ; ==================================================== Start: ;PortX содержит информацию, предназначенную для вывода. ;PinX содержит вводимую информацию ;DDRX содержит информацию о том, какой канал настроен на ввод, какой - на вывод. ;То есть, DDRX определяет, грубо говоря, какая ножка микросхемы будет подключена к PinX, какая - к PortX: ;0 - ввод ;1 - вывод ldi temp,RamEnd out SPL,temp ; инициализация стека ldi temp,0b00000001 out DDRB,temp ; RB0 - out ldi temp,0 out PortB,temp ; отключает подтягивающие резисторы ldi temp,0b10000001 ; Запуск ШИМ на выводе PB0 out TCCR0A,temp ldi temp,0b00000010 ;вкл таймер с предделителем out TCCR0B,temp sbi DDRB,0 ; Напишем программу математического блока rcall D_DIV latch: rjmp latch D_DIV: ; Выполняется digit+2,digit+1,digit / digit+4,digit+3=digit+9..digit+5 ; Делимое ldi temp,0xBB ; MSB sts digit+2,temp ldi temp,0xAA sts digit+1,temp ldi temp,0xff ; LSB sts digit,temp ; Делитель ldi temp,0xA0 ; MSB sts digit+4,temp ldi temp,0x03 sts digit+3,temp ;---------------------------------- ; Для выполнения деления нужен счетчик проходов, равный по величине числу бит ; делимого - в нашем случае 3 байта ; Отстаток от деления в temporary+2,..., temporary ldi temp,24 ; Запишем в счетчик число проходов ldi temp2,0 sts digit+7,temp2 ; Очистим будущий ответ sts digit+6,temp2 sts digit+5,temp2 sts temporary,temp2 sts temporary+1,temp2 sts temporary+2,temp2 Shift_Left: ; Выполним сдвиг делимого влево. начиная с LSB lds temp3,digit rol temp3 sts digit,temp3 lds temp3,digit+1 rol temp3 sts digit+1,temp3 lds temp3,digit+2 rol temp3 sts digit+2,temp3 ; Следом сдвинем переменную влево. начиная с LSB lds temp3,temporary rol temp3 sts temporary,temp3 sbrc temp3,0 ; Здесь удаляются лишние нули rjmp RLF_OTV ; стоящие в старших разрядах ; делимого dec temp tst temp brne Shift_Left ;breq Shift_Left prohod: lds temp3,digit rol temp3 sts digit,temp3 lds temp3,digit+1 rol temp3 sts digit+1,temp3 lds temp3,digit+2 rol temp3 sts digit+2,temp3 lds temp3,temporary rol temp3 sts temporary,temp3 lds temp3,temporary+1 rol temp3 sts temporary+1,temp3 lds temp3,temporary+2 rol temp3 sts temporary+2,temp3 RLF_OTV: lds temp3,digit+5 rol temp3 sts digit+5,temp3 lds temp3,digit+6 rol temp3 sts digit+6,temp3 lds temp3,digit+7 rol temp3 sts digit+7,temp3 ; Выполним вычитание делителя из временного значения lds temp3,digit+3 ; LSB lds temp4,temporary sub temp4,temp3 sts temporary,temp4 ; Save otvet lds temp3,digit+4 lds temp4,temporary+1 sbc temp4,temp3 sts temporary+1,temp4 ; Save otvet ; Если результат вычитания отрицательный ; то был заем. Поэтому прибавим число назад ; чтобы восстановить исходное значение tst temp4 brcc NO_ADD ; Выполним обратное сложение для восстановления числа ; в переменной lds temp3,digit+3 lds temp4,temporary add temp4,temp3 sts temporary,temp4 ; LSB lds temp3,digit+4 lds temp4,temporary+1 adc temp4,temp3 sts temporary+1,temp4 ; загрузили промежуточное значение rjmp NO_INC NO_ADD: lds temp3,digit+5 ; Установим нулевой бит в 1 sbr temp3,1 sts digit+5,temp3 NO_INC: dec temp cpi temp,0 brne one ret one: rjmp prohod D_MUL: ; Выполняется digit+2,digit+1,digit * digit+4,digit+3=digit+9..digit+5 ldi temp,0 sts digit+9,temp ; Очистим будущий ответ sts digit+8,temp sts digit+7,temp sts digit+6,temp sts digit+5,temp ; Извлечем множитель из оперативки lds temp2,digit+4 ; Старший байт lds temp1,digit+3 ; младший байт ; Для умножения на число необходим счетчик проходов, значение которого будет равно ; числу бит наименьшего числа. В нашем случае это значение составит 16 ldi temp,0x10 zicl_mul: ror temp2 ; Сдвигаем множитель вправо ror temp1 brcc shift_mul ; carry - 1? ; Суммируем старшие байты ответа и множимого lds temp3,digit lds temp4,digit+7 add temp4,temp3 sts digit+7,temp4 ; загрузили промежуточное значение lds temp3,digit+1 lds temp4,digit+8 adc temp4,temp3 sts digit+8,temp4 ; загрузили промежуточное значение lds temp3,digit+2 lds temp4,digit+9 adc temp4,temp3 sts digit+9,temp4 ; Если было переполнение, то бит carry войдет в регистр при сдвиге shift_mul: lds temp3,digit+9 ror temp3 ; производим сдвиг вправо от старшего sts digit+9,temp3 ; регистра ответа к младшему lds temp3,digit+8 ror temp3 sts digit+8,temp3 lds temp3,digit+7 ror temp3 sts digit+7,temp3 lds temp3,digit+6 ror temp3 sts digit+6,temp3 lds temp3,digit+5 ror temp3 sts digit+5,temp3 dec temp ; декремент счетчика проходов cpi temp,0 brne zicl_mul ret D_SUB: ; Выполняется temp4,temp3-temp2,temp1=temp4,temp3 ; temp2,temp1 сохраняют свои значения sbc temp4,temp2 sub temp3,temp1 ret D_ADD: ; Выполняется temp5,temp4,temp3+temp2,temp1=temp5,temp4,temp3 ; temp2,temp1 сохраняют свои значения add temp3,temp1 adc temp4,temp2 brcc out1 inc temp5 out1: ret .EXIT