4

このプログラムでは、タイマー割り込みを使用してLEDを循環しています。誰かがスイッチを押すと、最初の割り込みを停止し、押されたスイッチに応じてLEDを点灯させる2番目の割り込みをトリガーする必要があります。ここで、どの割り込みが呼び出されているか少し混乱しています。ピン変更割り込みについていくつかの本を参照し、PCMSK2を設定するための数行を書きました。取得している出力は、「スイッチが押されると、最初はすべてのLEDが循環しています... LEDの循環が停止して最初からやり直します(つまり、プログラムが入力を読み取っており、2番目の割り込みをトリガーしていません)。停止しません。または一時停止して、後続のLEDが点灯しません。」誰か助けてもらえますか?

#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)
    {

    }
}

たくさんのご支援ありがとうございます。

4

2 に答える 2

5

AVRアーキテクチャの外部割り込みは混乱を招きますが、不可能ではありません。私にとって最良のリソースは、割り込みに関するAVRlibcページであることがわかりました。コードを複雑にしすぎて、やりたいことができなくなったと思います。ゼロから始めましょう:

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

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

AVR libcは、実際には処理割り込みを非常に簡単にします。上記にリンクしたページには、各AVRチップでサポートされているすべての割り込みベクトルのリストがあります。Mega32を使用していて、タイマー割り込みを使用してLEDを点滅させたいとします。プログラムに追加しましょう:

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これにより、タイマー割り込みが発生するたびにLEDが点滅します。ISR(...)設定方法はマクロを使用することであることに注意してください。使用している__vector_...通話は廃止され、もう少し混乱します。

最後に、質問を正しく理解していれば、一連のスイッチを使用してLEDを点灯させたままにします。私は実際にはこれに外部割り込みを使用せず、PINKISR(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の両方の遷移で発生するように設定されていると思います)。あとは、LED出力をの値に依存させるだけですswitch_state。これまでLEDを切り替えてきたので、タイマー割り込みでこれを行います。新しいバージョンは次のようになります。

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

そしてそれはそれをするべきです!

脚注:スイッチの読み取りに外部割り込みを使用する必要はないことを先に述べました。これは、を使用してタイマー割り込み中にスイッチ値を読み取ることができるためですPINKswitch_state、、setup_switch_interrupt()ISR(INT0_vect)削除して、タイマー割り込みを次のように変更することができます。

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

これで、プログラムが少し簡単になります。

于 2011-02-01T14:10:08.390 に答える
0

したがって、何があっても、__vector_23実行するたびにPORTB、増分によって割り当てられたLEDを循環しますi。あなたがやろうとしていることを私が理解しているなら、あなたがすべきことは、スイッチが押されたとき、でiのみインクリメントすることです。__vector_25

于 2010-11-10T00:17:36.637 に答える