Пробема с прерываниями

Обсуждаем контроллеры компании Atmel.
vk_31
Первый раз сказал Мяу!
Сообщения: 37
Зарегистрирован: Чт май 19, 2016 11:22:52

Пробема с прерываниями

Сообщение vk_31 »

Добрый вечер!
Прошу помощи в решении проблемы. Имеется контроллер ATmega169pa-au. PORTE настроен на вход и подтянут резисторами внутри контроллера. На PE3 и PE6 подключена кнопка замыкающая на землю. PORTB настроен на выход и на PB6 повешен светодиод. Так же настроены прерывания по PCINT0..7.
Проблема вот в чем: на реальном устройстве не происходит отработка прерывания PCINT0 (кнопка повешена на PE3/PCINT3). При нажатии на кнопку, которая подвешена на PE6 светодиод включается.
Схема устройства упрощена (отсутствует LCD с обвязкой, кварц, ключи на транзисторах и т.д.), но суть проблемы передает.
Изображение
Вот такой код залит в контроллер:

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

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>


int main (void)
{

	DDRE = 0x00; // Порт E на вход
	PORTE = 0xff; // включаем поддтяжки на порте E
	PCMSK0 = 0xff; //маска прерываний на порт E	

	EIMSK |= (1<<PCIE0); // включение прерываний PCINT7..0	
	
	sei();// Разрешаем прерывания глобально.	
	
	DDRB |= (1<<PB0) | (1<<PB6); // Порт B на выход	
	PORTB = 0x00;
	
	while(1) {
		if (!(PINE & (1<<PE6)))
			PORTB |= (1<<PB6);
	};
}


ISR(PCINT0_vect) {	
	PORTB ^= (1<<PB6);
}
Реклама
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

Re: Пробема с прерываниями

Сообщение pyzhman »

Просимулировал в протеусе. Работает согласно программе. А в реальном устройстве обратите внимание на то, что у кнопок есть дребезг контактов, от которого нужно всегда избавляться.
Docendo discimus
Реклама
vk_31
Первый раз сказал Мяу!
Сообщения: 37
Зарегистрирован: Чт май 19, 2016 11:22:52

Re: Пробема с прерываниями

Сообщение vk_31 »

pyzhman писал(а):Просимулировал в протеусе. Работает согласно программе. А в реальном устройстве обратите внимание на то, что у кнопок есть дребезг контактов, от которого нужно всегда избавляться.
С дребезгом все равно был бы какой-нибудь результат, тем более что опрос кнопки в цикле работает (решение избавления от дребезга уже есть, только все уперлось в прерывания)
Может кто сталкивался с ошибками в разводке платы при которых не срабатывали прерывания? Есть еще подозрение на китайский МК, но если была бы подделка он не прошивался бы...
Аватара пользователя
B@R5uk
Собутыльник Кота
Сообщения: 2896
Зарегистрирован: Сб ноя 13, 2010 12:53:25
Откуда: приходит весна?

Re: Пробема с прерываниями

Сообщение B@R5uk »

Когда ничего не работает, то начинать надо сначала:
1) проверить наличие питания.
2) помигать светодиодом без всяких кнопок (я вместо этого обычно таймер на выход включаю и звук слушаю, за одно можно системную частоту проверить) а то вдруг генератор не завёлся.
3) проверять уже программу, вставляя всевозможные системные выводы в разные места: переключить ножку, отправить введённый с порта байт по USART и так далее.
Реклама
Эиком - электронные компоненты и радиодетали
vk_31
Первый раз сказал Мяу!
Сообщения: 37
Зарегистрирован: Чт май 19, 2016 11:22:52

Re: Пробема с прерываниями

Сообщение vk_31 »

B@R5uk писал(а):Когда ничего не работает, то начинать надо сначала:
1) проверить наличие питания.
2) помигать светодиодом без всяких кнопок (я вместо этого обычно таймер на выход включаю и звук слушаю, за одно можно системную частоту проверить) а то вдруг генератор не завёлся.
3) проверять уже программу, вставляя всевозможные системные выводы в разные места: переключить ножку, отправить введённый с порта байт по USART и так далее.
1) питание есть
2) светодиод моргает по таймеру и по нажатию на кнопку если ее опрашивать в цикле программы
3) программу специально упростил для примера
Все работает, таймер тикает, LCD завелся, порты окрашиваются и устанавливаются все кроме этого прерывания.
Уже не знаю где ошибка. Может адрес вектора прерывания МК изменен, а WinAvr со старыми работает? Даташит имеется для ATMega169, а у меня ATMega169pa-au, хотя врят ли это имеет большое значение
Реклама
Vov123
Опытный кот
Сообщения: 804
Зарегистрирован: Чт мар 12, 2009 16:31:05

Re: Пробема с прерываниями

Сообщение Vov123 »

Отключи fuse JTAG.
Реклама
Аватара пользователя
Z_h_e
Собутыльник Кота
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Re: Пробема с прерываниями

Сообщение Z_h_e »

Тоже такая мысль в голову пришла. Глянул ДШ, он там на порте F висит. Вроде как не при делах.

vk_31, попробуйте прерывание с других пинов запустить. Может стоит глянуть в дезассемблере вектора прерываний :dont_know: .
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
vk_31
Первый раз сказал Мяу!
Сообщения: 37
Зарегистрирован: Чт май 19, 2016 11:22:52

Re: Пробема с прерываниями

Сообщение vk_31 »

Z_h_e писал(а):Тоже такая мысль в голову пришла. Глянул ДШ, он там на порте F висит. Вроде как не при делах.

vk_31, попробуйте прерывание с других пинов запустить. Может стоит глянуть в дезассемблере вектора прерываний :dont_know: .
На все портах E одинакова ситуация(
Дизассемблер попробую посмотреть
Аватара пользователя
Mishany
Электрический кот
Сообщения: 1031
Зарегистрирован: Чт июн 20, 2013 00:00:58
Откуда: москва, м.Сходненская

Re: Пробема с прерываниями

Сообщение Mishany »

Может ноги к vcc резисторами притянуть?
vk_31
Первый раз сказал Мяу!
Сообщения: 37
Зарегистрирован: Чт май 19, 2016 11:22:52

Re: Пробема с прерываниями

Сообщение vk_31 »

Долго не отвечал, т.к. ждал новый камень
Vov123 писал(а):Отключи fuse JTAG.
Отключил, без изменений все.

Сейчас такой код залит в МК:

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

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

int main (void)
{

	DDRB |= (1<<PB0) | (1<<PB6); // Порт B на выход	
	PORTB = 0x00;

	DDRE &= ~((1<<PE3) | (1<<PE6)); // Порт E на вход
	PORTE |= (1<<PE3) | (1<<PE6); // включаем подтяжки на порте E

	EIMSK = (1<<PCIE0); // включение прерываний PCINT7..0	

	PCMSK0 |= (1<<PE3) | (1<<PE6); //маска прерываний на порт E
	
	sei();// Разрешаем прерывания глобально.	
	
	
	while(1) {
		if (!(PINE & (1<<PE6)))
			PORTB ^= (1<<PB6);
			
		//if (!(PINE & (1<<PE3)))
			//PORTB ^= (1<<PB0);

	};
}


ISR(PCINT0_vect) {	
	PORTB ^= (1<<PB6);
	PORTB ^= (1<<PB0);
}
На PE3 и PE6 висят кнопки, а на PB0 и PB6 светодиоды. При опросе в цикле все работает, на прерываниях - нет.

Фьюзы такие:
LOW: 0x62
HIGH: 0xD9
EXTENDED: 0xFF

Lock Bits: 0x3F
Vov123
Опытный кот
Сообщения: 804
Зарегистрирован: Чт мар 12, 2009 16:31:05

Re: Пробема с прерываниями

Сообщение Vov123 »

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

PCMSK0 = (1<<PCINT3) | (1<<PCINT6); //маска прерываний на порт E
EIFR = (1<<PCIF0);
vk_31
Первый раз сказал Мяу!
Сообщения: 37
Зарегистрирован: Чт май 19, 2016 11:22:52

Re: Пробема с прерываниями

Сообщение vk_31 »

Vov123 писал(а):

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

PCMSK0 = (1<<PCINT3) | (1<<PCINT6); //маска прерываний на порт E
EIFR = (1<<PCIF0);
Не помогло(

У меня был регулятор теплого пола с дисплеем на этом МК и я его прошивал - прерывания срабатывали. А развел свою плату, так все работает кроме прерываний PCINT

Уже грешу на разводку платы, хотя она и не сложная. Плату прилагаю
Вложения
SS.lay6
Печатная плата
(116.74 КБ) 295 скачиваний
Аватара пользователя
dr.doc
Это не хвост, это антенна
Сообщения: 1368
Зарегистрирован: Вс мар 28, 2010 12:52:22
Откуда: Беларусь

Re: Пробема с прерываниями

Сообщение dr.doc »

When the BOOTRST Fuse is unprogrammed
0x1C04 jmp PCINT0 ; PCINT0 Handler Читайте внимательно datasheet на странице 48 и 268.
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
vk_31
Первый раз сказал Мяу!
Сообщения: 37
Зарегистрирован: Чт май 19, 2016 11:22:52

Re: Пробема с прерываниями

Сообщение vk_31 »

dr.doc писал(а):When the BOOTRST Fuse is unprogrammed
0x1C04 jmp PCINT0 ; PCINT0 Handler Читайте внимательно datasheet на странице 48 и 268.
Запрограммировал BOOTRST Fuse, HIGH Fuse стал 0xD8, ситуация не изменилась. Или я Вас неправильно понял?
Аватара пользователя
dr.doc
Это не хвост, это антенна
Сообщения: 1368
Зарегистрирован: Вс мар 28, 2010 12:52:22
Откуда: Беларусь

Re: Пробема с прерываниями

Сообщение dr.doc »

По умолчанию BOOTRST - unprogrammed. При этом вектор прерываний от EXT_INT0 начинается с адреса 0x1C04. В случае запрограммированного fuse BOOTRST вектор прерываний от EXT_INT0 смещается на адрес 0x0004. По fuse должно работать.

Добавлено after 21 minute 26 seconds:
Возможно, но не факт - от четного числа импульсов дребезга процедура ИСКЛЮЧАЮЩЕЕ ИЛИ для выводов может возвращать состояние выхода на исходное. В то же время работа при опросе в цикле выполняется несколько иначе (прерывания срабатывают по спаду сигнала на входе). Тонкий момент тут - наличие четного числа импульсов дребезга.
Выполните тест, зажигая светодиод при первом же попадании в прерывание. Таким образом проверите их отработку.
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
vk_31
Первый раз сказал Мяу!
Сообщения: 37
Зарегистрирован: Чт май 19, 2016 11:22:52

Re: Пробема с прерываниями

Сообщение vk_31 »

dr.doc писал(а):Выполните тест, зажигая светодиод при первом же попадании в прерывание. Таким образом проверите их отработку.
Вы имеете ввиду сделать так:

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

ISR(PCINT0_vect) {   
   PORTB |= (1<<PB6);
   PORTB |= (1<<PB0);
}
Тоже результата нет.

Все больше и больше склоняюсь с тому, что есть ошибки в разводке платы (хоть и не понимаю как это может быть связано), т.к. прерывания на макетке с тем же камнем и фьюзами работают...
akl
Друг Кота
Сообщения: 4445
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Пробема с прерываниями

Сообщение akl »

dr.doc писал(а):По умолчанию BOOTRST - unprogrammed. При этом вектор прерываний от EXT_INT0 начинается с адреса 0x1C04. В случае запрограммированного fuse BOOTRST вектор прерываний от EXT_INT0 смещается на адрес 0x0004. По fuse должно работать.
Строго наоборот.
Table 111. Boot Reset Fuse(1)
BOOTRST______________Reset Address
___1________Reset Vector = Application Reset (address 0x0000)
___0________Reset Vector = Boot Loader Reset (see Table 113 on page 264)
Note: 1. “1” means unprogrammed, “0” means programmed
vk_31
Первый раз сказал Мяу!
Сообщения: 37
Зарегистрирован: Чт май 19, 2016 11:22:52

Re: Пробема с прерываниями

Сообщение vk_31 »

Добавил прерывания на INT0 и PCINT1 чтобы исключить неправильную адресацию

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

EICRA = (1<<ISC00); //Any logical change on INT0 generates an interrupt request.
PCMSK0 = (1<<PCINT3) | (1<<PCINT6); //PE3 и PE6
PCMSK1 = (1<<PCINT13); //PB5

EIMSK = (1<<PCIE0) | (1<<PCIE1) | (1<<INT0);

ISR(PCINT1_vect) {   
   PORTB ^= (1<<PB6);
}

ISR(INT0_vect) {   
   PORTB ^= (1<<PB6);
}

По INT0 прерывание вызывается, по PCINT1 - нет
Аватара пользователя
dr.doc
Это не хвост, это антенна
Сообщения: 1368
Зарегистрирован: Вс мар 28, 2010 12:52:22
Откуда: Беларусь

Re: Пробема с прерываниями

Сообщение dr.doc »

Верно, ошибся. Но! Поигравшись в студии на Асьме нашел, что бит PCIE0 записывается в регистр только командой out. Команда sts не записывает бит в студии! Попробуйте сделать ассемблерную вставку
Спойлерldi r16,(1<<PCIE0)
;sts EIMSK,r16
out EIMSK,r16
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
vk_31
Первый раз сказал Мяу!
Сообщения: 37
Зарегистрирован: Чт май 19, 2016 11:22:52

Re: Пробема с прерываниями

Сообщение vk_31 »

dr.doc писал(а):Попробуйте сделать ассемблерную вставку
Спойлерldi r16,(1<<PCIE0)
;sts EIMSK,r16
out EIMSK,r16
Я пишу в WinAVR. Посмотрел его дизассемблер - присвоение идет out'ом

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

   EIMSK = (1<<PCIE0) | (1<<PCIE1) | (1<<INT0); // включение прерываний PCINT7..0   
  a6:	81 ec       	ldi	r24, 0xC1	; 193
  a8:	8d bb       	out	0x1d, r24	; 29
Все же сделал вставку, но это не помогло.
С ассемблером на Вы, поэтому выкладываю код
Спойлер

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


main.elf:     file format elf32-avr


Disassembly of section .text:

00000000 <__vectors>:
   0:	0c 94 2e 00 	jmp	0x5c	; 0x5c <__ctors_end>
   4:	0c 94 77 00 	jmp	0xee	; 0xee <__vector_1>
   8:	0c 94 59 00 	jmp	0xb2	; 0xb2 <__vector_2>
   c:	0c 94 65 00 	jmp	0xca	; 0xca <__vector_3>
  10:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  14:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  18:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  1c:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  20:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  24:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  28:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  2c:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  30:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  34:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  38:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  3c:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  40:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  44:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  48:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  4c:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  50:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  54:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>
  58:	0c 94 38 00 	jmp	0x70	; 0x70 <__bad_interrupt>

0000005c <__ctors_end>:
  5c:	11 24       	eor	r1, r1
  5e:	1f be       	out	0x3f, r1	; 63
  60:	cf ef       	ldi	r28, 0xFF	; 255
  62:	d4 e0       	ldi	r29, 0x04	; 4
  64:	de bf       	out	0x3e, r29	; 62
  66:	cd bf       	out	0x3d, r28	; 61
  68:	0e 94 3a 00 	call	0x74	; 0x74 <main>
  6c:	0c 94 89 00 	jmp	0x112	; 0x112 <_exit>

00000070 <__bad_interrupt>:
  70:	0c 94 00 00 	jmp	0	; 0x0 <__vectors>

00000074 <main>:
#include <avr/interrupt.h>

int main (void)
{

   DDRB |= (1<<PB0) | (1<<PB6); // Порт B на выход   
  74:	84 b1       	in	r24, 0x04	; 4
  76:	81 64       	ori	r24, 0x41	; 65
  78:	84 b9       	out	0x04, r24	; 4
   PORTB &= ~((1<<PB0) | (1<<PB6)); //  0x00;
  7a:	85 b1       	in	r24, 0x05	; 5
  7c:	8e 7b       	andi	r24, 0xBE	; 190
  7e:	85 b9       	out	0x05, r24	; 5
   
   DDRB &= ~(1<<PB5); // Порт B на выход   
  80:	25 98       	cbi	0x04, 5	; 4
   PORTB |= (1<<PB5); //  0x00;
  82:	2d 9a       	sbi	0x05, 5	; 5
   
   DDRD &= ~(1<<PD1); // Порт D на вход
  84:	51 98       	cbi	0x0a, 1	; 10
   PORTD |= (1<<PD1); // включаем подтяжки на порте D
  86:	59 9a       	sbi	0x0b, 1	; 11

   DDRE = 0x00; // Порт E на вход
  88:	1d b8       	out	0x0d, r1	; 13
   PORTE = 0xFF; // включаем подтяжки на порте E
  8a:	9f ef       	ldi	r25, 0xFF	; 255
  8c:	9e b9       	out	0x0e, r25	; 14
   
   EICRA = (1<<ISC00);//Any logical change on INT0 generates an interrupt request.
  8e:	81 e0       	ldi	r24, 0x01	; 1
  90:	80 93 69 00 	sts	0x0069, r24
   PCMSK0 = 0xff; //маска прерываний на порт E
  94:	90 93 6b 00 	sts	0x006B, r25
   PCMSK1 = (1<<PCINT13); //PB5
  98:	80 e2       	ldi	r24, 0x20	; 32
  9a:	80 93 6c 00 	sts	0x006C, r24
   
   EIMSK = (1<<PCIE0) | (1<<PCIE1) | (1<<INT0); // включение прерываний PCINT7..0   
  9e:	81 ec       	ldi	r24, 0xC1	; 193
  a0:	8d bb       	out	0x1d, r24	; 29

   //EIFR = (1<<PCIF0) | (1<<PCIF1) | (1<<INTF0);
   
   sei();// Разрешаем прерывания глобально.   
  a2:	78 94       	sei
   
   
	while(1) {
		if (!(PINE & (1<<PE6)))
			PORTB ^= (1<<PB6);
  a4:	90 e4       	ldi	r25, 0x40	; 64
   
   sei();// Разрешаем прерывания глобально.   
   
   
	while(1) {
		if (!(PINE & (1<<PE6)))
  a6:	66 99       	sbic	0x0c, 6	; 12
  a8:	fe cf       	rjmp	.-4      	; 0xa6 <main+0x32>
			PORTB ^= (1<<PB6);
  aa:	85 b1       	in	r24, 0x05	; 5
  ac:	89 27       	eor	r24, r25
  ae:	85 b9       	out	0x05, r24	; 5
  b0:	fa cf       	rjmp	.-12     	; 0xa6 <main+0x32>

000000b2 <__vector_2>:

	};
}


ISR(PCINT0_vect) {   
  b2:	1f 92       	push	r1
  b4:	0f 92       	push	r0
  b6:	0f b6       	in	r0, 0x3f	; 63
  b8:	0f 92       	push	r0
  ba:	11 24       	eor	r1, r1
   PORTB |= (1<<PB6);
  bc:	2e 9a       	sbi	0x05, 6	; 5
   PORTB |= (1<<PB0);
  be:	28 9a       	sbi	0x05, 0	; 5
}
  c0:	0f 90       	pop	r0
  c2:	0f be       	out	0x3f, r0	; 63
  c4:	0f 90       	pop	r0
  c6:	1f 90       	pop	r1
  c8:	18 95       	reti

000000ca <__vector_3>:

ISR(PCINT1_vect) {   
  ca:	1f 92       	push	r1
  cc:	0f 92       	push	r0
  ce:	0f b6       	in	r0, 0x3f	; 63
  d0:	0f 92       	push	r0
  d2:	11 24       	eor	r1, r1
  d4:	8f 93       	push	r24
  d6:	9f 93       	push	r25
   PORTB ^= (1<<PB6);
  d8:	85 b1       	in	r24, 0x05	; 5
  da:	90 e4       	ldi	r25, 0x40	; 64
  dc:	89 27       	eor	r24, r25
  de:	85 b9       	out	0x05, r24	; 5
}
  e0:	9f 91       	pop	r25
  e2:	8f 91       	pop	r24
  e4:	0f 90       	pop	r0
  e6:	0f be       	out	0x3f, r0	; 63
  e8:	0f 90       	pop	r0
  ea:	1f 90       	pop	r1
  ec:	18 95       	reti

000000ee <__vector_1>:

ISR(INT0_vect) {   
  ee:	1f 92       	push	r1
  f0:	0f 92       	push	r0
  f2:	0f b6       	in	r0, 0x3f	; 63
  f4:	0f 92       	push	r0
  f6:	11 24       	eor	r1, r1
  f8:	8f 93       	push	r24
  fa:	9f 93       	push	r25
   PORTB ^= (1<<PB6);
  fc:	85 b1       	in	r24, 0x05	; 5
  fe:	90 e4       	ldi	r25, 0x40	; 64
 100:	89 27       	eor	r24, r25
 102:	85 b9       	out	0x05, r24	; 5
 104:	9f 91       	pop	r25
 106:	8f 91       	pop	r24
 108:	0f 90       	pop	r0
 10a:	0f be       	out	0x3f, r0	; 63
 10c:	0f 90       	pop	r0
 10e:	1f 90       	pop	r1
 110:	18 95       	reti

00000112 <_exit>:
 112:	f8 94       	cli

00000114 <__stop_program>:
 114:	ff cf       	rjmp	.-2      	; 0x114 <__stop_program>
Ответить

Вернуться в «AVR»