Comment puis-je corriger ce code pour permettre à mon AVR parler sur le port série?

StackOverflow https://stackoverflow.com/questions/846206

  •  21-08-2019
  •  | 
  •  

Question

J'ai mes cheveux tirais ces derniers temps en essayant d'obtenir un ATmega162 sur mon STK200 parler à mon ordinateur via RS232. J'ai vérifié et fait en sorte que le STK200 contient une puce MAX202CPE.

I ai configuré pour utiliser la puce son horloge à 8MHz interne et divisé par 8.

J'ai essayé de copier le code de la feuille de données (et fait des changements où le compilateur) se plaint, mais en vain.

Mon code est ci-dessous, quelqu'un pourrait me aider à résoudre s'il vous plaît les problèmes que je vais avoir?

Je l'ai confirmé que mon port série fonctionne sur d'autres appareils et ne sont pas défectueux.

Merci!

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

#define BAUDRATE 4800

void USART_Init(unsigned int baud)
{
    UBRR0H = (unsigned char)(baud >> 8);
    UBRR0L = (unsigned char)baud;

    UCSR0B = (1 << RXEN0) | (1 << TXEN0);

    UCSR0C = (1 << URSEL0) | (1 << USBS0) | (3 << UCSZ00);
}

void USART_Transmit(unsigned char data)
{
    while(!(UCSR0A & (1 << UDRE0)));

    UDR0 = data;
}

unsigned char USART_Receive()
{
    while(!(UCSR0A & (1 << RXC0)));

    return UDR0;
}

int main()
{

    USART_Init(BAUDRATE);

    unsigned char data;

    // all are 1, all as output
    DDRB = 0xFF;

    while(1)
    {
        data = USART_Receive();

        PORTB = data;

        USART_Transmit(data);


    }
}
Était-ce utile?

La solution 4

Après avoir lu la fiche de données un peu plus à fond, je mettais mal la vitesse de transmission. La fiche de données ATmega162 avait un tableau de fréquences d'horloge tracée en fonction des vitesses de transmission et l'erreur correspondante.

Pour une vitesse de transmission de 4800 et une fréquence d'horloge de 1 MHz, l'erreur est de 0,2%, ce qui était acceptable pour moi. L'astuce était de passage 12 à la fonction USART_Init (), au lieu de 4800.

Espérons que cela aide quelqu'un d'autre!

Autres conseils

Je l'ai commenté la réponse de Greg, mais je voudrais ajouter une chose. Pour ce genre de problème, la méthode standard d'or de débogage, il est d'abord comprendre communications série asynchrone, puis d'obtenir un oscilloscope et voir ce qui se passe sur la ligne. Si les caractères sont échangés et il est juste un problème de vitesse de transmission, ce sera particulièrement utile que vous pouvez calculer la vitesse de transmission que vous voyez et ensuite ajuster le diviseur en conséquence.

Voici une amorce super rapide, sans aucun doute, vous pouvez trouver quelque chose de beaucoup plus complet sur Wikipédia ou ailleurs.

Supposons que 8 bits, pas de parité, 1 bit d'arrêt (réglage le plus courant). ( « ? » = Ascii) Ensuite, si le caractère est transmis est dire 0x3f, la ligne ressemble à ceci;

...--+   +---+---+---+---+---+---+       +---+--...
     | S | 1   1   1   1   1   1 | 0   0 | E
     +---+                       +---+---+

Le haut (1) de niveau est de + 5V à la puce et -12V après conversion en niveaux RS232.

Le niveau bas (0) est de 0V à la puce et + 12V après conversion en niveaux RS232.

S est le bit de départ.

Ensuite, nous avons 8 bits de données, moins significatif en premier, alors voici 00111111 = 0x3f = ''.

E est le bit d'arrêt (e pour fin).

Le temps avance de gauche à droite, tout comme un écran de l'oscilloscope, Si la vitesse de transmission est de 4800, chaque durée de bit (1/4800) secondes = 0,21 millisecondes (environ).

Les travaux de réception par échantillonnage de la ligne à la recherche d'un front descendant (une ligne de repos est tout simplement logique « 1 » tout le temps). Le récepteur connaît la vitesse de transmission, et le nombre de bits de départ (1), il mesure un demi temps bit du front descendant pour trouver le milieu du bit de départ, puis les échantillons les ligne 8 fois bit successivement après que, pour recueillir les Bits de données. Le récepteur attend ensuite une fois de plus de bits (jusqu'à mi-chemin à travers le bit d'arrêt) et commence à chercher un autre bit de démarrage (c.-à-bord descendant). Pendant ce temps le caractère lu est mis à la disposition du reste du système. L'émetteur garantit que le prochain front descendant ne commencera pas jusqu'à ce que le bit d'arrêt est terminée. L'émetteur peut être programmé pour attendre toujours plus (avec bits d'arrêt supplémentaires), mais qui est un problème de l'héritage, les bits d'arrêt supplémentaires ont été nécessaires que avec du matériel très lent et / ou des configurations logicielles.

Je n'ai pas du matériel de référence à portée de main, mais la vitesse de transmission UBRR de registre contient habituellement une valeur de diviseur, plutôt que la vitesse de transmission souhaitée lui-même. Un recherche rapide Google indique que la valeur du diviseur correct pour 4800 bauds peut être 239. Donc, essayez:

divisor = 239;
UBRR0H = (unsigned char)(divisor >> 8);
UBRR0L = (unsigned char)divisor;

Si cela ne fonctionne pas, consultez la documentation de référence pour votre puce particulière pour la formule de calcul du diviseur correct.

Pour le débogage communication UART, il y a deux choses utiles à faire:

1) Faites une boucle arrière au niveau du connecteur et assurez-vous que vous pouvez relire ce que vous écrivez. Si vous envoyez un caractère et obtiendrez exactement, vous savez que le matériel est correctement câblé, et qu'au moins l'ensemble de base de la configuration du registre UART est correct.

2) envoyer à plusieurs reprises le caractère 0x55 ( « U ») -. La configuration binaire 01010101 vous permettra de voir rapidement la largeur de bit sur l'oscilloscope, qui vous permettra de vérifier que le réglage de la vitesse est correcte

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top