2009-10-24 23 views
5

J'essaie de faire communiquer un microcontrôleur avec un programme sur mon bureau. J'utilise des connexions de port série avec les radios Xbee aux deux extrémités.Comment envoyer et recevoir en continu avec le port série sans fil 8051?

La communication fonctionne correctement lorsque j'envoie quelque chose du microcontrôleur au bureau et que le programme sur le bureau envoie ensuite quelque chose au microcontrôleur.

Cependant, lorsque j'exige que les informations soient envoyées du contrôleur au programme de bureau en continu jusqu'à ce que le programme de bureau envoie une réponse particulière, cela ne fonctionne pas.

Voici le code pour ce dont je parle:

unsigned char ans = 'N'; 
    unsigned int count = 0; 

    void main(void) 
    { 


     while(1) 
     { 
      if(count == 0) 
      { 
       Configure(); 
       count = 1; 
      } 

        //there is some more code here but is irrelevant to the serial communication 

     } 

    } 


void Configure() 
{ 


    //Repeat this until the user accepts the sent string as correct 
    while(ans == 'N') 
    { 

     BuildString(); 
     Send(); 
     Receive(); 
    } 
} 

void Send() 
{ 
    unsigned int i; 

    TMOD = 0x20; 
    TH1 = 0xFD; 
    SCON = 0x50; 
    TR1 = 1; 

    for(i=0; i<4; i++) 
    { 
     SBUF = toSend[i]; 
     while(TI == 0); 
     TI = 0; 
    } 

} 

void Receive() 
{ 
    unsigned int j; 

    TMOD = 0x20; 
    TH1 = 0xFD; 
    SCON = 0x50; 
    TR1 = 1; 


    for(j=0; j<2; j++) 
    { 
     while(RI == 0); 
     Received[j] = SBUF; 
     RI = 0; 
    } 


    if(count == 0) 
     ans = Received[1]; 

    else 
    { 
     RunType = Received[0]; 
     Move = Received[1]; 
    } 


} 

La fonction BuildString() construit simplement une chaîne sur la base de certaines entrées de capteurs. Les fonctions d'envoi et de réception fonctionnent normalement, mais lorsque j'en ai besoin pour envoyer et recevoir en continu, comme dans la fonction Configure() ci-dessus, cela ne fonctionne pas.

Des suggestions? Je les apprécierais vraiment.

+0

Un hack rapide et sale qui rendra votre code plus fiable est de limiter le temps que vous attendez que RI soit défini sur true. Définissez une variable sur 65535 et décrémentez. Si elle atteint 0 avant d'avoir un octet, abandonnez et essayez d'envoyer à nouveau. Si vous avez vraiment besoin d'une version basée sur l'interruption de votre code, je peux vous convaincre - en général, ces versions sont beaucoup plus fiables. –

Répondre

4

Le problème est que vos fonctions d'envoi et de réception sont interrogées et bloquées. Lorsque vous appelez la fonction de réception, elle ne revient qu'après la réception d'un message complet. Dito pour la fonction d'envoi, mais en cas d'envoi, la durée est propablement plus courte (votre programme appellera seulement l'envoi quand il y a un message à envoyer, tandis que la réception peut attendre plusieurs jours avant l'arrivée d'un message). Il est préférable d'utiliser une communication asynchrone, au moins pour la réception et, idéalement, pour la réception et idéalement pour l'envoi et la réception

Il est également possible de l'utiliser en utilisant des communications interrogées, mais vous devez alors écrire une fonction qui vérifie si un caractère est disponible pour recevoir (ou si tx-vide), pour lire/écrire le caractère suivant depuis/vers le tampon

Les avantages de l'interruption b communication ASED sont:

  • full duplex
  • moins de temps cpu est utilisé (aucune attente boucles nécessaire)
  • moins de puissance (il permet au cpu d'aller à une faible puissance/mode veille, avec réveil sur interruption ; l'interrogation requiert toujours la pleine puissance)

Dans un premier temps, je vous conseille d'implémenter (ou d'obtenir) une réception basée sur l'interruption; Même lorsque la fonction de transmission est toujours bloquée, elle permet un fonctionnement en duplex intégral avec un minimum d'effort. Si vous n'avez pas d'os (rtos/scheduler), vous devrez penser à un mécanisme de synchronisation. La forme la plus simple consiste à ce que votre destinataire reçoive un message s'il y en a un, et qu'il retourne immédiatement s'il n'y a pas de message (complet).

bonne chance.

Modifier après les commentaires Sur une base message par message, les choses semblent fonctionner si le bureau réagit sur les messages envoyés par le contrôleur. Si votre contrôleur a un grand tampon FIFO (c'est-à-dire 64 octets) sur la réception, cela peut fonctionner. La plupart des contrôleurs que je connais n'ont pas cela. Beaucoup n'ont qu'un seul tampon de caractères. Vous pouvez le détecter en utilisant un bit OVERFLOW dans les registres; Si cela est défini, les caractères ont été perdus lors de la réception.

Quelques cas d'utilisation: * vous voulez envoyer 2 messages en une fois (disons: init + do_something). Le pc répond au premier msg, mais le contrôleur envoie toujours et abandonne la plupart des données. * L'ordinateur commence à envoyer avant que le contrôleur n'exécute la fonction receive(). Les données au début du paquet peuvent être perdues * toute perte de communication peut provoquer un blocage (c'est-à-dire que le contrôleur et le bureau attendent tous les deux que l'autre extrémité envoie quelque chose.)

Pour diagnostiquer: vérifier le bit de débordement. il est réglé, vous avez perdu des données et vous avez besoin de travailler sur les fonctions d'interruption.Si possible, surveillez les deux côtés (au moins l'état, un clignotement un led pour envoyer, et un pour recevoir par exemple)

A Le moniteur rs232 peut vous aider (vous aurez besoin de ports supplémentaires pour cela.) Il y a beaucoup d'applications (y compris freeware) qui peuvent surveiller plusieurs ports rs232 et fournir des horodatages.Vous pouvez donc observer l'ordre des communications Google m'a trouvé: link; J'ai utilisé plusieurs simil services publics au cours des dernières années.

+0

Merci beaucoup pour votre suggestion Adriaan. Mais je suis confus. J'avais l'intuition que ça ne fonctionnait peut-être pas à cause de l'aspect bloquant, mais je me suis dit que la façon dont j'avais écrit mes programmes l'aurait contourné. Voir Je fais que le contrôleur envoie un msg pendant que le programme de bureau l'attend avec un Receive() Ensuite, le programme de bureau vérifie le msg voit si c'est acceptable (tout cela tant que le programme du contrôleur attend de recevoir) un msg signalant l'acceptation ou le rejet du message. Le Receive() dans le contrôleur qui a été bloqué est maintenant débloqué n'est-ce pas? – CodeConfused

+0

Donc, ne devrait-il pas continuer avec le reste du code? C'est-à-dire vérifier si le message reçu est pour l'acceptation ou le rejet (Pendant ce temps, l'ordinateur de bureau attend avec une réception bloquée) puis envoyer à nouveau le message? Je suis sûr que la communication asynchrone permettrait de résoudre ce problème comme vous l'avez dit, mais je suis sur un peu d'une date limite avec ce projet et je n'ai jamais essayé de communication asynchrone. avant donc j'apprécierais vraiment si vous pouviez aider à résoudre ceci avec synchrone! – CodeConfused

+0

voir modifier en réponse. – Adriaan

1

Votre programme comme écrit devrait envoyer 4 octets, puis lire 2 octets (en supposant que les registres que vous avez sont corrects, mais si vous l'avez fait fonctionner, ils sont probablement corrects) puis envoyer à nouveau 4 octets ... n'est probablement pas suspendu à la partie envoi mais au côté réception car il attendra toujours de lire deux octets, et si pour une raison quelconque, deux octets n'arrivent pas au registre d'entrée, vous continuerez à attendre indéfiniment.

C'est peut-être lorsque vous stressez le système (envoyer trop rapidement) que vous débordez le tampon d'entrée et que vous perdez un octet? donc ne jamais avoir deux octets. et va rester coincé.

  1. pouvez-vous déboguer où vous êtes coincé? est-ce en fait dans la boucle de réception?
  2. pouvez-vous limiter la transmission du pc vers le micro pour pouvoir envoyer manuellement un octet à la fois?
  3. Y a-t-il une poignée de main entre l'interface micro et xbee? cela peut-il être étranglé par le micro?
+0

Oui Simon vous avez raison, il devrait envoyer 4 octets puis recevoir 2 et ainsi de suite jusqu'à ce qu'une certaine réponse est reçue Je suis assez sûr que le problème se trouve dans la partie réception, simplement parce que les Xbees s'allument lors de l'envoi ou de la réception, donc je peux 'voir' que les 2 octets du programme desktop ont quitté le bureau et peuvent également les "voir" arriver au microcontrôleur. J'ai essayé de déboguer en envoyant manuellement les octets un à la fois comme vous l'avez dit, mais cela n'a toujours pas fonctionné – CodeConfused

+0

Je ne suis pas sûr de la poignée de main entre le micro et Xbee Mais je suis presque sûr qu'il n'y en a pas – CodeConfused

+0

@CudeConfused, Pouvez-vous déterminer si/combien de fois le bit RI est changé? terminer un octet quelques fois le bit RI n'est pas défini. Est-ce que quelque chose peut déclencher le RI avant de l'effacer et ainsi manquer le second octet? – simon