2017-10-12 11 views
0

Je tente d'implémenter l'UART semi-duplex avec un ATTiny841. L'idée du code est que lorsque je transmets autre chose que le caractère «d», je ne reçois rien de nouveau et quand je transmets le «d», je récupère cette lettre. Après avoir testé cela, avec différents caractères, je reçois toujours la même lettre que j'ai transmise. L'un des problèmes majeurs auxquels je suis confronté ici est dans USART0_RX_vect. Pour une raison quelconque, l'instruction if ne semble pas fonctionner. Des suggestions sur ce que je pourrais faire pour résoudre ce problème?Erreur d'interruption du récepteur semi-duplex AVR

#include <avr/io.h> 
#include <avr/interrupt.h> 

class CommsController { 
public: 
    uint8_t data; 
    bool bjsonComplete; 

    CommsController(uint8_t ubrr) { 
     UCSR0B |= (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0); // Enable Rx and Rx Complete Interrupt. 
     UBRR0H = (ubrr>>8); 
     UBRR0L = ubrr; 
     // Select 8-bit data frame, single stop bit and no parity using UCSR0C (Default values are what we want). 

     this->bjsonComplete = false; 
    } 

    void transmit(unsigned char data) { 
     UCSR0B &= ~(1<<RXEN0) & ~(1<<RXCIE0); // disable Rx and interrupt. 
     /* Wait for empty transmit buffer */ 
     while (!(UCSR0A & (1<<UDRE0))) 
     ; 
     /* Put data into buffer, sends the data */ 
     UDR0 = data; 
     while (!(UCSR0A & (1<<UDRE0) & (1<<TXC0))) {}; // Wait for empty transmit buffer. 
     UCSR0B |= (1<<RXEN0)|(1<<RXCIE0); // Re-enable Rx and interrupt. 
    } 
}; 


volatile uint8_t data = 0; 

CommsController* commsController; 

ISR(USART0_RX_vect) { 
    data = UDR0; 
    if(data == 'd') { 
     commsController->data = data; 
     commsController->bjsonComplete = true; 
    } 
} 

/* Replace with your library code */ 
int main(void) 
{ 
    cli(); 
    CommsController c(51); 
    commsController = &c; 
    sei(); 

    while(1) { 
     if(commsController->bjsonComplete) { 
      commsController->transmit(commsController->data); 
     } 
    } 

    return 0; 
} 
+0

Êtes-vous sûr que ce soit un exemple complet pour reproduire le comportement? Les données de commsController-> ne devraient jamais contenir autre chose que 'd' sauf initialement. Ce que j'ai remarqué est que vous devriez probablement remettre commsController-> bjsonComplete à false après que vous ayez transmis? –

+0

ouais c'était parmi l'un des problèmes avec ce code. J'ai découvert que c'était en fait parce que je n'ai pas déclaré le commsController volatile. Je posterai le code de travail complet ci-dessous pour toute personne confrontée à des problèmes similaires. – Hydroflax

Répondre

0
#define F_CPU 8000000UL 

#include <avr/io.h> 
#include <avr/interrupt.h> 
#include <avr/delay.h> 

class CommsController { 
public: 
    volatile uint8_t data; 
    volatile bool bjsonComplete; 

    CommsController(uint8_t ubrr) { 
     UCSR0B |= (1<<RXEN0)|(1<<RXCIE0); // Enable Rx and Rx Complete Interrupt. 
     UBRR0H = (ubrr>>8); 
     UBRR0L = ubrr; 
     // Select 8-bit data frame, single stop bit and no parity using UCSR0C (Default values are what we want). 

     this->bjsonComplete = false; 
     this->data = 0; 
    } 

    void transmit(unsigned char data) volatile { 
     UCSR0B &= ~(1<<RXCIE0); // disable Rx interrupt. 
     /* Wait for empty transmit buffer */ 
     while (!(UCSR0A & (1<<UDRE0))); 

     /* Put data into buffer, sends the data */ 
     UDR0 = data; 
     while (!(UCSR0A & (1<<TXC0))); // Wait for empty transmit buffer. 
     UCSR0B |= (1<<RXCIE0); // Re-enable Rx interrupt. 
    } 
}; 

volatile CommsController c(51); 

ISR(USART0_RX_vect) { 
    c.data = UDR0; 
} 

/* Replace with your library code */ 
int main(void) 
{ 
    cli(); 
    sei(); 
    DDRB |= (1<<PORTB1); 
    PORTB &= ~(1<<PORTB1); 

    while(1) { 
     if(c.data == 'd') { 
      c.transmit('f'); 
      c.data = 0; 
     } 
    } 

    return 0; 
}