Czy istnieje sposób, aby nie musieć sondować UART AVR?

10

Otrzymuję dane przez UART z innego AVR. Jednak robię inne rzeczy, więc nie chcę ciągle sprawdzać UART. Wiem, że są przerwania, ale widzę tylko jedno z otrzymanych zakończeń, które, jak zakładam, nadal wymaga ode mnie sondowania, aby dokończyć przesyłanie.

Adam Makin
źródło
1
Dlaczego musisz sondować, aby zainicjować transfer? W każdym razie istnieją również przerwy w zakończeniu transmisji. Nie przepadam za AVR, ale można je nazwać „TX pustym”, „FIFO pustym” lub progiem FIFO ”lub podobnym.
Eugene Sh.

Odpowiedzi:

20

Istnieją wektory przerwań zarówno dla RXC, jak i TXC (kompletne RX i TX) na AVR. Nigdy nie powinieneś sondować tych, chyba że chcesz.

AVRFreaks ma fajny post na ten temat, podobnie jak producent .

evildemonic
źródło
3
Miałem zamiar powiedzieć „dlaczego link AppNote wskazuje na Microchip, to produkt Atmel!” Nie mogę uwierzyć, że nigdy nie słyszałem, że Microchip kupił
Atmela, odsuwasz
2
@ZacFaragher NXP + Freescale + Qualcomm. Analogowe + LT. ON + Fairchild. Infineon + IR. Wszystko to w ciągu ostatnich 1-2 lat. Znajdź swojego najgorszego / jedynego konkurenta, a następnie połącz się z nim.
Lundin
1
@Lundin Qualcomm NXP się nie wydarzyło i nie wydaje się, aby był już przedmiotem publicznej uwagi. Mógł nadal, a może coś innego - w końcu był czas, kiedy to Dialog miał kupić Atmela.
Chris Stratton
2

Procedura przerwania przechowuje dane w buforze (bufor okrągły z wskaźnikami put i get działa dobrze). Pętla główna sprawdza, czy w buforze są dane, a kiedy są, usuwa je. Główna pętla może robić inne rzeczy, ale musi sprawdzić i usunąć dane, zanim przepełni się bufor przerwań (kiedy put spotka się z get).

Nie można go skompilować, ale ilustruje to metodę.

char circ_buf[BUFFER_SIZE];
int get_index, put_index;

void initialize(void) {
    get_index = 0;
    put_index = 0;
}

isr serial_port_interrupt(void) {                       // interrupt
    circ_buf[put_index++] = SERIAL_PORT_REGISTER;
    if(put_index==get_index) error("buffer overflow");  // oops
    if(put_index==BUFFER_SIZE) put_index = 0;           // circular buffer
}

void background routine(void) {
    while(put_index!=get_index) {                       // or if()
        ch = circ_buf[get_index++];
        // do something with ch
        if(get_index==BUFFER_SIZE) get_index = 0;
        }
}
Królikarnia
źródło