Serielle Uart-Kommunikation kann Atmega16a nicht zurückgeben

Ich bin neu beim avr (8bit uc) und vor kurzem bin ich auf ein Problem bei der seriellen Kommunikation (uart) mit dem PC gestoßen. Der Mikrocontroller antwortet nicht im Putty-Terminal, wo er zurückgeben sollte, was ich gesendet habe.


Vielen Dank für Ihre Antwort an alle.

Es tut mir leid für den beschädigten Code. Ich hatte keine Ahnung, was ich tat, da ich Neuling in diesem Code-Einzug im Stack-Austausch bin.


Der neue Code ist unten angehängt, bitte schlagen Sie ihn freundlich vor

#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>

volatile char data;

void USARTInit(uint16_t ubrr_value) {
    UBRRL = ubrr_value;
    UBRRH = (ubrr_value >> 8);
    UCSRC = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);
    UCSRB = (1 << RXEN) | (1 << TXEN);
}

void USARTWriteChar(char data) {
    while (!(UCSRA & (1 << UDRE)))
        { }

    //Now write the data to USART buffer
    UDR = data;                                                               
}                                                                             

void main() {                                                                 
    sei();                                                                    
    UCSRB |= (1 << RXCIE);                                                    
    USARTInit(51);                                                            

    while (1) {                                                               
        if (data == 'a') {                                                    
            USARTWriteChar(data);
        }
    }
}

ISR(USARTRXC_vect) {
    data = UDR;
}

Hier stellt foo also nur meine data='a' dar, leider reagiert avr nicht auf meine Eingaben. wenn ich "a" eingebe.

Nun, Sie haben die Zeile auskommentiert, die Daten von Ihrem UART abgefragt hätte - in der Hoffnung, dass Ihr Interrupt funktioniert. Wenn Sie den Polling-Ansatz anstelle von Interrupts verwenden, haben Sie Erfolg?
@brhans Es sieht so aus, als würde er versuchen, einen Interrupt dafür zu verwenden, aber es ist mit diesem schlecht formatierten Code schwer zu sagen, und es sieht auch am if(data==1) }Ende dort abgeschnitten aus ...
@Majenko Ja - die Codeformatierung hat mich zuerst getäuscht und das Bit am Ende macht auch keinen Sinn.
@brhans Ich habe es durch einen Stil geleitet, um es ein wenig aufzuräumen. Hebt wirklich den defekten Codeteil hervor ...

Antworten (1)

Erstens wird dieser Code nicht kompiliert. Der letzte Teil davon (der ISR) sieht beschädigt aus - vielleicht möchten Sie diesen Teil erneut veröffentlichen.

Zweitens ist es nicht verwunderlich, dass es nicht reagiert, wenn Sie "FOO" eingeben, da der Code darauf wartet, dass Sie "a" drücken, woraufhin er mit "[a][a][a][a]" antworten würde. [a][a]....", bis Sie etwas anderes drücken.

Drittens sollten Sie lernen, Ihren Code richtig zu formatieren oder zumindest einen der guten automatischen Formatierer wie Artistic Style zu verwenden.

Leider habe ich hier keinen ATMega16A, um Ihren Code zu testen, und ich bin nicht auf Atmel-Interrupts, also kann ich nur einige Dinge vorschlagen, die Sie ausprobieren sollten:

  1. Stellen Sie sicher, dass Ihr Code tatsächlich ausgeführt wird und die Seriennummer selbst funktioniert: Lassen Sie main()nach der Konfiguration des UART zu Beginn eine "Hallo" -Nachricht drucken.
  2. Stellen Sie sicher, dass der Interrupt tatsächlich ausgelöst wird - lassen Sie eine LED leuchten, wenn der Interrupt ausgelöst wird.
  3. Lassen Sie eine weitere LED als "Herzschlag" in Ihrer Hauptschleife blinken, while(1)um sicherzustellen, dass sie nicht hängen bleibt.

Bearbeiten: Nach einigem Graben und Lesen (ich finde, dass Atmel-Datenblätter erschreckend schlecht geschrieben sind) habe ich festgestellt, dass Ihr Interrupt-Vektor falsch benannt ist.

Diese Seite listet sie alle auf: http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

Dort findet man nach einigem Durchforsten, dass für den ATMega16 der RX-Vektor heißen müsste:

    USART_RXC_vect 

Nachdem ich den Namen geändert habe, kann ich anhand einer Dekompilierung sehen, dass die ISR ordnungsgemäß in der Vektortabelle installiert wird:

00000000 <__vectors>:
   0:   0c 94 2a 00     jmp 0x54    ; 0x54 <__ctors_end>
   4:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
   8:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
   c:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  10:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  14:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  18:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  1c:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  20:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  24:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  28:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  2c:   0c 94 5c 00     jmp 0xb8    ; 0xb8 <__vector_11>   // <-- ISR
  30:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  34:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  38:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  3c:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  40:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  44:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  48:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  4c:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>
  50:   0c 94 47 00     jmp 0x8e    ; 0x8e <__bad_interrupt>

... was vorher nicht der Fall war.

Ich bin auch neu im Codieren von Formaten, wie Sie zum künstlerischen Stil vorgeschlagen haben. Ich habe es in Atmel Studio 5.2 installiert, aber es scheint überhaupt keinen Unterschied im Format zu geben.
Ich habe noch nie Artistic Style von Atmel Studio verwendet. Ich weiß nicht, ob es überhaupt darin unterstützt wird. Ich verwende es nur als Befehlszeilentool oder von meiner eigenen IDE (UECIDE, die ich speziell konfiguriert habe, um Ihren Code auszuprobieren).
Der von mir erwähnte uart-Interrupt funktioniert aus unbekannten Gründen in Atmel Studio 5.2. Wenn ich den Interrupt wie von Ihnen erwähnt gebe, scheint er mir einen Fehler als "MISSTYPED HANDLER" zu geben. RX, habe es mit int anstelle von char getestet. Es scheint, dass ich (strcmp (x, y) == 0) verwenden muss ... danke für deine Mühe, Freund.