Xác định chân nào kích hoạt ngắt PCINTn?


9

Tôi có đúng không khi nghĩ rằng nếu bạn có hai chân gây ra cùng một ngắt PC PCINT, (ví dụ: vectơ PCINT0 gây ra bởi các chân PCINT0 hoặc PCINT1 - Tôi nghĩ rằng việc đặt tên cho các vectơ và chân là khó hiểu) là cách duy nhất để xác định chân nào (s) gây ra ngắt là ghi lại trạng thái của chúng sau mỗi lần ngắt và so sánh giá trị hiện tại và trước đó của tất cả các chân được bật trong PCMSKn?


1
Đã được một thời gian kể từ khi tôi sử dụng một AVR, nhưng tôi chắc chắn phải có một cờ được kích hoạt cho đúng pin. Cờ này sẽ xóa sau khi xảy ra gián đoạn, do đó bạn không cần lưu trữ trạng thái. Thực tế là cờ được đặt là đủ
Gustavo Litovsky

@ gl3829 các cờ là trên mỗi nhóm ghim nếu tôi hiểu chính xác
Tom Davies

Câu trả lời:


11

Tôi nghĩ rằng sự trùng lặp đặt tên của vectơ và chân là khó hiểu

Nó là!

Lý do có 8 chân ngoài khác nhau cho một vectơ ngắt là để giúp bố trí PCB dễ dàng hơn hoặc sử dụng một chân khác nếu có xung đột với chức năng ghim khác.

Tôi có đúng không khi nghĩ ... cách duy nhất để xác định (các) pin nào gây ra ngắt là ghi lại trạng thái của chúng sau mỗi lần ngắt và so sánh giá trị hiện tại và trước đó của tất cả các chân được bật trong PCMSKn?

Khá nhiều, giả sử bạn chỉ quan tâm đến PB0 (PCINT0) và PB1 (PCINT1). Vì vậy, thay đổi pin cho phép mặt nạ PCMSK0 sẽ được đặt thành 0x03.

// External Interrupt Setup
...

volatile u_int8 previousPins = 0; 
volatile u_int8 pins = 0; 

ISR(SIG_PIN_CHANGE0)
{
    previousPins = pins; // Save the previous state so you can tell what changed
    pins = (PINB & 0x03); // set pins to the value of PB0 and PB1
    ...
}

Vì vậy, nếu pinslà 0x01, bạn biết đó là PB0 ... Và nếu bạn cần biết những gì đã thay đổi, bạn cần so sánh nó với previousPins, chính xác như những gì bạn nghĩ.

Hãy ghi nhớ trong một số trường hợp, pinscó thể không chính xác nếu pin có trạng thái thay đổi kể từ khi ngắt nhưng trước đó pins = (PINB & 0x03).

Một tùy chọn khác là sử dụng các vectơ ngắt riêng biệt với một chân từ mỗi vectơ để bạn biết cái nào được thay đổi. Một lần nữa, điều này cũng có một số vấn đề, như ưu tiên ngắt và khi CPU đi vào ISR, toàn cầu gián đoạn cho phép chút I-bittrong SREGsẽ bị xóa để tất cả các ngắt khác bị vô hiệu hóa, mặc dù bạn có thể đặt nó bên trong ngắt nếu bạn muốn, mà có thể là một ngắt lồng nhau.

Để biết thêm thông tin, hãy xem ghi chú ứng dụng của Atmel bằng cách sử dụng Ngắt bên ngoài cho các thiết bị megaAVR.

Cập nhật

Đây là một ví dụ mã hoàn chỉnh tôi vừa tìm thấy ở đây .

#include <avr/io.h>
#include <stdint.h>            // has to be added to use uint8_t
#include <avr/interrupt.h>    // Needed to use interrupts
volatile uint8_t portbhistory = 0xFF;     // default is high because the pull-up

int main(void)
{
    DDRB &= ~((1 << DDB0) | (1 << DDB1) | (1 << DDB2)); // Clear the PB0, PB1, PB2 pin
    // PB0,PB1,PB2 (PCINT0, PCINT1, PCINT2 pin) are now inputs

    PORTB |= ((1 << PORTB0) | (1 << PORTB1) | (1 << PORTB2)); // turn On the Pull-up
    // PB0, PB1 and PB2 are now inputs with pull-up enabled

    PCICR |= (1 << PCIE0);     // set PCIE0 to enable PCMSK0 scan
    PCMSK0 |= (1 << PCINT0);   // set PCINT0 to trigger an interrupt on state change 

    sei();                     // turn on interrupts

    while(1)
    {
    /*main program loop here */
    }
}

ISR (PCINT0_vect)
{
    uint8_t changedbits;

    changedbits = PINB ^ portbhistory;
    portbhistory = PINB;

    if(changedbits & (1 << PB0))
    {
    /* PCINT0 changed */
    }

    if(changedbits & (1 << PB1))
    {
    /* PCINT1 changed */
    }

    if(changedbits & (1 << PB2))
    {
    /* PCINT2 changed */
    }
}

Mega có ba ngắt thay đổi pin, với vectơ PCINT [0-2], nhưng mỗi cái được kích hoạt bởi một bộ chân. Câu hỏi của tôi là về cách phân biệt chân nào trong bộ đó gây ra ngắt.
Tom Davies

@TomDavies bạn đúng, cảm ơn, tôi đã thay đổi câu trả lời của tôi tuy nhiên đó chính xác là những gì bạn nghĩ. Và tôi đọc qua bảng dữ liệu, không có cờ nào cho biết pin nào đã thay đổi.
Garrett Fogerlie

@ Garret: Bạn có nhận ra rằng trong ví dụ ban đầu của mình, người ta có thể dễ dàng xác định xem đó là điểm rơi hay cạnh tăng đã kích hoạt ngắt? (tốt, trừ khi cả hai chân thay đổi cùng một lúc ... nhưng trong trường hợp này chỉ có phép màu đen giúp) (trước_ chân> chân): cạnh rơi (chân trước <chân): cạnh tăng Có lẽ điều này đáng được đề cập ở trên.

@TomDavies PINB bao gồm PCINT0-7, PINC bao gồm PCINT8-15, v.v.
EkriirkE 15/1/2015

0

Trên thanh ghi sê-ri ATTINY mới hơn INTFLAGSsẽ cho bạn biết bit cổng nào đã gây ra ngắt.

Đây là đoạn trích từ bảng dữ liệu:

Bits 7: 0 - INT [7: 0]: Cờ ghim ngắt Cờ INT được đặt khi thay đổi / trạng thái pin khớp với cấu hình cảm giác đầu vào của pin. Viết '1' vào vị trí bit của cờ sẽ xóa cờ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.