¿Hay alguna manera de no tener que sondear el UART de un AVR?

10

Estoy recibiendo datos a través de UART de otro AVR. Sin embargo, estoy haciendo otras cosas, así que no quiero tener que sondear constantemente el UART. Sé que hay interrupciones, pero solo puedo ver una para recibir completa, lo que supongo que todavía requiere que haga una encuesta para completar la transferencia.

Adam Makin
fuente
1
¿Por qué necesitaría sondear para iniciar una transferencia? De todos modos, también hay interrupciones para completar la transmisión. No estoy muy interesado en AVR, pero estos se pueden llamar "TX vacío" o "FIFO vacío" o umbral FIFO "o similar.
Eugene Sh.

Respuestas:

20

Hay vectores de interrupción para RXC y TXC (RX y TX completos) en los AVR. Nunca debería tener que sondearlos a menos que lo desee.

AVRFreaks tiene una buena publicación sobre esto, y también el fabricante .

evildemonic
fuente
3
Iba a ser todo "¿por qué el enlace de AppNote apunta a Microchip, es un producto Atmel!" No puedo creer que nunca escuché que Microchip compró Atmel, te alejas de los microcontroladores durante 5 años ...
Zac Faragher
2
@ZacFaragher NXP + Freescale + Qualcomm. Analógico + LT. ON + Fairchild. Infineon + IR. Todo esto en los últimos 1-2 años. Encuentra tu peor / único competidor y luego únete a ellos, más o menos.
Lundin
1
@Lundin Qualcomm NXP no ha sucedido, y ya no parece estar bajo consideración pública activa . Todavía podría, o algo más podría, después de todo hubo un momento en que fue Dialog quien iba a comprar Atmel.
Chris Stratton
2

La rutina de interrupción almacena los datos en un búfer (un búfer circular con punteros put y get funciona muy bien). El bucle principal verifica si hay datos en el búfer y, cuando los hay, los saca. El bucle principal puede hacer otras cosas, pero necesita verificar y eliminar los datos antes de que se desborde el búfer de interrupción (cuando el put se encuentra con el get).

No se compilará, pero esto ilustra el método.

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;
        }
}
Madriguera
fuente