Задать вопрос
@Ramirag
Я человек.

Как решить проблему с прерываниями на ATMega328P-PU?

Код пишется в Atmel studio. Плата Arduino UNO c ATMega328P-PU. Заливаю hex файл через XLoader v1.00. Есть две проблемы.
Первая: Прерывание по PCIE0:2
.cseg
		.org	0

		rjmp	init	; Reset Handler
		reti			; IRQ0 Handler
		reti			; IRQ1 Handler
		rjmp	pci0	; PCINT0 Handler
		rjmp	pci1	; PCINT1 Handler
		rjmp	pci2	; PCINT2 Handler
		reti			; Watchdog Timer Handler
		reti			; Timer2 Compare A Handler
		reti			; Timer2 Compare B Handler
		reti			; Timer2 Overflow Handler
		reti			; Timer1 Capture Handler
		reti			; Timer1 Compare A Handler
		reti			; Timer1 Compare B Handler
		reti			; Timer1 Overflow Handler
		reti			; Timer0 Compare A Handler
		reti			; Timer0 Compare B Handler
		reti			; Timer0 Overflow Handler
		reti			; SPI Transfer Complete Handler
		reti			; USART, RX Complete Handler
		reti			; USART, UDR Empty Handler
		reti			; USART, TX Complete Handler
		reti			; ADC Conversion Complete Handler
		reti			; EEPROM Ready Handler
		reti			; Analog Comparator Handler
		reti			; 2-wire Serial Interface Handler
		reti			; Store Program Memory Ready Handler

;-------------------------- Инициализация стека

init:	ldi		r31, 0x8
		ldi		r30, 0xFF

		out		SPL, r30
		out		SPH, r31

;-------------------------- Активация прерываний

		ldi		r16, 1 << PCIE2 | 1 << PCIE1 | 1 << PCIE0
		sts		PCICR, r16

		ldi		r16, 1 << PCINT0
		sts		PCMSK0, r16

		ldi		r16, 1 << PCINT8
		sts		PCMSK1, r16

		ldi		r16, 1 << PCINT16
		sts		PCMSK2, r16

;-------------------------- Инициализация портов ВВ

		ldi		r16, 0b11111110
		out		DDRB, r16
		out		DDRC, r16
		out		DDRD, r16

		ldi		r16, 0b11111111
		out		PORTB, r16
		out		PORTC, r16
		out		PORTD, r16

		ldi		r16, 0b00000001

		sei
main:
		rjmp	main

pci0:	out		PORTB, r16
		reti

pci1:	out		PORTC, r16
		reti

pci2:	out		PORTD, r16
		reti

Регистры DDRB0, DDRC0, DDRD0 настроены на ввод, а так-же на генерацию прерывания при изменении сигнала. Все остальные на вывод.
Прерывание должно менять выходное значение на порту и зажигать диоды, но оно не происходит.
Вторая: Прерывание по INT0:1
;------------------------- Начало программного кода

		.cseg 	
		.org	0	

		rjmp	init	; Reset Handler
		rjmp	irq0	; IRQ0 Handler
		rjmp	irq1	; IRQ1 Handler
		reti			; PCINT0 Handler
		reti			; PCINT1 Handler
		reti			; PCINT2 Handler
		reti			; Watchdog Timer Handler
		reti			; Timer2 Compare A Handler
		reti			; Timer2 Compare B Handler
		reti			; Timer2 Overflow Handler
		reti			; Timer1 Capture Handler
		reti			; Timer1 Compare A Handler
		reti			; Timer1 Compare B Handler
		reti			; Timer1 Overflow Handler
		reti			; Timer0 Compare A Handler
		reti			; Timer0 Compare B Handler
		reti			; Timer0 Overflow Handler
		reti			; SPI Transfer Complete Handler
		reti			; USART, RX Complete Handler
		reti			; USART, UDR Empty Handler
		reti			; USART, TX Complete Handler
		reti			; ADC Conversion Complete Handler
		reti			; EEPROM Ready Handler
		reti			; Analog Comparator Handler
		reti			; 2-wire Serial Interface Handler
		reti			; Store Program Memory Ready Handler

;-------------------------- Инициализация стека

init:	ldi		r31, 0x8
		ldi		r30, 0xFF

		out		SPL, r30
		out		SPH, r31

;-------------------------- Активация прерываний

		ldi		r16, 1 << INT1 | 1 << INT0
		out		EIMSK, r16

		ldi		r16, 0 << ISC11 | 0 << ISC10 | 0 << ISC01 | 0 << ISC00
		sts		EICRA, r16

;-------------------------- Инициализация портов ВВ

		ldi		r16, 0b11110011
		out		DDRB, r16
		out		DDRD, r16

		ldi		r16, 0b11111111
		out		PORTB, r16
		out		PORTD, r16

		sei
main:
		rjmp	main

irq0:	ldi		r16, 0b11111110
		out		PORTB, r16
		reti

irq1:	ldi		r17, 0b11111101
		out		PORTB, r17
		reti

Регистры DDRD2:3 настроены на ввод, а так-же на генерацию прерывания при низком уровне. DDRB0:1 на вывод.
Прерывание по INT0 у меня вызывает не irq0, а irq1.
Дальше методом тыка я узнал, что INT1 у меня вызовет irq0, если я напишу так:
rjmp	init	; Reset Handler
		reti			; IRQ0 Handler
		rjmp	irq0	; IRQ1 Handler
		reti			; PCINT0 Handler
		rjmp	irq1	; PCINT1 Handler
		reti			; PCINT2 Handler

Я совсем ничего не понимаю, тк в даташите по другому написано.
  • Вопрос задан
  • 4557 просмотров
Подписаться 2 Оценить 2 комментария
Решения вопроса 1
@vanyamba-electronics
В даташите очепятка про таблицу векторов. RJMP -это relative jmp, он занимает 2 байта. Нужно использовать JMP, который занимает 4 байта. По четыре байта на каждый вектор.
Button_1_LED.cpp.elf:     формат файла elf32-avr

Дизассемблирование раздела .text:

00000000 <__vectors>:
   0:   0c 94 63 00     jmp     0xc6    ; 0xc6 <__ctors_end>
   4:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
   8:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
   c:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  10:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  14:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  18:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  1c:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  20:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  24:   0c 94 c3 00     jmp     0x186   ; 0x186 <__vector_9>
  28:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  2c:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  30:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  34:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  38:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  3c:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  40:   0c 94 5c 04     jmp     0x8b8   ; 0x8b8 <__vector_16>
  44:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  48:   0c 94 09 03     jmp     0x612   ; 0x612 <__vector_18>
  4c:   0c 94 50 03     jmp     0x6a0   ; 0x6a0 <__vector_19>
  50:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  54:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  58:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  5c:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  60:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>
  64:   0c 94 8b 00     jmp     0x116   ; 0x116 <__bad_interrupt>

00000116 <__bad_interrupt>:
  116:   0c 94 00 00   jmp      0           ; 0x0 <__vectors>
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы