Обсуждаем контроллеры компании Atmel.
Ответить

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вт сен 12, 2017 08:37:46

У АВРок внешнего разрешения счета нет... разве что использовать программный дубляж для управления по ICP/захвату в таймере С/Т1...
:roll:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вт сен 12, 2017 09:23:25

Если хорошая кнопка, то для подавления дребезга может быть достаточно конденсатора, я с таким уже встречался.

А режим захвата в AVR есть по фронту и спаду одновременно?

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вт сен 12, 2017 09:53:20

• Bit 6 – ICES1: Input Capture Edge Select
This bit selects which edge on the Input Capture pin (ICP1) that is used to trigger a capture
event. When the ICES1 bit is written to zero, a falling (negative) edge is used as trigger, and
when the ICES1 bit is written to one, a rising (positive) edge will trigger the capture.
When a capture is triggered according to the ICES1 setting, the counter value is copied into the
Input Capture Register (ICR1). The event will also set the Input Capture Flag (ICF1), and this
can be used to cause an Input Capture Interrupt, if this interrupt is enabled.
DS на ATtiny2313 утверждает, что нет.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вт сен 12, 2017 09:57:54

Мне тоже помнится что нет. Хотя может на каких-то более продвинутых есть.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вт сен 12, 2017 11:31:13

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

Да, при коротком нажатии ловим сначала нажатие, фильтруем дребезг таймером, ловим отпускание, ещё раз фильтруем. А с длинным что делать? Надо чтобы длинное без отпускания ловил.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вт сен 12, 2017 11:58:45

radio-fan писал(а):Надо чтобы длинное без отпускания ловил.
После отсечки дребезга запускается таймер и останавливается при отпускании кнопки. При переполнении таймера, считается что кнопка достаточно долго нажата.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Ср сен 13, 2017 06:49:01

Делаем замер "самого длинного" делим на N частей (желателно кратно 2 дабы с математикой не заморачиваться) и делаем минимального "условного енота" с табличкой определений хотелок в УЕ (от 1 УЕ до максимум/УЕ +2УЕ). Это часть автокалибровки измерителя.
Измеренный интервал нарезаем интервалами "условного енота" с неким округлением и грузим количество тех интервалов в "счетчик УЕ, прошедших на вход".
Затем содержимое счетчика используем как указатель обработчика.
:wink:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Ср сен 13, 2017 17:40:21

Вы че тут понаписали про опрос кнопок? ТС-у требуется используя внешнее прерывание отловить короткие и длинные нажатия? Не вопрос. Пусть сработало внешнее прерывание. Как только оно сработало, отключаем внешнее прерывание и пин МК становится обычным входом. Отслеживаем его. Прошли дребезг? Засчитываем как нажатие, запускаем программный таймер длинного нажатия. Только нужно определиться, какое время считаем длинным нажатием? Секунда, пусть будет секунда. Три секунды? Пусть так. Отпустили кнопку раньше положенного? Считаем коротким нажатием. Снова настраиваем вход как внешнее прерывание. Сидим ждем следующее нажатие. Прошло заданное время? Значит длинное нажатие. А вот чтобы считать времянки, используем программные таймеры. Аппаратный таймер один. Программных можно сделать столько, насколько хватит ресурсов МК. Хоть десятки.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Ср сен 13, 2017 20:41:00

Я описал алгоритм замера и сортировки интервалов.
А кнопка то или чего иного - никакушной разницы, если базовым измерителем таймер с внешним разрешением счета выбран.
:wink:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сб сен 16, 2017 05:34:08

... Аппаратный таймер один...
Вполне достаточно. Таймер(ы) для того и введён(ы), чтобы считать "времянки". Программе остается только анализ дребезга, короткого или длинного нажатия.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сб сен 16, 2017 05:41:38

Речь идет о том, что аппаратных таймеров мало. И они нужны для других нужд. Поэтому, отводится один аппаратный таймер для программных таймеров, которых можно наделать сколько угодно, главное, чтобы хватило ресурсов МК.
Это распространенная проблема начинающих. Аппаратных таймеров мало, как отмерять времянки? Вот и ответ сразу - решение - программные таймеры.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сб сен 16, 2017 08:06:26

Все зависит от терминологии...
Вобщем-то все проблемы снимает правильно скомпонованный генератор системной сетки частот.
Основа - 8/16 разрядный таймер с автоперезагрузкой (предпочтение 16-разрядному с вероятным предделителем), тактируемый от частоты системного генератора.
А при помощи чего дальнейшая обработка этого системного "тик" выполняться будет - зависит от творчества авторов.
Возможны добавочные счетчики с передаточными служебными флагами или чего другое...
Установка нескольких одновременно протекающих асинхронных процессов дело достаточно сложное из-за компоновки приоритетов прерываний. Да и не всегда дает желаемый результат по оперативному быстродействию.
:beer:

Сб сен 23, 2017 13:44:06

И снова здравствуйте. Помогите пожалуйста.
Пытаюсь написать прогу переключения световых эффектов и их инверсии с помощью внешнего прерывания.
Проблема в том, что хреново отслеживается длинное нажатие (происходит незапланированная инверсия и\или увеличение счётчика нажатий (младшая тетрада Flag)). Надо чтобы при коротком мы инкрементировали счётчик, а при зажатии кнопки происходила инверсия, при последующем отпускании ничего не происходило и дальше снова ловим нажатие.
Код прилагаю ниже:
Код:
.include "c:\Program Files\Atmel\AVR Tools\AvrAssembler2\Appnotes\m8def.inc"
                   ;ATmega8 программируем
                   ;тактовая частота 8 МГц
.def Temp=R16      ;рабочая перемнная
.def Flag=R17      ;3-0 бит счётчик нажатий, 4 бит инверсии (1 инверсия), 5 бит нажатия отпускания (0 нажатие, 1 отпускание), 6 бит длинное короткое нажатие(0 короткое, 1 длинное)
.def Count=R18     ;счётчик эффектов
.def TimCount=R19  ;счётчик переполнений таймер 0
.def Temp1=R20
.def Temp2=R21
.def Temp3=R22

.cseg
.org 0

rjmp RESET         ;переход на обработку сброса
rjmp EXT_INT0      ;переход на обработку запроса IRQ0
reti;rjmp EXT_INT1      ;переход на обработку запроса IRQ1
reti;rjmp TIM2_COMP     ;переход на обработку сравнения Timer2
reti;rjmp TIM2_OVF      ;переход на обработку при переполнении Timer2
reti;rjmp TIM1_CAPT     ;переход на обработку при захвате фронта Timer1
rjmp TIM1_COMPA    ;переход на обработку при срабатывании компаратора A Timer1
reti;rjmp TIM1_COMPB    ;переход на обработку при срабатывании компаратора B Timer1
reti;rjmp TIM1_OVF      ;переход на обработку при переполнении Timer1
rjmp TIM0_OVF      ;переход на обработку при переполнении Timer0
reti;rjmp SPI_STC       ;переход на обработку при завершении передачи SPI
reti;rjmp USART_RXC     ;переход на обработку при завершении приёма УСАППО
reti;rjmp USART_UDRE    ;переход на обработку при освобождении регистра
reti;rjmp USART_TXC     ;переход на обработку при завершении передачи
reti;rjmp ACDC          ;переход на обработку при завершении приобразования АЦП
reti;rjmp EE_RDY        ;переход на обработку при готовности EEROM
reti;rjmp ANA_COMP      ;переход на обработку при срабатывании аналогового компаратора
reti;rjmp TWSI          ;двухпроводный последовательный интерфейс
reti;rjmp SPM_RDY       ;переход на обработку прерывания при готовности записи в память программ

;************************************************************************************************
;МАССИВ
;************************************************************************************************

ARRAY0:
.db 0b01001001, 0b10010010, 0b00100100, 0          ;Максимум 16 эффектов

ARRAY1:
.db 0b00000001, 0b00000010, 0b00000100, 0b00001000 ;1 светодиод светится 1/8 с (125000мкс)
.db 0b00010000, 0b00100000, 0b01000000, 0b10000000 ;частота без предделиеля 8Мгц => 1 такт 0,125мкс
.db 0b01000000, 0b00100000, 0b00010000, 0b00001000 ;всего 65535 => 1 такт должен длиться 2мкс =>
.db 0b00000100, 0b00000010, 0, 0                   ;частота предделителя 8*10^6/32 гц (011) (1такт 4мкс)

ARRAY2:
.db 0b00011000, 0b00100100, 0b01000010, 0b10000001 ;125000/4=31250 (7A12)
.db 0b01000010, 0b00100100, 0, 0                   ;

ARRAY3:
.db 0b00000001, 0b00000010, 0b00000100, 0b00001000 ;
.db 0b00010000, 0b00100000, 0b01000000, 0b10000000 ;
.db 0, 0                                           ;

ARRAY4:
.db 0b10000000, 0b01000000, 0b00100000, 0b00010000 ;
.db 0b00001000, 0b00000100, 0b00000010, 0b00000001 ;
.db 0, 0                                           ;

ARRAY5:
.db 0b00011000, 0b00100100, 0b01000010, 0b10000001 ;
.db 0, 0                                           ;

ARRAY6:
.db 0b00000001, 0b00000011, 0b00000111, 0b00001111 ;
.db 0b00011111, 0b00111111, 0b01111111, 0b11111111 ;
.db 0b11111110, 0b11111100, 0b11111000, 0b11110000 ;
.db 0b11100000, 0b11000000, 0b10000000, 0          ;

ARRAY7:
.db 0b10000000, 0b11000000, 0b11100000, 0b11110000 ;
.db 0b11111000, 0b11111100, 0b11111110, 0b11111111 ;
.db 0b01111111, 0b00111111, 0b00011111, 0b00001111 ;
.db 0b00000111, 0b00000011, 0b00000001, 0          ;

ARRAY8:
.db 0b00011000, 0b00111100, 0b01111110, 0b11111111 ;
.db 0b01111110, 0b00111100, 0, 0                   ;

ARRAY9:
.db 0b00000001, 0b00000011, 0b00000111, 0b00001111 ;
.db 0b00011111, 0b00111111, 0b01111111, 0b11111111 ;
.db 0b01111111, 0b00111111, 0b00011111, 0b00001111 ;
.db 0b00000111, 0b00000011, 0, 0                   ;

ARRAY10:
.db 0b10000000, 0b11000000, 0b11100000, 0b11110000 ;
.db 0b11111000, 0b11111100, 0b11111110, 0b11111111 ;
.db 0b11111110, 0b11111100, 0b11111000, 0b11110000 ;
.db 0b11100000, 0b11000000, 0, 0                   ;

;################################################################################################
;ИНИЦИАЛИЗАЦИЯ
;################################################################################################

Reset: ldi Temp, high(RAMEND)      ;Инциализация стека
       out SPH, Temp               ;
      ldi Temp, low(RAMEND)       ;
      out SPL, Temp               ;

       ldi Temp, 0b11111111        ;Инициализация портов
      out DDRB, Temp              ;
      ldi Temp, 0b00000100        ;Подтягивающий резистор на INT0
      out PORTD, Temp             ;

      clr Flag                    ;
      clr Count                   ;
      clr TimCount                ;

       ldi Temp, 0b00000010        ;инициализируем INT0 по спаду
      out MCUCR, Temp             ;

      ldi Temp, 0b01000000        ;включаем прерывание int0
      out GICR, Temp              ;
            
      ldi Temp, 0b00010001        ;настройка прерываний(разрешаем прерывание компаратора 1-ого таймера)
      out TIMSK, Temp             ;вывод в TIMSK

       ldi Temp, high(31250)       ;Задаём число в компаратор
      out OCR1AH, Temp            ;
      ldi Temp, low(31250)        ;
      out OCR1AL, Temp            ;

       ldi Temp, 0b00000011        ;настройка предделителя
      out TCCR1B, Temp            ;вывод в TCCR1B

       clr Temp                    ;Обнуляем таймер
       out TCNT1H, Temp            ;
       out TCNT1L, Temp            ;


      sei                         ;

;#################################################################################################
;ООСНОВНОЙ ЦИКЛ
;#################################################################################################

Do:         sbrs Flag, 6           ;
         rjmp Do                ;
         ldi Temp3, 0x12        ;загружаем число 124F80 задержка 0,75с
         ldi Temp2, 0x48        ;6000000/5=1200000
         ldi Temp1, 0x80        ;750000/0,125=6000000
Delay:      subi Temp1, 1          ;задержка
         sbci Temp2, 0          ;
         sbci Temp3, 0          ;
         brcc Delay             ;
         cli                    ;запрещаем прерывания
         cbr Flag, 0b01000000   ;устанавливаем короткое нажатие
         sbrs Flag, 4           ;инверсия эффектов
         rjmp Invers            ;
         cbr Flag, 0b00010000   ;
         rjmp End               ;
Invers:     sbr Flag, 0b00010000   ;
End:        ldi Temp, 0b00000010   ;инициализируем INT0 по спаду
            out MCUCR, Temp        ;
         ldi Temp, 0b00000011   ;настройка предделителя
            out TCCR1B, Temp       ;вывод в TCCR1B
         sei                    ;разрешаем прерывния
         rjmp Do                ;

;#################################################################################################
;ПРЕРЫВАНИЕ КОМПАРАТОРА
;#################################################################################################

TIM1_COMPA: in Temp, SREG          ;сохраняем флаги в стек
         push Temp              ;
            clr Temp               ;Обнуляем таймер
         out TCNT1H, Temp       ;
         out TCNT1L, Temp       ;         

Test0:      mov Temp, Flag         ;Проверка кнопки
            andi Temp, 0b00001111  ;
            cpi Temp, 0            ;
         brne Test1             ;
            ldi ZH, High(ARRAY0*2) ;
         ldi ZL, Low(ARRAY0*2)  ;
         rjmp Readarray         ;

Test1:      cpi Temp, 1            ;
         brne Test2             ;
            ldi ZH, High(ARRAY1*2) ;
         ldi ZL, Low(ARRAY1*2)  ;
         rjmp Readarray         ;

Test2:      cpi Temp, 2            ;(10)
         brne Test3             ;
            ldi ZH, High(ARRAY2*2) ;
         ldi ZL, Low(ARRAY2*2)  ;
         rjmp Readarray         ;

Test3:      cpi Temp, 3            ;(11)
         brne Test4             ;
            ldi ZH, High(ARRAY3*2) ;
         ldi ZL, Low(ARRAY3*2)  ;
         rjmp Readarray         ;

Test4:      cpi Temp, 4            ;(100)
         brne Test5             ;
            ldi ZH, High(ARRAY4*2) ;
         ldi ZL, Low(ARRAY4*2)  ;
         rjmp Readarray         ;

Test5:      cpi Temp, 5            ;(101)
         brne Test6             ;
            ldi ZH, High(ARRAY5*2) ;
         ldi ZL, Low(ARRAY5*2)  ;
         rjmp Readarray         ;

Test6:      cpi Temp, 6            ;(110)
         brne Test7             ;
            ldi ZH, High(ARRAY6*2) ;
         ldi ZL, Low(ARRAY6*2)  ;
         rjmp Readarray         ;

Test7:      cpi Temp, 7            ;(111)
         brne Test8             ;
            ldi ZH, High(ARRAY7*2) ;
         ldi ZL, Low(ARRAY7*2)  ;
         rjmp Readarray         ;

Test8:      cpi Temp, 8            ;(1000)
         brne Test9             ;
            ldi ZH, High(ARRAY8*2) ;
         ldi ZL, Low(ARRAY8*2)  ;
         rjmp Readarray         ;

Test9:      cpi Temp, 9            ;(1001)
         brne Test10            ;
            ldi ZH, High(ARRAY9*2) ;
         ldi ZL, Low(ARRAY9*2)  ;
         rjmp Readarray         ;

Test10:     cpi Temp, 10            ;(1010,A)
            ldi ZH, High(ARRAY10*2) ;
         ldi ZL, Low(ARRAY10*2)  ;

Readarray:  ldi Temp, 0            ;загружаем элемент массива
            add ZL, Count          ;
         adc ZH, Temp           ;
         lpm                    ;
         mov Temp, R0           ;
         cpi Temp, 0            ;
         breq Go                ;
         inc Count              ;
         rjmp Output            ;

Go:         clr Count              ;
            rjmp Test0             ;

Output:     sbrc Flag, 4           ;проверка на бегущую тень
            com Temp               ;
         out PortB, Temp        ;вывод в порты
         pop Temp               ;
         out SREG, Temp         ;
         reti                   ;

;#############################################################################################
;ПРЕРЫВАНИЕ ПО КНОПКЕ
;#############################################################################################

EXT_INT0:   in Temp, SREG          ;сохраняем флаги в стек
         push Temp              ;
            clr Temp               ;
            out GICR, Temp         ;запрещаем прерывание по кнопке
           out TCCR1B, Temp       ;останавливаем компаратор
         out TCCR0, Temp        ;останавливаем таймер 0
         out TCNT0, Temp        ;очищаем регистр 0 таймера
         cbr Flag, 0b01000000   ;длинного нажатия нет

            sbrs Flag, 5           ;если 0 то было нажатие, если 1 то отпускание
         rjmp PushCycl          ;
         clr Count              ;
         ldi Temp, 0b00000011   ;настройка предделителя
           out TCCR1B, Temp       ;вывод в TCCR1B
         mov Temp, Flag         ;сравниваем счётчик нажатий
         andi Temp, 0b00001111  ;
         cpi Temp, 11           ;
         brne GO1               ;
         andi Flag, 0b11110000  ;
         rjmp GO2               ;
GO1:        inc Flag               ;
GO2:        cbr Flag, 0b00100000   ;
            ldi TimCount, 195      ;пауза 0,05 с
            ldi Temp, 0b00000001   ;запускаем таймер 0
         out TCCR0, Temp        ;частота 1/8
         clr count              ;
         pop Temp               ;извлекаем флаги из стека
         out SREG, Temp         ;
         reti

PushCycl:   sbr Flag, 0b00100000   ;
            ldi TimCount, 146      ;пауза 0,25 с
            ldi Temp, 0b00000011   ;частота 1/32
         out TCCR0, Temp        ;
         pop Temp               ;извлекаем флаги из стека
         out SREG, Temp         ;
         sei                    ;
         rjmp Do                ;конец прерывания

;#############################################################################################
;ПРЕРЫВАНИЕ ПО ПЕРЕПОЛНЕНИЮ ТАЙМЕРА 0
;#############################################################################################

TIM0_OVF:   in Temp, SREG          ;сохраняем флаги в стек
         push Temp              ;
            dec TimCount           ;
            breq Timer             ;
         pop Temp               ;извлекаем флаги из стека
         out SREG, Temp         ;
         reti                   ;

Timer:      clr Temp               ;останавливаем таймер 0
         out TCCR0, Temp        ;
         sbrs Flag, 5           ;
            rjmp GO3               ;
         ldi Temp, 0b00000011   ;инициализируем INT0 по фронту
           out MCUCR, Temp        ;
         sbr Flag, 0b01000000   ;
         ldi Temp, 0b01000000   ;включаем прерывание int0
           out GICR, Temp         ;
         ldi Temp, 0b00000011   ;настройка предделителя
           out TCCR1B, Temp       ;вывод в TCCR1B
         pop Temp               ;извлекаем флаги из стека
         out SREG, Temp         ;
         reti

GO3:        ldi Temp, 0b00000010   ;инициализируем INT0 по спаду
            out MCUCR, Temp        ;
         ldi Temp, 0b01000000   ;включаем прерывание int0
           out GICR, Temp         ;
         pop Temp               ;извлекаем флаги из стека
         out SREG, Temp         ;
         sei                    ;
         rjmp Do                ;конец прерывания

P.S.Ещё один баг нашёл. Вообще не понимаю почему так происходит. Если перебирать эффекты, то он меняет местами 3,4 массивы и 9,10 массивы. Как это исправить?

Re:

Сб сен 23, 2017 15:28:51

Ассемблер ничем не отличается от других языков в плане абстракций. Проектирование сверху вниз. Забудьте о регистрах, байтах и тактах. Устройство, блоки устройства, блоки блоков. Алгоритмы. Берете бумажку и составляете ТЗ. Рисуйте алгоритмы. Когда это у вас будет, тогда будут и программы. По сути, программы будут писаться по нарисованным алгоритмам. Пишите программы на ассемблере так, как будто вы пишете на языке высокого уровня.
Ссылки на цикл статей я вам давал. Читайте, там все разжевано и даже картинки есть. Вам осталось написать программу по этим картинкам.

Re:

Пн сен 25, 2017 05:51:31

[code]
;#############################################################################################
;ПРЕРЫВАНИЕ ПО КНОПКЕ
;#############################################################################################

EXT_INT0: in Temp, SREG ;сохраняем флаги в стек
push Temp ;
clr Temp ;
out GICR, Temp ;запрещаем прерывание по кнопке
out TCCR1B, Temp ;останавливаем компаратор
out TCCR0, Temp ;останавливаем таймер 0
out TCNT0, Temp ;очищаем регистр 0 таймера
cbr Flag, 0b01000000 ;длинного нажатия нет

sbrs Flag, 5 ;если 0 то было нажатие, если 1 то отпускание
rjmp PushCycl ;
clr Count ;
ldi Temp, 0b00000011 ;настройка предделителя
out TCCR1B, Temp ;вывод в TCCR1B
mov Temp, Flag ;сравниваем счётчик нажатий
andi Temp, 0b00001111 ;
cpi Temp, 11 ;
brne GO1 ;
andi Flag, 0b11110000 ;
rjmp GO2 ;
GO1: inc Flag ;
GO2: cbr Flag, 0b00100000 ;
ldi TimCount, 195 ;пауза 0,05 с
ldi Temp, 0b00000001 ;запускаем таймер 0
out TCCR0, Temp ;частота 1/8
clr count ;
pop Temp ;извлекаем флаги из стека
out SREG, Temp ;
reti

PushCycl: sbr Flag, 0b00100000 ;
ldi TimCount, 146 ;пауза 0,25 с
ldi Temp, 0b00000011 ;частота 1/32
out TCCR0, Temp ;
pop Temp ;извлекаем флаги из стека
out SREG, Temp ;
sei ;
rjmp Do ;конец прерывания
Здесь будет срыв стека, т.к. выход из прерывания по RJMP

Пн сен 25, 2017 09:27:42

Если прерывание int0 произойдёт во время отсчёта задержки, то командой reti мы вернёмся обратно в задержку, а после прерывания она нам уже будет не нужна.
Только вот что, а если из прерывания выходить не через reti, то в стеке будет оставаться адрес?

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн сен 25, 2017 09:32:10

radio-fan писал(а): если из прерывания выходить не через reti, то в стеке будет оставаться адрес?
ясен пень, куда ж ему деваться-то?
не смотря на то, что ассемблер позволяет делать, что угодно, все-таки хорошей практикой следует признать выход из прерывания туда, откуда был вход. собственно, как и из любой другой подпрограммы.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн сен 25, 2017 10:38:10

RETI всего лишь сбрасывает блокировку прерываний
(восстанавливает флаг "глобального разрешения" I в регистре статуса SREG после того, как он будет АВТМАТИЧЕСКИ СБРОШЕН при входе в прерывание)
По обработке стека и RET и RETI
ОДНО И ТО ЖЕ.
8)

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн сен 25, 2017 10:40:26

BOB51 писал(а):По обработке стека и RET и RETI
ОДНО И ТО ЖЕ
только речь про
akl писал(а):rjmp Do ;конец прерывания

Re:

Пн сен 25, 2017 10:45:53

...если из прерывания выходить не через reti, то в стеке будет оставаться адрес?
Да, но указатель стека SP будет смещен и следующие прерывания с таким же условием будут его смещать и смещать. В итоге зависон обеспечен.
Ответить