代码之家  ›  专栏  ›  技术社区  ›  danieljimeneznz

AVR半双工接收器中断错误

  •  0
  • danieljimeneznz  · 技术社区  · 7 年前

    我试图用ATTiny841实现半双工UART。代码的思想是,当我传输除字符“d”以外的任何内容时,我什么也没有收到,而当我传输“d”时,我得到了那封信。经过测试,使用不同的字符,我总是收到我发送的同一封信。我在这里面临的主要问题之一是USART0\U RX\U vect。由于某些原因,if语句似乎不起作用。有什么建议可以帮我解决这个问题吗?

    #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;
    }
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   danieljimeneznz    5 年前

    我后来发现,问题实际上是因为我没有声明commsController为volatile。我将在下面为面临类似问题的任何人发布完整的工作代码:

    #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;
    }