Шаблон обработки прерывания от int0 для AtTiny2313

Вот простой и наглядный пример обработки прерывания int0 для микроконтроллера ATtiny2313, на прерывание int0 можно установить кнопку или например датчик с выходным напряжением до 5Вольт. Я в основном использую внешние прерывания int0 и int1 для установки на них кнопок, в основном "вешаю" на них выполнение уникальных и требующих немедленного исполнения программ.

  1. #include <avr/io.h> //библиотека ввода/вывода
  2. #include <avr/interrupt.h> //библиотека прерываний
  3.  
  4. #define nop() {asm("nop");}
  5.  
  6. unsigned int ms,x; //декларирование переменных
  7.  
  8. // функция задержки
  9. void delay_ms(int ms)
  10. {
  11. for (x=ms; x>0; x--)
  12. nop (); //задержка на один такт
  13. }
  14.  
  15. //обработка прерываний
  16. SIGNAL(SIG_INTERRUPT0)
  17. {
  18. //Тут размещается текст программы
  19. //которую надо выполнить
  20. //при срабатывании прерывания INT0
  21. }
  22.  
  23. int main( void ) //главная программа
  24. {
  25. GIMSK=0b01000000; //разрешаем прерывание int0 - кнопка
  26. MCUCR=0x03; // срабатывание по нарастанию фронта - для кнопки
  27.  
  28. sei(); //глобальное разрешение прерываний
  29.  
  30. for(;;) //бесконечный цикл
  31. {
  32. //Тут размещают программу
  33. //которая выполняется/
  34. //в свободное от выполнения
  35. //обработчика прерывания
  36. }
  37. }

Скачать пример обработки прерывания int0 в txt файле

Шаблон обработки прерывания от int0 для AtTiny2313

Подскажите пожалуйста, у меня ATtiny2313A принимает и передает данные по SPI(реализован программным путем на основе USI), В главной функции вот такой код:

  1. for(;;)//бесконечный цикл
  2. {
  3. if(bit_is_clear(PIN_SPI, SS))//если выбран наш кристалл
  4. {
  5. data_r[0] = SPI_WR_S(data_w[0]); //принимаем по SPI байт данных, одновременно передавая
  6. data_w[0]=data_r[0];
  7. data_r[1] = SPI_WR_S(data_w[1]); //принимаем по SPI байт данных, одновременно передавая
  8. data_w[1]=data_r[1];
  9. }

Работает все норм.
Но я хочу переделать чтоб прием/передача происходило по внешнему прерыванию, т.е. на INT0 приходит логический ноль и после этого МК идет на обработку прерывания(прием данных). Хочу сделать через INT0 потому что будут еще задействованы прерывания INT1 и прерывание таймера, но прием данных является самым важным звеном.
Ну короче говоря настраиваю INT0:
  1. GIMSK|=(1<<INT0); //регистр маски прерываний
  2. MCUCR&=~((1<<ISC01)|(1<<ISC00)); //по нижнему уровню
  3. и обработчик прерывания:
  4. ISR(INT0_vect)
  5. {
  6. data_r[0] = SPI_WR_S(data_w[0]); //принимаем по SPI байт данных, одновременно передавая
  7. data_w[0]=data_r[0];
  8. data_r[1] = SPI_WR_S(data_w[1]); //принимаем по SPI байт данных, одновременно передавая
  9. data_w[1]=data_r[1];
  10. EIFR|=(1<<INTF0); //убираю флаг на всякий случай
  11. }

А проблема в том что почему-то первый и второй байты меняются местами и вообще как-то непонятно работатет это прерывание. У меня возник вопрос: а как долго должен продержаться низкий уровень на INT0 чтоб сработало прерывание? или может в коде настройки прерывания ошибка? может чего то недопонимаю?

а вот уй!

в обработчике меняю глобальную переменную, которую вывожу в UART. смотрю UART, замыкаю int0 на землю или на Vcc - а в уарте ничего не меняется. что я делаю не так?

правда, я сделал

  1. MCUCR=0x01;

и обработчик прерывания у меня называется
ISR(INT0_vect)

еще заодно спрошу - чем отличается

  1. GIMSK |= (1 < 6);

от
  1. GIMSK |= (1<<INT0);

Проще выложи код и сделай

Проще выложи код и сделай запись на форуме, я гляну код может что действителньо кривое написал.

По вопросам:

Отличия в записи никаких нет, так как задать конфигурацию регистра можно двумя способами с явным указанием его внутернних битов или же через указание номера бита, который отвечает за определенный, нужный тебе бит. Так что записи идентичны.

кстати, в этом шаблоне как

кстати, в этом шаблоне как минимум нету строчек, устанавливающих порт на вход.

подключил датчик холла на

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

просто в одном случае <, а в

просто в одном случае <, а в другом - <<
код в части прерываний:

  1. ISR(INT0_vect)
  2. {
  3. GIMSK &= ~(1 < 6);
  4. if (int0voltage==45) {int0voltage=43;} //меняем ASCII код + и - поочередно
  5. else {int0voltage=45;};
  6. GIMSK |= (1 < 6);
  7. }
  8.  
  9.  
  10. int main (void)
  11. {
  12. int0voltage=48; //ASCII код нуля
  13.  
  14. TIMSK=0x80; //включаем 7 бит, TOIE1: Timer/Counter1, Overflow Interrupt Enable
  15. TCCR1A=0x00;
  16. TCCR1B=0x00; //это я таймеры настраиваю - но вдруг еще и настройки прерываний меняются?
  17.  
  18. GIMSK=0b01000000; //разрешаем прерывание int0 - кнопка
  19. MCUCR=0x01; // срабатывание по изменению уровня - для кнопки
  20. // turn on interrupts!
  21. GIMSK |= (1<<INT0);
  22.  
  23. while (1)
  24. {
  25. //тут выводим в уарт с секундной задержкой соответсвующий
  26. //int0voltage символ из таблицы ASCII,
  27. //но выводится только ноль, ничего не меняется.
  28. //вывод UART проверял - рабочий
  29. //(через таб вывожу плюсом к int0voltage меняющийся символ)
  30. }

1. нету разрешения прерываний

1. нету разрешения прерываний sei();
2. Зачем в обработчки прерывания пихать настройки регистра GIMSK?

1. уже понял 2. мне кажется,

1. уже понял
2. мне кажется, там таким образом просто запрещаются прерывания