Précédent   Forum du club des développeurs et IT Pro > Général Développement > Programmation système > Embarqué
Embarqué Forum d'entraide sur la programmation des systèmes embarqués
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 07/09/2012, 13h48   #1
arthurdubois
Invité régulier
 
Homme arthur
Étudiant
Inscription : 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 : 9
Points : 9
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
arthurdubois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/09/2012, 17h04   #2
arthurdubois
Invité régulier
 
Homme arthur
Étudiant
Inscription : 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 : 9
Points : 9
Bonsoir,

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

Citation:
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.
arthurdubois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/09/2012, 12h46   #3
nnovic
Membre éprouvé
 
Développeur en systèmes embarqués
Inscription : mars 2009
Messages : 222
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 : 222
Points : 477
Points : 477
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 ?
nnovic est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/09/2012, 09h06   #4
Bktero
Modérateur
 
Avatar de Bktero
 
Ingénieur systèmes embarqués
Inscription : juin 2009
Messages : 1 821
Détails du profil
Informations personnelles :
Âge : 25
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 : 1 821
Points : 4 603
Points : 4 603
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é !
Bktero est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/09/2012, 10h23   #5
Hibernatus34
Membre Expert
 
Inscription : août 2010
Messages : 533
Détails du profil
Informations forums :
Inscription : août 2010
Messages : 533
Points : 1 006
Points : 1 006
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.
Hibernatus34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/09/2012, 13h22   #6
arthurdubois
Invité régulier
 
Homme arthur
Étudiant
Inscription : 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 : 9
Points : 9
Merci pour les explications.
j´ai saisis !!
arthurdubois est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 06h33.


 
 
 
 
Partenaires

Hébergement Web