| 
													Последний раз редактировалось _Ivana 18.12.2012, 20:32, всего редактировалось 3 раз(а).
												
 
 Берем число (например, двухбайтовое целое), пока оно больше 10000 - вычитаем из него 10000, считаем сколько раз вычли в отдельном регистре. Прибавляем к значению регистра счетчика код символа "0" - получаем код символа нужной цифры текущего десятичного разряда - шлем его по USART на комп где в любой терминальной программе он выводится как десятичная цифра. Далее - в исходных регистрах у нас остался остаток меньше 10000 - начинаем вычитать из него 1000 и действуем по тому уже алгоритму. (Оффтоп) Код:    .include "Tn13def.inc"
 
 ; функции ножек
 
 .equ   _PIN_PC_OUT            = PB2      ; 7 - й PIN - вывод данных на комп
 .equ   _PIN_RELE_OUT1         = PB3      ; 2 - й PIN - выход на обмотку 1
 .equ   _PIN_RELE_OUT2         = PB1      ; 6 - й PIN - выход на обмотку 2
 .equ   _PIN_RELE_IN1         = PB4      ; 3 - й PIN - вход контакта 1
 .equ   _PIN_RELE_IN2         = PB0      ; 5 - й PIN - вход контакта 2
 
 ; регистры общего назначения
 
 .def   _r_mom               = r16      ; служебный регистр для записи в порты
 .def   _r_WAIT               = r17
 
 .def   _r_count_measure_sets   = r18
 .def   _r_transmit_data      = r19
 
 .def   _r_t1_lb            = r20
 .def   _r_t1_hb            = r21
 .def   _r_t1_last_lb         = r22
 .def   _r_t1_last_hb         = r23
 .def   _r_t2_lb            = r24
 .def   _r_t2_hb            = r25
 .def   _r_t2_last_lb         = r26
 .def   _r_t2_last_hb         = r27
 
 .def   _r_count_measure_time_lb   = r28
 .def   _r_count_measure_time_hb   = r29
 
 ; переменные
 
 .equ   _one_measure_time      = 96      ; тактов = 10us - дискретность измерения
 
 .equ   _max_measure_time      = 3000      ; циклов по 10us = 30ms - интервал измерения
 
 .equ   _sets_of_measures      = 10      ; количество измерений (1 измерение = туда + обратно)
 
 ;.equ   _RS232_time            = 1000      ; тактов бита RS232 для скорости 9600 бод
 .equ   _RS232_time            = 250      ; тактов бита RS232 для скорости 38400 бод
 
 ; для десятичной системы исчисления
 
 .equ   _SI_order            = 10      ; для десятичной системы исчисления при выводе результатов
 ;.equ   _max_length_SI         = 5         ; макс. разрядность чисел в _SI_order
 
 .equ   _SI_order_0            = 1
 .equ   _SI_order_1            = _SI_order
 .equ   _SI_order_2            = _SI_order_1*_SI_order_1
 .equ   _SI_order_3            = _SI_order_2*_SI_order_1
 .equ   _SI_order_4            = _SI_order_3*_SI_order_1
 
 ; нужные коды KOI_8
 
 .equ   KOI_8_comma            = $2C      ; код ","
 .equ   KOI_8_semicolon         = $3B      ; код ";"
 .equ   KOI_8_ps            = $0A      ; код "перевод строки"
 .equ   KOI_8_vk            = $0D      ; код "возврат каретки"
 
 ;--------------------------------------------------------------------
 
 rjmp   RESET                      ; Reset Handler
 reti      ;rjmp EXT_INT0             ; IRQ0 Handler
 reti      ;rjmp   PIN_CHANGE                   ; PCINT0 Handler
 reti      ;rjmp TIM0_OVF             ; Timer0 Overflow Handler
 reti      ;rjmp EE_RDY             ; EEPROM Ready Handler
 reti      ;rjmp ANA_COMP             ; Analog Comparator Handler
 reti      ;rjmp   TIM0_COMPA                   ; Timer0 CompareA Handler
 reti      ;rjmp TIM0_COMPB          ; Timer0 CompareB Handler
 reti      ;rjmp WATCHDOG             ; Watchdog Interrupt Handler
 reti      ;rjmp ADCCONV            ; ADC Conversion Handler
 ;--------------------------------------------------------------------
 
 RESET:
 
 ldi    _r_mom, (1<<_PIN_RELE_OUT1) + (1<<_PIN_RELE_OUT2) + (1<<_PIN_PC_OUT)
 out    DDRB, _r_mom            ; пины выходов
 
 ldi    _r_mom, (1<<_PIN_RELE_IN1) + (1<<_PIN_RELE_IN2)
 out    PORTB, _r_mom            ; подтягиваюие резисторы на входы
 
 ;   ldi    _r_mom, (1<<_PIN_RELE_IN1) + (1<<_PIN_RELE_IN2) + (1<<_PIN_RELE_OUT1) + (1<<_PIN_RELE_OUT2)
 ;   out    PCMSK, _r_mom            ; маска пинов для прерываний по pin change
 
 rjmp    MAIN
 ;--------------------------------------------------------------------
 ; прерывание по изменению состояния выводов
 
 ;PIN_CHANGE:
 
 ;   clr    _r_mom
 ;   out    GIMSK, _r_mom
 
 ;   reti
 ;--------------------------------------------------------------------
 
 WAIT_Idle:
 
 ; для относительно длинных пауз
 ; ждем в состоянии Idle ПРИМЕРНО _r_WAIT / 37.5 секунд
 
 cli
 
 ;   clr    _r_mom
 ;   out    GIMSK, _r_mom
 
 in       _r_mom, MCUCR
 cbr    _r_mom, (1<<SM0) + (1<<SM1)
 sbr    _r_mom, (1<<SE)
 ;ldi    _r_mom, (0<<ISC00) + (0<<ISC01) + (0<<SM0) + (0<<SM1) + (1<<SE) + (0<<PUD)
 out    MCUCR, _r_mom      ; задаем режим sleep-а Idle и устанавливаем флаг его разрешения
 
 ldi    _r_mom, 250
 out    OCR0A, _r_mom      ; значение счетчика таймера для прерывания
 clr    _r_mom
 out    TCNT0, _r_mom      ; сброс счетчика таймера
 ldi    _r_mom, (1<<OCIE0A)
 out    TIMSK0, _r_mom      ; разрешаем прерывание по счетчику таймера
 ldi    _r_mom, (1<<CS02) + (0<<CS01) + (1<<CS00)
 out    TCCR0B, _r_mom      ; запускаем таймер с частотой СК/1024
 
 sei
 
 WAIT_Idle_sleep:
 
 sleep                  ; Idle
 
 clr    _r_mom
 out    TCNT0, _r_mom      ; сброс счетчика таймера
 
 dec    _r_WAIT
 brne    WAIT_Idle_sleep
 
 cli
 
 in       _r_mom, MCUCR
 cbr    _r_mom, (1<<SE)
 out    MCUCR, _r_mom      ; сбрасываем флаг разрешения sleep-а
 
 clr    _r_mom
 out    TIMSK0, _r_mom      ; запрещаем прерывание по счетчику таймера
 out    TCCR0B, _r_mom      ; останавливаем таймер
 out    OCR0A, _r_mom      ; нулевое значение счетчика таймера для прерывания
 out    TCNT0, _r_mom      ; сброс счетчика таймера
 
 ret
 ;;--------------------------------------------------------------------
 ;
 ;EEPROM_write:
 ;
 ;   sbic   EECR, EEPE
 ;   rjmp    EEPROM_write
 ;
 ;   ; Set Programming mode
 ;   ldi    _r_mom, (0<<EEPM1)|(0<<EEPM0)
 ;   out    EECR, _r_mom
 ;
 ;   out    EEARL, _r_EEPROM_address
 ;   out    EEDR, _r_EEPROM_data
 ;   sbi    EECR, EEMPE
 ;   sbi    EECR, EEPE
 ;   ret
 ;;--------------------------------------------------------------------
 ;
 ;EEPROM_read:
 ;
 ;   sbic    EECR, EEPE
 ;   rjmp    EEPROM_read
 ;   out    EEARL, _r_EEPROM_address
 ;   sbi    EECR, EERE
 ;   in      _r_EEPROM_data, EEDR
 ;   ret
 ;;--------------------------------------------------------------------
 
 DECIMAL_value_KOI_8:
 
 ; _r_t1_hb:_r_t1_lb - остаток от числа, _SI_order-ичный разряд которого надо получить
 ; _r_count_measure_time_hb:_r_count_measure_time_lb - число _SI_order в нужной степени
 ; результат - в _r_transmit_data (и уже +$30 к цифре для получения её кода KOI-8)
 
 clr      _r_transmit_data
 
 DECIMAL_value_KOI_8_1:
 
 cp      _r_t1_lb, _r_count_measure_time_lb
 cpc      _r_t1_hb, _r_count_measure_time_hb
 brlo   DECIMAL_value_KOI_8_END
 sub      _r_t1_lb, _r_count_measure_time_lb
 sbc      _r_t1_hb, _r_count_measure_time_hb
 inc      _r_transmit_data
 rjmp   DECIMAL_value_KOI_8_1
 
 DECIMAL_value_KOI_8_END:
 
 ldi      _r_mom, $30            ; свиг для кода KOI-8 цифры
 add      _r_transmit_data, _r_mom
 
 ret
 ;--------------------------------------------------------------------
 
 PAUSE_RS232:
 
 ; _RS232_time - 13 (тактов на операции при передаче) - 5 (вызов rcall) - 2 (ret)
 ; итог / 5 (тактов каждого цикла) = в счетчик
 
 ldi    _r_mom, (_RS232_time - 13 - 5 - 2) / 5;
 
 PAUSE_RS232_Count:
 
 dec      _r_mom
 nop
 nop
 brne   PAUSE_RS232_Count
 
 ret
 ;--------------------------------------------------------------------
 
 DATA_transmit_RS232:
 
 ; содержимое _r_transmit_data - на комп по RS232
 
 cli
 
 ; отправляем посылку RS232
 ; 13 тактов операций после каждого бита + (_RS232_time - 9) тактов паузы
 
 cbi      PORTB, _PIN_PC_OUT   ; старт-бит, до сего момента у нас была 1-ца и долго
 rcall   PAUSE_RS232
 nop
 nop
 nop
 nop
 nop
 nop
 
 ; 8 бит данных и 2 стоп бита = 10 бит
 ; для посылки их в одном цикле инвертируем байт даннных
 ; и будем посылать инвертированные биты - 2 стоп бита получатся
 ; как инвертированные нули при логическом сдвиге вправо :)
 
 com      _r_transmit_data
 ldi      _r_WAIT, 10
 
 DATA_transmit_RS232_DATA_BITS:
 
 sbrc   _r_transmit_data, 0
 cbi      PORTB, _PIN_PC_OUT
 sbrs   _r_transmit_data, 0
 sbi      PORTB, _PIN_PC_OUT
 
 rcall   PAUSE_RS232
 nop
 nop
 nop
 nop
 
 lsr      _r_transmit_data
 dec      _r_WAIT
 brne   DATA_transmit_RS232_DATA_BITS
 
 ; по хорошему, надо было запомнить флаг прерывания в начале процедуры
 ; и вернуть его такой же в конце. Но мы не будем возвращать
 ; - по умолчанию живем без прерываний, если надо - выставим когда надо
 ;sei
 
 ret
 ;--------------------------------------------------------------------
 
 VALUE_transmit_RS232:
 
 ;_r_t1_hb:_r_t1_lb - на комп по RS232 в десятичной системе с запятой
 ;_r_count_measure_time_hb:_r_count_measure_time_lb - _SI_order
 ;_r_transmit_data - который потом шлем на комп по RS232
 
 ldi      _r_count_measure_time_lb, low(_SI_order_4)
 ldi      _r_count_measure_time_hb, high(_SI_order_4)
 rcall    DECIMAL_value_KOI_8
 rcall    DATA_transmit_RS232
 
 ldi      _r_count_measure_time_lb, low(_SI_order_3)
 ldi      _r_count_measure_time_hb, high(_SI_order_3)
 rcall    DECIMAL_value_KOI_8
 rcall    DATA_transmit_RS232
 
 ldi      _r_count_measure_time_lb, low(_SI_order_2)
 ldi      _r_count_measure_time_hb, high(_SI_order_2)
 rcall    DECIMAL_value_KOI_8
 rcall    DATA_transmit_RS232
 
 ; запятая
 ldi      _r_transmit_data, KOI_8_comma
 rcall    DATA_transmit_RS232
 
 ldi      _r_count_measure_time_lb, low(_SI_order_1)
 ldi      _r_count_measure_time_hb, high(_SI_order_1)
 rcall    DECIMAL_value_KOI_8
 rcall    DATA_transmit_RS232
 
 ldi      _r_count_measure_time_lb, low(_SI_order_0)
 ldi      _r_count_measure_time_hb, high(_SI_order_0)
 rcall    DECIMAL_value_KOI_8
 rcall    DATA_transmit_RS232
 
 ret
 ;--------------------------------------------------------------------
 
 MEASURE_transmit_RS232:
 
 ; вынес в процедуру ИСКЛЮЧИТЕЛЬНО из-за ограничения количества строк перехода!
 
 ;_r_t1_hb:_r_t1_lb - на комп по RS232 в десятичной системе с запятой
 ;_r_count_measure_time_hb:_r_count_measure_time_lb - _SI_order
 ;_r_transmit_data - который потом шлем на комп по RS232
 
 ; сначала рассчитаем и приготовим все нужные рагистры для передачи
 ; а потом уже передадим - при передаче они корежатся :)
 
 ; расчет и запись ti_last как разница ti_lastт - ti
 
 cp      _r_t1_last_lb, _r_t1_lb
 cpc      _r_t1_last_hb, _r_t1_hb
 brlo   _clr_r_t1_last
 sub      _r_t1_last_lb, _r_t1_lb
 sbc      _r_t1_last_hb, _r_t1_hb
 rjmp   _calc_r_t1_last_end
 _clr_r_t1_last:
 clr      _r_t1_last_lb
 clr      _r_t1_last_hb
 _calc_r_t1_last_end:
 
 cp      _r_t2_last_lb, _r_t2_lb
 cpc      _r_t2_last_hb, _r_t2_hb
 brlo   _clr_r_t2_last
 sub      _r_t2_last_lb, _r_t2_lb
 sbc      _r_t2_last_hb, _r_t2_hb
 rjmp   _calc_r_t2_last_end
 _clr_r_t2_last:
 clr      _r_t2_last_lb
 clr      _r_t2_last_hb
 _calc_r_t2_last_end:
 
 ; тут в _r_t1_hb:_r_t1_lb уже нужное число для передачи - ничего не делаем
 
 rcall    VALUE_transmit_RS232
 ldi      _r_transmit_data, KOI_8_semicolon
 rcall    DATA_transmit_RS232               ; символ ";"
 
 mov      _r_t1_lb, _r_t1_last_lb
 mov      _r_t1_hb, _r_t1_last_hb
 rcall    VALUE_transmit_RS232
 ldi      _r_transmit_data, KOI_8_semicolon
 rcall    DATA_transmit_RS232               ; символ ";"
 
 mov      _r_t1_lb, _r_t2_lb
 mov      _r_t1_hb, _r_t2_hb
 rcall    VALUE_transmit_RS232
 ldi      _r_transmit_data, KOI_8_semicolon
 rcall    DATA_transmit_RS232               ; символ ";"
 
 mov      _r_t1_lb, _r_t2_last_lb
 mov      _r_t1_hb, _r_t2_last_hb
 rcall    VALUE_transmit_RS232
 
 ; счетчик измерений считает от 0 вверх
 ; если он четный - в конце передаем ";", иначе переход на новую строку
 
 sbrc   _r_count_measure_sets, 0
 rjmp   MEASURE_transmit_RS232_SEND_TO_PC_new_line
 
 ldi      _r_transmit_data, KOI_8_semicolon
 rcall    DATA_transmit_RS232               ; символ ";"
 
 rjmp   MEASURE_transmit_RS232_END
 
 MEASURE_transmit_RS232_SEND_TO_PC_new_line:
 
 ldi      _r_transmit_data, KOI_8_ps
 rcall    DATA_transmit_RS232
 ldi      _r_transmit_data, KOI_8_vk
 rcall    DATA_transmit_RS232               ; переход на новую строку
 
 MEASURE_transmit_RS232_END:
 
 ret
 ;--------------------------------------------------------------------
 
 INITIALIZE_MEASURE:
 
 ; вынес в процедуру ИСКЛЮЧИТЕЛЬНО из-за ограничения количества строк перехода!
 
 clr    _r_count_measure_time_lb
 clr    _r_count_measure_time_hb
 
 ser    _r_t1_lb
 ser    _r_t1_hb
 ser    _r_t2_lb
 ser    _r_t2_hb
 
 ; используем тут _r_transmit_data для начального состояния входов
 in      _r_transmit_data, PINB
 
 in       _r_mom, MCUCR
 cbr    _r_mom, (1<<SM0) + (1<<SM1)
 sbr    _r_mom, (1<<SE)
 out    MCUCR, _r_mom      ; задаем режим sleep-а Idle и устанавливаем флаг его разрешения
 
 ldi    _r_mom, _one_measure_time - 1 - 8 - 4 - 8
 out    OCR0A, _r_mom      ; значение счетчика таймера для прерывания
 ; 1 - на установку флага прерывания
 ; 8 - на переход на адрес вектора прерывания
 ; 4 - на reti с адреса вектора прерывания
 ; 8 = 2 на сброс счетчика таймера + 6 на проверку условия цикла
 clr    _r_mom
 out    TCNT0, _r_mom      ; сброс счетчика таймера
 ldi    _r_mom, (1<<OCIE0A)
 out    TIMSK0, _r_mom      ; разрешаем прерывание по счетчику таймера
 ldi    _r_mom, (0<<CS02) + (0<<CS01) + (1<<CS00)
 out    TCCR0B, _r_mom      ; запускаем таймер с частотой СК
 
 sei
 
 ret
 ;--------------------------------------------------------------------
 
 MAIN:
 
 cbi      PORTB, _PIN_RELE_OUT1
 cbi      PORTB, _PIN_RELE_OUT2
 sbi      PORTB, _PIN_PC_OUT      ; инициализируем передачу на комп
 
 ;   ldi    _r_mom, (1<<PCIE)
 ;   out    GIMSK, _r_mom         ; разрешаем прерыванияпо изменению состояния выводов
 
 ;   in       _r_mom, MCUCR
 ;   cbr    _r_mom, (1<<SM0)
 ;   sbr    _r_mom, (1<<SM1) + (1<<SE)
 ;   ;ldi    _r_mom, (0<<ISC00) + (0<<ISC01) + (0<<SM0) + (0<<SM1) + (1<<SE) + (0<<PUD)
 ;   out    MCUCR, _r_mom      ; задаем режим sleep-а Power-down и устанавливаем флаг его разрешения
 
 ;   sei
 
 ;   sleep                  ; Power-down
 
 ; тут проснемся от прерывания PIN_CHANGE
 
 ldi    _r_WAIT, 20 ; 37.5 Гц
 rcall    WAIT_Idle         ; ждать 1s
 
 ; инициализировать контакты реле
 
 sbi      PORTB, _PIN_RELE_OUT2
 
 ldi    _r_WAIT, 6 ; 37.5 Гц
 rcall    WAIT_Idle         ; ждать 250ms
 
 cbi      PORTB, _PIN_RELE_OUT2
 
 ldi    _r_WAIT, 6 ; 37.5 Гц
 rcall    WAIT_Idle         ; ждать 250ms
 
 ; провести серию измерений, записывая результаты каждого в EEPROM
 
 clr    _r_count_measure_sets
 
 SET_OF_MEASURES:
 
 rcall    INITIALIZE_MEASURE
 
 ; команда на переключение - инвертируем _PIN_RELE_OUT1
 ldi      _r_WAIT, (1<<_PIN_RELE_OUT1)
 in      _r_mom, PORTB
 eor      _r_mom, _r_WAIT
 out      PORTB, _r_mom
 
 ; измеряем t1 и t2
 
 MEASURE:                  ; опрос пинов строго раз в 10us = 96 тактов
 ; таких опросов строго до достижения _max_measure_time
 clr    _r_mom
 out    TCNT0, _r_mom      ; сброс счетчика таймера
 
 ; тут у нас есть на все наши операции максимум 96 - 1 - 8 - 4 - 8 = 75 тактов!
 
 ;   ldi      _r_mom, 25
 ;a3:   dec      _r_mom
 ;   brne   a3
 ;   ; 75 тактов
 ;   ;nop
 ;   ;nop
 ;   nop
 
 ldi      _r_mom, 1
 clr    _r_WAIT
 add      _r_count_measure_time_lb, _r_mom
 adc      _r_count_measure_time_hb, _r_WAIT   ; инкремент счетчика
 
 ; манипуляции с _r_mom, после которых в битах _PIN_RELE_IN1 и _PIN_RELE_IN2
 ; будут 1-цы только если текущие значения не равны начальным из _r_transmit_data
 in      _r_mom, PINB
 eor      _r_mom, _r_transmit_data
 
 ; старшие байты _r_t1_hb и _r_t2_hb изначально забиты 1-цами
 ; а после занесения в них значений измерения - гарантированно меньше,
 ; т.к. максимальное значение у нас будет 3000 а возможное - 65536
 
 cpi      _r_t1_hb, 255
 brne   MEASURE_t1_END         ; пропускаем если _r_t1_hb <> 255 - уже заполнили
 
 sbrs   _r_mom, _PIN_RELE_IN1
 rjmp   MEASURE_t1_END         ; пропускаем если состояние не изменилось
 
 mov      _r_t1_lb, _r_count_measure_time_lb
 mov      _r_t1_hb, _r_count_measure_time_hb
 
 MEASURE_t1_END:
 
 cpi      _r_t2_hb, 255
 brne   MEASURE_t2_END         ; пропускаем если _r_t2_hb <> 255 - уже заполнили
 
 sbrs   _r_mom, _PIN_RELE_IN2
 rjmp   MEASURE_t2_END         ; пропускаем если состояние не изменилось
 
 mov      _r_t2_lb, _r_count_measure_time_lb
 mov      _r_t2_hb, _r_count_measure_time_hb
 
 MEASURE_t2_END:
 
 ; каждый цикл записываем тек. время если состояние вывода РАВНО исходному
 ; - так отследим время окончания дребезга
 
 sbrc   _r_mom, _PIN_RELE_IN1
 rjmp   MEASURE_t1_last_END      ; пропускаем если состояние изменилось
 
 mov      _r_t1_last_lb, _r_count_measure_time_lb
 mov      _r_t1_last_hb, _r_count_measure_time_hb
 
 MEASURE_t1_last_END:
 
 sbrc   _r_mom, _PIN_RELE_IN2
 rjmp   MEASURE_t2_last_END      ; пропускаем если состояние изменилось
 
 mov      _r_t2_last_lb, _r_count_measure_time_lb
 mov      _r_t2_last_hb, _r_count_measure_time_hb
 
 MEASURE_t2_last_END:
 
 ; заняли максимум 40 тактов
 
 sleep
 
 ldi      _r_mom,  low(_max_measure_time)
 ldi      _r_WAIT, high(_max_measure_time)
 cp      _r_count_measure_time_lb, _r_mom
 cpc      _r_count_measure_time_hb, _r_WAIT
 brlo   MEASURE
 
 ; прошли _max_measure_time - сделали очередное измерение
 cli
 
 in       _r_mom, MCUCR
 cbr    _r_mom, (1<<SE)
 out    MCUCR, _r_mom      ; сбрасываем флаг разрешения sleep-а
 
 clr    _r_mom
 out    TCCR0B, _r_mom      ; останавливаем таймер
 out    TCNT0, _r_mom      ; сброс счетчика таймера
 
 ldi    _r_WAIT, 6 ; 37.5 Гц
 rcall    WAIT_Idle         ; ждать 250ms
 
 ; команда на исходное положение - инвертируем _PIN_RELE_OUT2
 ldi      _r_WAIT, (1<<_PIN_RELE_OUT2)
 in      _r_mom, PORTB
 eor      _r_mom, _r_WAIT
 out      PORTB, _r_mom
 
 ; передать результаты на комп
 rcall   MEASURE_transmit_RS232
 
 ldi    _r_WAIT, 6 ; 37.5 Гц
 rcall    WAIT_Idle         ; ждать 250ms
 
 ; если ещё не все измерения сделаны (а одно измерение - это сначала туда а потом обратно)
 ; то сделаем ещё измерение
 inc      _r_count_measure_sets
 cpi      _r_count_measure_sets, 2*_sets_of_measures
 brlo   SET_OF_MEASURES
 
 ; провели серию измерений и передали результаты на комп -
 ; готовы к новой серии измерений (на старт и PowerDown)
 
 ;rjmp    MAIN
 
 ; нет - тут падаем в Power-down без права прерывания и ждем RESET :)))
 
 SLEEP_Power_down:
 
 cli
 
 in       _r_mom, MCUCR
 cbr    _r_mom, (1<<SM0)
 sbr    _r_mom, (1<<SM1) + (1<<SE)
 ;ldi    _r_mom, (0<<ISC00) + (0<<ISC01) + (0<<SM0) + (0<<SM1) + (1<<SE) + (0<<PUD)
 out    MCUCR, _r_mom      ; задаем режим sleep-а Power-down и устанавливаем флаг его разрешения
 
 sleep                  ; Power-down
 
 rjmp    SLEEP_Power_down
 
 |