Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 6 sur 6
  1. #1
    Invité régulier
    Homme Profil pro arthur
    Étudiant
    Inscrit en
    mars 2012
    Messages
    110
    Détails du profil
    Informations personnelles :
    Nom : Homme arthur
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : mars 2012
    Messages : 110
    Points : 8
    Points
    8

    Par défaut Transfert de donnees entre l´USART0 et l´USART1

    Bonjour,

    je dispose d´un microntrôleur Atmega644p possedant deux USARTs. A savoir USART0 et USART1. USART0 recoit des bytes du pc et les enregistrent dans son buffer UDR0. Ensuite les bytes se trouvant dans le buffer UDR0 de l´USART0 doivent être transferes dans le buffer UDR1 de l´USART1. Une fois les donnees dans UDR1, les bytes seront envoyes a une autre unite.

    pour l´instant, je m´occupe uniquement du transfert des bytes de UDR0 vers UDR1 en me servant de la fonction d´interruption de reception ISR(USART0_RX_vect).

    Voici mon code:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    /*-- function receive USART0 --*/
    unsigned char USART0_Receive (void)
    {
        while(!(UCSR0A & (1<<RXC0)) ); // Wait for data to be received 
         return UDR0; // Get and return received data from buffer 
    }
    
    /*-- function transmit USART1 --*/  
    void USART1_Transmit (unsigned char data1)
    {
      while ( !(UCSR1A & (1<<UDRE1)) ); // Wait for empty transmit buffer  
       UDR1 = data1; // Put data into buffer, sends the data  
    }
    
    ISR(USART0_RX_vect)
    {
      char data;
      data = UDR0; // lire le byte
      UDR1 = data; // ecrire le byte
    }
    
    int main (void)
    
    { 
      
      USART_Init(UBRR_VAL) ;  // Initialisation de USART0 und USART1 
      sei();
      char c ;
      
    
      while(1)
      {
       c = USART1_Receive();
    
       if( (UCSR1A & (1<<RXC1))  &&
            (UCSR1A & (1<<UDRE1)) )  // l´USART1 peut envoyer un caractere 
         {
           USART1_Transmit(c);
         }      
      }
    
    }
    Le code marche certe, mais j´ai une perte de donnees dans la fonction ISR(USART0_RX_vect) lorsque j´ecris:
    les donnees recues par le buffer UDR0 ne sont pas tous transferes dans le Buffer UDR1. J´ai une perte de donnees.

    Comment pourrais-je corriger cela ? Manque t-il une autre condition dans ma fonction ISR(USART0_RX_vect) ? Aidez moi s´il vous plaît.

    Merci

  2. #2
    Invité régulier
    Homme Profil pro arthur
    Étudiant
    Inscrit en
    mars 2012
    Messages
    110
    Détails du profil
    Informations personnelles :
    Nom : Homme arthur
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : mars 2012
    Messages : 110
    Points : 8
    Points
    8

    Par défaut

    Bonsoir,

    est-ce possible d´eviter la perte de donnees avec la modification suivante:

    ISR(USART0_RX_vect)
    {
    char data ;
    data = UDR0;

    if(!(UCSR1A & (1<<UDRE1))) // ready to write
    {
    UDR1 = data;
    }
    }
    Qu´en dites-vous? Merci de bien vouloir m´aider.

  3. #3
    Membre éprouvé

    Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    mars 2009
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : mars 2009
    Messages : 237
    Points : 475
    Points
    475

    Par défaut

    Hello,

    Ton deuxième poste va dans la bonne direction, mais je crois que c'est encore insuffisant: si l'UART1 n'est pas dispo pour écrire, que faire de "data" ?

    Il faut partir du principe que les deux UARTS ne fonctionnent pas au même rythme. Les données venant de l'UART0 doivent être stockées dans un buffer, et l'UART1 vient prendre dans ce buffer les octets à émettre.

    Pour t'aider à faire ça, l'UART1 a peux peut-être une interruption qui se déclenche lorsqu'il est prêt à émettre ?

  4. #4
    Modérateur
    Avatar de Bktero
    Profil pro
    Ingénieur systèmes embarqués
    Inscrit en
    juin 2009
    Messages
    2 645
    Détails du profil
    Informations personnelles :
    Âge : 27
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2009
    Messages : 2 645
    Points : 6 325
    Points
    6 325

    Par défaut

    Bonjour,

    Dans ton premier post, tu parles d'un vecteur d'interruption mais tu fais même une attente active pour la réception ?

    Le problème soulevé par nnovic est important : les baudrates des 2 liaisons sont-elles les mêmes ? Si non et que UART0 est plus rapide que UART1, il y a tous un tas de problématiques de gestion de buffer et d'émission et réception asynchrones. Si oui ou que UART0 est plus lente que UART1, pourquoi ne pas simplement faire une interruption dés qu'UART0 reçoit une donnée. C'est ce que tu sembles faire dans le 2e message si j'ai bien compris.

    Code :
    UDR1 = data; J´ai une perte de donnees
    C'est-à-dire ? Tu perds des octets de temps en temps ou tu perds systématiquement certains bits de tous les octets ?
    Si Code::Blocks vous dit undefined reference to 'socket@12', cela signifie que vous avez un problème d'édition des liens. Allez dans Projects / Build Options / Linker Settings / Add et renseigner ici les .a qui vont bien. Exemple pour les sockets : C:\Program Files\CodeBlocks\MinGW\lib\libws2_32.a

    Pour les adeptes du langage SMS, allez ici et ramenez la traduction française ^^

    Pour vos problèmes d'embarqué, utilisez le forum dédié !

  5. #5
    Membre Expert
    Inscrit en
    août 2010
    Messages
    647
    Détails du profil
    Informations forums :
    Inscription : août 2010
    Messages : 647
    Points : 1 261
    Points
    1 261

    Par défaut

    Il faut utiliser un buffer, mais je t'ai déjà donné du code le faisant. Ca écrivait dans UDR0 mais il suffisait de remplacer par UDR1.
    Il faut utiliser l'interruption qui signale la disponibilité de UDR1 (UDRE1).
    Sinon, si le débit est différent, il faut du contrôle de flux à un moment donné. Le contrôle de flux c'est le récepteur qui interdit à l'émetteur de lui envoyer des données en attendant de vider son buffer.

  6. #6
    Invité régulier
    Homme Profil pro arthur
    Étudiant
    Inscrit en
    mars 2012
    Messages
    110
    Détails du profil
    Informations personnelles :
    Nom : Homme arthur
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : mars 2012
    Messages : 110
    Points : 8
    Points
    8

    Par défaut

    Merci pour les explications.
    j´ai saisis !!

+ Répondre à la discussion
Cette discussion est résolue.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •