Внешнее прерывание 2313

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Встал на лапы
Аватара пользователя
Сообщения: 119
Зарегистрирован: Ср ноя 07, 2007 15:17:20

Сообщение Dexa »

В протеусе не пашет. Кнопка весит на входе внешнего прерывания INT1, как только наступило прерывание - антидребезг кнопки, включаем реле, потом задержка на 3 секунды примерно (при этом светодиод моргает примерно каждые 0,5 секунды), потом выключили реле. Знаю задержка реализована глупо, если подскажите как лучше со сведодиодами и задержкой (а еще и научно популярно объясните) то буду только рад.
З.ы. И еще вопросик - не могу понять как загружается константа
ldi R16,(0<<ISC00)|(1<<ISC01)
Что написано после запятой?
Вложения
Work.rar
(17.23 КБ) 190 скачиваний
......aлкоголь расширяет сосуды, курение их сужает, а сдают почему-то нервы......
Контактная информация:
Реклама
GP1
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2401
Зарегистрирован: Пт май 23, 2008 19:32:22
Откуда: Россия, Волгоград

Сообщение GP1 »

первое - обработчик прерывания должен заканчиваться командой reti, а не ret
по остальному гляну чуть позже.
Чем дальше, тем больше становлюсь занудой...
Изображение
Контактная информация:
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 119
Зарегистрирован: Ср ноя 07, 2007 15:17:20

Сообщение Dexa »

Он и заканчивается командой reti. Я толко учусь и не знаю точно можно ли в обработчике прерываний использовать подпрограммы, которые находяться как бы сказать за пределами, т.е. внимательнее посмотрите, после команды reti стоят подпрограммы.
......aлкоголь расширяет сосуды, курение их сужает, а сдают почему-то нервы......
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 31
Зарегистрирован: Вс сен 13, 2009 15:42:50
Откуда: Львів

Сообщение Петро »

ldi R16, (0 <<ISC00) | (1 <<ISC01) означает: бит ISC00 является нулевым в регистре MCUCR, следовательно в R16 нулевой бит сбрасывается в 0 (0 <<ISC00), бит ISC01 является первым в MCUCR, следовательно в регистре R16 первый бит сбрасывается в 1 (1 <<ISC01);
конечно, можно в обработчике прерываний вызвать функции за его пределами;
кроме того, вместо стольких ненужных переходов на обработчики прерываний и пустых обработчиков вы можете написать:
. org INT1addr; переход на адрес вектора прерывания при возникновении
rjmp EXT_INT1; переход по вектору прерывания на обработчик
INT1addr - константа, определенная в файле констант для определенной модели МК, см. 2313def
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Первый раз сказал Мяу!
Сообщения: 31
Зарегистрирован: Вс сен 13, 2009 15:42:50
Откуда: Львів

Сообщение Петро »

а задержку можно реализовать так: в обработчике RESET программируем таймер 1 на задержку 0.5 сек, в функции Zadergka пишем sei (так как при переходе по прерыванию EXT_INT1 в регистре SREG бит И = 0) и разрешаем прерывание по равенства счетного регистра TCNT1 i OCR1A:
ldi R16, (1 <<OCIE1A)
out TIMSK, R16

Вот код:

Код: Выделить всё

;AT90S2313  @  External 4Mhz
.nolist
.include "2313def.inc"
.list
;***************??????????*****************
.def	temp=R16
.def    temp1=r17
.def  temp2=r18
.def temp3=r19
.def count=r20
.def count1=r21
.def temp4=r22


;***********************************************
.cseg
.org 0
    rjmp RESET    ; Reset Handler
.org INT1addr
    rjmp EXT_INT1 ; IRQ1 Handler
.org OC1addr
	rjmp OC1
              
;***************?????????????*****************
RESET:   ldi temp,RamEnd	;????????????? ?????
              out SPL,temp
	;cli     зачем запрещаэш преривания? по-моему, это лишнее
              ldi temp,0b11111111;????? ? ?????? ????? B
              out DDRB,temp
              ldi temp,0b10000011;????? ? ?????? ????? D
              out DDRD,temp
              ldi temp,0b00000000;????????? ????????? ????? B ? ????????
              out PortB,temp
              ldi temp,0b00000000;????????? ????????? ????? D ? ????????
              out PortD,temp
              ldi	Temp,0b11000000;????????? ?????????? INT0 ? INT1
              out	GIMSK,Temp
              ldi Temp,0b00001010; INT0 ?? ?? ?????????? ??????, INT1 ?? ?????????? ??????
              out MCUCR,Temp
              ldi temp,(1<<CS10)|(1<<CS12)
			  ;деления частоты 1024
              out TIMSK, temp        
              ;таймера обнулять не надо пока
	;и еще посчитай количество импульсов Х за 0,5 сек при деления частоты МК на 1024 по формуле 0.5 / (1 / (частота МК / 1024)) вручную и запиши в OCR1A округленное значение
Х - двухбайтовые значение
              ldi temp,X1	
	  out OCR1AL,temp
              ldi temp,X2	
	  out OCR1AH,temp
              sei 

Start:    ldi temp4,0b10000000
            out GIFR,temp4
            rjmp Start; ??????????? ????
EXT_INT1:
              rcall Antidrebezg
              in temp3, SREG
              push temp3
              sbi PortB,4; ??????? ?????
              rcall Zadergka
              cbi PortB,4;??????? ?????
              pop temp3
              out SREG,temp3
              reti; ????? ?? ??????????? ?????????? INT1
;*****************???????????*********************
; ??? ?????? 4 ??? ???? ?????? ????? ???????? 10 ??, ????????? ?????????? count 
;???????? 2 ??????? - ???????? 20 ??
Antidrebezg:
              push Temp1
              push Temp2
              ldi Temp1,0
              ldi Temp2,50
              ldi count,2
d11:        dec Temp1
              brne d11
              dec Temp2
              brne d11
              pop Temp2
              pop Temp1
              dec count
              brne d11
              ret

Zadergka:
	in temp,TIMSK
            sbr temp,OCIE1A
	out TIMSK,temp
	sei
	clr R23		;R23=0000 0000
While:	cpi R23,6
	brlo While  ;если R17=6, т.е. прошло 3 сек (6 по 0.5), тогда запрещаем прерывание от таймера 1, выходим из функции, а иначе дальше будут прерывания каждые 0,5 сек
	cbr temp,OCIE1A
        	out TIMSK, temp
	ret
OC1:
            ;обнуление таймера
	;засветки светодиода	
	inc R23
	reti
Контактная информация:
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 119
Зарегистрирован: Ср ноя 07, 2007 15:17:20

Сообщение Dexa »

Спасибо. Но не совсем понял смысл sbr temp,OCIE1A. Вот это логическое или зачем нужно? Сложновато мне понять применение масок((
Так в целом выходит моя программа рабочая, просто не совсем грамотно написана, так? В протеусе и ваша и моя не работают( Если у вас есть иные компиляторы (я делал в AVRstudio), попробуйте откомпилить ее и проверить в моем проекте протеуса. Заранее благодарен.
p.s
точно не уверен, ибо не совсем освоил AVRstudio, но вроде моя прога после reti возвращается не на строку rjmp Start, а на вектор прерывания reset, что вроде не правильно. Может где-то чего не хватает?
......aлкоголь расширяет сосуды, курение их сужает, а сдают почему-то нервы......
Контактная информация:
Реклама
Первый раз сказал Мяу!
Сообщения: 31
Зарегистрирован: Вс сен 13, 2009 15:42:50
Откуда: Львів

Сообщение Петро »

Код: Выделить всё

;AT90S2313  @  External 4Mhz
.nolist
.include "2313def.inc"
.list
;***************??????????*****************
.def temp=R16

;***********************************************
.cseg
.org 0
    rjmp RESET    ;Reset Handler
.org INT1addr
	rjmp INT_1
              
;***************?????????????*****************
RESET:   ldi temp,RamEnd	;????????????? ?????
         out SPL,temp
		 sbi DDRD,0
		 cbi DDRD,3
         sbi DDRB,4
		 ldi temp,(1<<ISC10)|(1<<ISC11)
		 out MCUCR,temp
		 ldi temp,(1<<INT1)
		 out GIMSK,temp         
         sei		 
Start:   rjmp Start;

INT_1:
		ldi R26,6
		while:
			rcall Svitim
			rcall Zadergka
			rcall Gasim
			rcall Zadergka
			dec R26
			brne while
		reti

Gasim:
        cbi PortD,0;??????? ?????
		cbi PortB,4;??????? ?????
		ret
Svitim:
		sbi PortD,0; ??????? ?????
		sbi PortB,4; ??????? ?????
		ret
Zadergka:
		ldi R25,5
		for:
			dec R23
			brne for
			dec R24
			brne for
			dec R25
		brne for						
		ret
Здесь при нажатии кнопки генерируется прерывание, при переходе на обработчик, прерывание автоматически запрещаются на несколько секунд, чем гарантуэться нужна временная задержка, за которое происходит почти 6 мигань светодиодов по 0.5 сек

Задержка использует такты процессора чтобы отчислить примерно 0.5 сек. Каждая команда dec занимает 1 такт, brne тоже 1. Тогда самый первый цикл выполнится за N1 = 256 * 2 = 512 тактов, второй цикл содержит первый, то есть второй исполнится 256 раз так же за 512 тактов, но в нем также исполнится 256 раз первый цикл, на что уйдет еще 255 * N1 тактов. Тогда время выполнения 2-го цикла N2 = 512 +256 * N1 = 131584.3-тий цикл повторится также 5 раз, а в нем 256 раз повторится цикл 2. N3 = 5 * N2 +512 = 658432. Итак, ф-л задержки отсчитает N = N1 + N2 + N3 = 790 528 тактов, примерно 800 000. Частота кварца МК 4 МГц = 4 000 000 Гц. Тогда период Т = 1 / 4 000 000 = 0.00000025 сек на 1 такт. Тогда период выполнения ф = й Zadergka t = 0.00000025 * 800 000 = 0.2 сек. Поскольку для одного мигания ф-я вызывается 2 раза, то t = 2 * 0.2 = 0.4 сек. По внешнему прерыванию в обработчике срабатывает цикл из 6 итераций (3:0.5 = 6 мигань). Далее вы разберетесь сами, если почитаете нечто из "Микроконтроллеры в радиолюбительской практике" Белова и "Микроконтроллеры AVR семейства Mega" Евстифеева.

P.S.sbr temp,OCIE1A означает: бит №OCIE1A регистра temp = 1
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 31
Зарегистрирован: Вс сен 13, 2009 15:42:50
Откуда: Львів

Сообщение Петро »

Кстати, хотя есть задержка на целых 2.4 сек, прерывания все равно будут генерироваться при дребезге кнопки, так как будут изменения сигнала, подаваемого на PORTD3. Впоследствии сгенерированные прерывания будут ставиться в очередь и обрабатываться поочередно после выполнения обработчика. Следовательно, надо избежать поступления сигналов на вывод PORTD3. Поэтому в начале обработчика внешнего прерывания настраиваем PORTD3 на вывод (sbi DDRD, 3), чтобы через него не вводилась информация и не было лжепрериваний; ну и бит 3 регистра PORTD записываем 1, чтобы не возникало более 6-ти мигань (sbi PortD, 3). А в конце обработчика снова настраиваем третий вывод на вход (cbi DDRD, 3), чтобы он принимал сигналы. Тогда обработчик будет таким:

Код: Выделить всё

INT_1:
		sbi DDRD,3	;íà âèâ³ä,ùîá íå íàäõîäèëî ñèãíàë³â\
		sbi PortD,3
		ldi R26,6
		while:
			rcall Svitim
			rcall Zadergka
			rcall Gasim
			rcall Zadergka
			dec R26
			brne while
		cbi DDRD,3
		reti
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 119
Зарегистрирован: Ср ноя 07, 2007 15:17:20

Сообщение Dexa »

хм...огромное спасибо, работает. Но так как я учусь, то мне очень важно понять что я сдел не так? почему не работал мой алгоритм? Моя ошибка где-то в подпрограмме задержки или в подпрограмме антидребезга. Я их убрал, но хоть убей не пойму почему не работало?
p.s. ваш способ антидребезга странно работате: диод моргает 12 раз и время увеличилось в 2 раза, а всего то 3 строки добавили:
sbi DDRD,3 ;ia aea?a,uia ia iaaoiaeei neaiae?a\
sbi PortD,3
.
.
.
cbi DDRD,3
не знаю почему так происходит, но тем самым срабатывает второе прерывание. Без них все правильно моргает 6 раз.
Теперь совсем запутался. Настроили порт Д на выход, командой sbi PortD,3 сделали на выводе логическую единичку. Все логично, снова настраиваем на ввод и все) Где собака зарыта?!
......aлкоголь расширяет сосуды, курение их сужает, а сдают почему-то нервы......
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 31
Зарегистрирован: Вс сен 13, 2009 15:42:50
Откуда: Львів

Сообщение Петро »

Но так как я учусь, то мне очень важно понять что я сдел не так?
Ну во-первых, не надо трогать регистров ...IFR (GIFR, TIFR и т.д), их биты изменяют свое состояние сами при возникновении прерываний. Поэтому в своей первоначальной версии сотрыте обращения к GIFR, оставте следующее: Start: rjmp Start
И, как я писал ранее, временная задержка при нажатии кнопки лишь откладывает обработку прерываний на потом, потому сотрыте функцию Antidrebezg и обращение к ней.
Компилите, запускаете в Протеус, при нажатии на кнопку светодиод от PB4 светиться постоянно, а от PD0 мигнет только 1 раз. Это потому, что вы записываете 1 в PD0 только в начале функции Zadergka, а в цикле всего лишь сбрасываете его в 0. А надо и в цикле записывать в него 1.
Задержка в вас очень большая, лучше считайте такты процессора МК (так, как я описывал выше). И в функции Zadergka должен быть, по-идеи одна лишь задержка времени, а вы еще и светодиод хотите зажечь там. Лучшее в обработчике EXT_INT1 внешнего прерывания организуйте цикл, который меняет значение PD0 i PB4, зажигая и гася светодиоды.

Код: Выделить всё

;AT90S2313  @  External 4Mhz
.nolist
.include "2313def.inc"
.list
;***************??????????*****************
.def	temp=R16
.def    temp1=r17
.def  temp2=r18
.def temp3=r19
.def count=r20
.def count1=r21
.def temp4=r22


;***********************************************
.cseg
.org 0
rjmp RESET    ; Reset Handler
              rjmp EXT_INT0 ; IRQ0 Handler
              rjmp EXT_INT1 ; IRQ1 Handler
              rjmp TIM_CAPT1 ; Timer1 Capture Handler
              rjmp TIM_COMP1 ; Timer1 Compare Handler
              rjmp TIM_OVF1 ; Timer1 Overflow Handler
              rjmp TIM_OVF0 ; Timer0 Overflow Handler
              rjmp UART_RXC ; UART RX Complete Handler
              rjmp UART_DRE ; UDR Empty Handler
              rjmp UART_TXC ; UART TX Complete Handler
              rjmp ANA_COMP ; Analog Comparator Handler
              EXT_INT0: ret
			  TIM_COMP1: ret
			  TIM_OVF1:ret
              TIM_CAPT1 :	ret
              TIM_OVF0  : ret
              UART_RXC  : ret
              UART_DRE  : ret
              UART_TXC  : ret
              ANA_COMP  : ret
;***************?????????????*****************
RESET:   ldi temp,RamEnd	;????????????? ?????
              out SPL,temp
              cli
              ldi temp,0b11111111;????? ? ?????? ????? B
              out DDRB,temp
              ldi temp,0b10000011;????? ? ?????? ????? D
              out DDRD,temp
              ldi temp,0b00000000;????????? ????????? ????? B ? ????????
              out PortB,temp
              ldi temp,0b00000000;????????? ????????? ????? D ? ????????
              out PortD,temp
              ldi	Temp,0b11000000;????????? ?????????? INT0 ? INT1
              out	GIMSK,Temp
              ldi Temp,0b00001010; INT0 ?? ?? ?????????? ??????, INT1 ?? ?????????? ??????
              out MCUCR,Temp
              ldi Temp,0b11000000; ???????? ?????????? ?? ???????????? 1 ??????? 
              out TIMSK, Temp        
              ldi Temp,0            ;????????? ???????
              out TCNT1H,Temp
              out TCNT1L,Temp
              sei 

Start:        rjmp Start; ??????????? ????
EXT_INT1:
              in temp3, SREG
              push temp3
			  ldi R23,3
			While:
              sbi PortB,4	;??????? ?????
			  sbi PortD,0
              rcall Zadergka			  
              cbi PortB,4	;??????? ?????
			  cbi PortD,0
			  rcall Zadergka
			  dec R23
			brne While
              pop temp3
              out SREG,temp3
              reti; ????? ?? ??????????? ?????????? INT1
;*****************???????????*********************
; ??? ?????? 4 ??? ???? ?????? ????? ???????? 10 ??, ????????? ?????????? count 
;???????? 2 ??????? - ???????? 20 ??

Zadergka:
              push Temp1
              push Temp2
              ldi Temp1,0
              ldi Temp2,0
              ldi count,15
              ldi count1,2
d12:        dec Temp1
              brne d12
              dec Temp2
              brne d12
	  dec count
              brne d12
              pop Temp2
              pop Temp1
              ret
[/quote]
Последний раз редактировалось Петро Вс дек 13, 2009 03:36:25, всего редактировалось 1 раз.
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 31
Зарегистрирован: Вс сен 13, 2009 15:42:50
Откуда: Львів

Сообщение Петро »

p.s. ваш способ антидребезга странно работате: диод моргает 12 раз и время увеличилось в 2 раза
Да, я уже исправил ошибку. При инициализации MCUCR я задал изменении входного сигнала по переднему фронту при любом изменении значения на выводе PD3:

Код: Выделить всё

ldi temp, (1 <<ISC10) | (1 <<ISC11) 
out MCUCR, temp
И поэтому, когда меняем в начале обработчика INT_1 значение вывода sbi PortD, 3, генерируется ненужное прерывания. На самом деле надо при инициализации MCUCR задать, что 0 на входе INT1 (наш PD3) вызывает прерывание, и проблема исчезнет.

Код: Выделить всё

ldi temp,(0<<ISC10)|(0<<ISC11)
out MCUCR,temp
Кстати, в своем уже работающем варианте вы можете в обработчик добавить мой прием антидребезга
sbi DDRD,3 ;ia aea?a,uia ia iaaoiaeei neaiae?a\
sbi PortD,3
.
.
.
cbi DDRD,3[/code]
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 119
Зарегистрирован: Ср ноя 07, 2007 15:17:20

Сообщение Dexa »

Спасибо!
......aлкоголь расширяет сосуды, курение их сужает, а сдают почему-то нервы......
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 31
Зарегистрирован: Вс сен 13, 2009 15:42:50
Откуда: Львів

Сообщение Петро »

Да пожалуйста, всегда рад помочь!
Контактная информация:
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»