2010-11-09 3 views
4

Здесь, в программе, я прокручиваю светодиоды с использованием прерывания таймера &, если кто-то нажимает переключатель, он должен остановить первый прерыватель &, который должен зажечь второй, который должен загореться светодиодом в соответствии с переключателем нажат. Здесь я немного запутался, какое прерывание вызывает. Я упомянул несколько книг для прерывания смены контактов. & написал несколько строк для установки PCMSK2. Выходной сигнал am начинается: «Сначала все светодиоды циклически переключаются, когда нажат переключатель ... циклическое перемещение светодиодов & начинается снова (это означает, что программа считывает ввод, просто не вызывая второе прерывание). или пауза & не загорается последующим светодиодом. " Может ли кто-нибудь помочь, пожалуйста?Прерывание смены выводов - внешнее прерывание с внутренним прерыванием

#include <avr/io.h> 
#include <avr/interrupt.h> 
#define PINK_MASK \ 
    ((1<<PINK0)|(1<<PINK1)|(1<<PINK2)|(1<<PINK3)|(1<<PINK4)|(1<<PINK5)|(1<<PINK6)|(1<<PINK7)) 


volatile unsigned int intrs, i=1; 

void enable_ports(void); 
void delay(void); 

extern void __vector_23 (void) __attribute__ ((interrupt)); 

extern void __vector_25 (void) __attribute__ ((signal)); 

void enable_ports() 
{ 
    DDRB = 0xff; //PORTB as output for leds 

    PORTB = 0xff; 

    DDRK = 0x00; //PORTK as input from switches 

    PORTK |= PINK_MASK; 

    PCMSK2 = PINK_MASK;  //ENABLE PCMSK2, Setting interrupts 

    PCICR = 0x04; 

    PCIFR = 0x04; 

    TCCR0B = 0x03;  //Setting TIMER 

    TIMSK0 = 0x01; 

    TCNT0 = 0x00; 

    intrs = 0; 
} 
void __vector_23 (void) 
{ 
    intrs++; 
    if(intrs > 60) 
    { 
     intrs = 0; 
     PORTB = (0xff<<i); 

     i++ ; 
     if(i == 10) 
     { 
      PORTB = 0xff; 
      i = 1 ; 
     } 
    } 
} 

void __vector_25 (void) 
{ 
    unsigned char switches; 

    switches = ((~PINK) & (PINK_MASK)); //Reading from switches 

    if(switches & (1<<PINK0)) 
     PORTB = (PORTB<<PINK0); 

    else if (switches & (1<<PINK1)) 
     PORTB = (PORTB<<PINK1); 

    else if (switches & (1<<PINK2)) 
     PORTB = (PORTB<<PINK2); 

    else if (switches & (1<<PINK3)) 
     PORTB = (PORTB<<PINK3); 

    else if (switches & (1<<PINK4)) 
     PORTB = (PORTB<<PINK4); 

    else if (switches & (1<<PINK5)) 
     PORTB = (PORTB<<PINK5); 

    else if (switches & (1<<PINK6)) 
     PORTB = (PORTB<<PINK6); 

    else if (switches & (1<<PINK7)) 
     PORTB = (PORTB<<PINK7); 
} 

int main(void) 
{ 
    enable_ports(); 
    sei(); 

    while(1) 
    { 

    } 
} 

Спасибо за вашу поддержку.

+0

Кто-нибудь, пожалуйста, помогите! – sneezy

+0

Извините, я не использую Atmel μCs. Но, может быть, вы могли бы спросить на http://embdev.net/ – AndreKR

+1

Какое конкретное устройство вы планируете? – evilspacepirate

ответ

5

Внешние прерывания в архитектуре AVR сбивают с толку, но не невозможны. Я нашел лучший ресурс для меня был AVR libc page on interrupts. Я думаю, что вы сделали код слишком сложным для того, что вы хотите. Начнем с нуля:

#include <avr/io.h> 
#include <stdint.h> 
#include <avr/interrupt.h> 

void main() { 
    sei(); 
    while(1) {}; 
} 

AVR libc фактически делает обработку прерываний довольно безболезненной. На странице, с которой я связан выше, есть список всех поддерживаемых векторов прерываний на каждом чипе AVR. Предположим, вы используете Mega32, и теперь вы хотите, чтобы светодиоды мигали, используя прерывание таймера. Давайте добавим к программе:

uint8_t led_state; 

ISR(TIMER0_COMP_vect) { 
    led_state = ~led_state; 
    PORTB = led_state; 
} 

void setup_timer_interrupt() { 
    TCCR0B = 0x03; 
    TIMSK0 = 0x01; 
    TCNT0 = 0x00; 
} 

Это должно мигать светодиоды на PORTB каждый раз, когда происходит прерывание от таймера. Обратите внимание, что способ, которым он должен быть настроен, - использовать макрос ISR(...); звонки __vector_..., которые вы используете, устарели и немного более запутанны.

Наконец, вы хотите использовать набор переключателей для удержания светодиода, если я правильно понял ваш вопрос. На самом деле я бы не использовал внешнее прерывание для этого, просто прочитайте значение переключателей, используя PINK во время ISR(TIMER0_COMP_vect), но мы можем использовать его, если хотите. Нам нужно будет добавить следующий код:

uint8_t switch_state; 

void setup_switch_interrupt() { 
    // I'm assuming this code to enable external interrupts works. 
    DDRK = 0x00; 
    PORTK = 0xff; 
    PCMSK2 = 0xff; // set to all 1s 
    PCICR = 0x04; 
    PCIFR = 0x04; 
} 

ISR(INT0_vect) { 
    switch_state = PINK; 
} 

Что это значит? Мы будем держать состояние переключателей в switch_state, каждый раз, когда срабатывает внешнее прерывание (я предполагаю, что этот набор будет выполняться на обоих переходах 0-> 1 и 1-> 0). Все, что осталось, - сделать светодиодный выход зависимым от значения switch_state. Мы сделаем это в прерывании таймера, так как именно там мы переключали светодиоды. Новая версия выглядит так:

ISR(TIMER0_COMP_vect) { 
    led_state = ~led_state | switch_state; 
    PORTB = led_state; 
} 

И это должно быть сделано!

Сноска: Я сказал ранее, что использование внешнего прерывания для считывания коммутаторов действительно не требуется. Это связано с тем, что вы можете просто прочитать значения переключателя во время прерывания таймера с помощью PINK.Вы можете избавиться от switch_state, setup_switch_interrupt() и ISR(INT0_vect) и просто изменить прерывание таймера таким:

ISR(TIMER0_COMP_vect) { 
    led_state = ~led_state | PINK; 
    PORTB = led_state; 
} 

Это должно сделать программу немного проще.

0

Так что независимо от того, каждый раз, когда ваш __vector_23 выполняет велопереключение по светодиодам, назначенным на PORTB, увеличивая i. Если я понимаю, что вы пытаетесь сделать, что вы должны делать, это приращение i только в __vector_25, когда переключатель нажат.

+0

ТАК, что я пишу вместо этого? – sneezy

+0

@sneezy, я думаю, что я ошибся, когда я впервые ответил, пожалуйста, посмотрите мое редактирование с некоторыми лучшими инструкциями. –

+0

Я не вижу, чтобы __vector_25 получил вызов. – sneezy

Смежные вопросы