Bir AVR'nin UART'ını yoklamak zorunda kalmanın bir yolu var mı?


10

Başka bir AVR'dan UART üzerinden veri alıyorum. Ancak başka şeyler yapıyorum, bu yüzden sürekli olarak UART'ı sorgulamaya devam etmek istemiyorum. Kesinti olduğunu biliyorum ama sadece tam bir tane almak için görebiliyorum, ki hala transfer işlemini tamamlamak için anket yapmam gerekiyor.


1
Transfer başlatmak için neden anket yapmanız gerekiyor? Her neyse, iletimin tamamlanması için de kesintiler var. . Benzer "TX boşaltmak" veya "FIFO boş" ya da FIFO eşik" veya çok AVR içine değilim ama bu çağrılabilir
. Eugene Sh

Yanıtlar:


20

AVR'lerde hem RXC hem de TXC (RX ve TX tamamlandı) için kesme vektörleri vardır. İstemediğiniz sürece bunlar için asla anket yapmamalısınız.

AVRFreaks'ın bu konuda güzel bir yazısı var ve üretici de öyle .


3
Ben hepim "AppNote bağlantısı neden Microchip'i gösteriyor, bu bir Atmel ürünü!" Microchip'in Atmel'i satın aldığını hiç duymadığımı düşünemiyorum, 5 yıl boyunca mikrodenetleyicilerden uzaklaşıyorsun ...
Zac Faragher

2
@ZacFaragher NXP + Freescale + Qualcomm. Analog + LT. AÇIK + Fairchild. Infineon + IR. Bütün bunlar son 1-2 yıl içinde. En kötü / sadece rakibinizi bulun ve onlarla birleştirin, hemen hemen.
Lundin

1
@Lundin Qualcomm NXP gerçekleşmedi ve artık aktif kamuoyu altında görünmüyor . Hala ya da başka bir şey olabilirdi - her şeyden sonra Dialog'un Atmel'i satın alacağı bir zaman vardı.
Chris Stratton

2

Kesme rutini verileri bir tamponda saklar (koy ve al işaretçileri olan dairesel bir tampon güzel çalışır). Ana döngü, arabellekte veri olup olmadığını kontrol eder ve varsa onu çıkarır. Ana döngü başka şeyler yapabilir, ancak kesme arabelleği taşmadan önce verileri kontrol etmeli ve kaldırmalıdır (put, get ile buluştuğunda).

Derlenmeyecektir, ancak bu yöntemi göstermektedir.

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;
        }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.