Existe uma maneira de não precisar pesquisar o UART de um AVR?

10

Estou recebendo dados pelo UART de outro AVR. No entanto, estou fazendo outras coisas, por isso não quero ter que continuar pesquisando constantemente o UART. Sei que há interrupções, mas só vejo uma para receber concluída, o que suponho que ainda exija que eu faça uma pesquisa para concluir a transferência.

Adam Makin
fonte
1
Por que você precisaria fazer uma pesquisa para iniciar uma transferência? De qualquer forma, também existem interrupções para a conclusão da transmissão. Eu não gosto muito de AVR, mas eles podem ser chamados de "TX vazio" ou "FIFO vazio" ou limite de FIFO "ou similar."
Eugene Sh.

Respostas:

20

Existem vetores de interrupção para o RXC e o TXC (RX e TX completos) nos AVRs. Você nunca deve pesquisar esses dados a menos que queira.

O AVRFreaks tem um bom post sobre isso, e o fabricante também .

evildemônico
fonte
3
Eu pensaria "por que o link do AppNote aponta para o Microchip, é um produto da Atmel!" Eu não posso acreditar que eu nunca ouvi isso Microchip comprou Atmel, você pisa longe de microcontroladores por 5 anos ...
Zac Faragher
2
@ZacFaragher NXP + Freescale + Qualcomm. Analógico + LT. ON + Fairchild. Infineon + IR. Tudo isso nos últimos 1-2 anos. Encontre o seu pior / único concorrente e, em seguida, junte-se a ele.
Lundin
1
O @Lundin Qualcomm NXP não aconteceu e não parece mais ser considerado publicamente ativo . Ainda assim, ou qualquer outra coisa, afinal, houve um tempo em que Dialog compraria a Atmel.
22819 Chris Stratton #
2

A rotina de interrupção armazena os dados em um buffer (um buffer circular com ponteiros put e get funciona bem). O loop principal verifica se há dados no buffer e, quando houver, os remove. O loop principal pode fazer outras coisas, mas precisa verificar e remover os dados antes que o buffer de interrupção transborde (quando o put se encontra com o get).

Não será compilado, mas isso ilustra o 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;
        }
}
Warren
fonte