Код пишется в Atmel studio. Плата Arduino UNO c ATMega328P-PU. Заливаю hex файл через XLoader v1.00. Есть две проблемы. Первая: Прерывание по PCIE0:2 Код (Text): .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 Код (Text): .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, если я напишу так: Код (Text): rjmp init ; Reset Handler reti ; IRQ0 Handler rjmp irq0 ; IRQ1 Handler reti ; PCINT0 Handler rjmp irq1 ; PCINT1 Handler reti ; PCINT2 Handler Я совсем ничего не понимаю, тк в даташите по другому расписана таблица прерываний.
Проблема решена. Оказалось, что есть опечатка в datasheet. По данному коду, можно видеть, что на каждое прерывание у меня есть по два байта. Код (Text): 0x0000 jmp RESET ; Reset Handler 0x0002 jmp EXT_INT0 ; IRQ0 Handler 0x0004 jmp EXT_INT1 ; IRQ1 Handler 0x0006 jmp PCINT0 ; PCINT0 Handler Только вот команда jmp занимает не 2, а 4 байта. В своей программе я использовал rjmp, который занимает 2 байта и как результат у меня вызывались не те прерывания, что должны были. Те выходит, что на самом деле таблица прерываний для моего мк будет выглядеть так. Код (Text): 0x0000 jmp RESET ; Reset Handler 0x0004 jmp EXT_INT0 ; IRQ0 Handler 0x0008 jmp EXT_INT1 ; IRQ1 Handler 0x000В jmp PCINT0 ; PCINT0 Handler
Узнал еще одну вещь, спасибо AlexPM с easyelectronics.ru Так что это от не знания, а не ошибка в datasheet http://forum.easyelectronics.ru/viewtopic.php?f=4&t=17994&p=320176#p320176
Для того что бы лучше понимать, как оно все работает. Это поможет тебе исправить непонятные баги. Они могут быть вызваны компилятором к примеру, вроде в С коде все написано нормально, а прога почему-то не работает как надо. Или к примеру к трудоемком участке кода, написать все через асм и получить хороший такой буст. Вот прочти статью DI HALT о бесполезности знания асма, человек не знающий асм такую проблему не найдет и не решит. http://easyelectronics.ru/avr-uchebnyj-kurs-programmirovanie-na-si-atomarnye-operacii.html
DI HALT так никогда не считал.Если программа крохотная типа помигать светодиодом или даже работа с USART то асм если большая и сложная то однозначно Си