Question

Je suis en train de faire communiquer un microcontrôleur 8051 sans fil avec un ordinateur. Le microcontrôleur enverra une chaîne à son port série (DB9) et l’ordinateur recevra cette chaîne et la manipulera.

Mon problème est que je ne sais pas comment faire en sorte que le 8051 transmette la chaîne une seule fois. Étant donné que je dois manipuler la chaîne sur le PC, elle ne doit être reçue qu'une seule fois. Actuellement, même si dans le code C j'envoie la chaîne une fois, sur mon ordinateur, je reçois la même chaîne de façon continue. Je suppose que cela est dû au fait que tout ce qui se trouve dans la SBUF est transmis en permanence. Existe-t-il un moyen de ne pouvoir envoyer ma chaîne qu'une seule fois? Existe-t-il un moyen de vider la SBUF?

J'ai essayé d'utiliser la broche (7ème broche) RTS (demande d'envoi) sur le DB9 car j'ai lu quelque part que si j'annulais la tension sur cette broche, le flux de données sur le port série serait interrompu. Donc, ce que j'ai fait a été programmé pour que mon microcontrôleur envoie la chaîne, puis envoie le niveau logique 0 à une broche de sortie connectée à ma broche DB9 RTS. Cependant, cela n'a pas fonctionné.

Quelqu'un a-t-il des suggestions? Je les apprécierais vraiment.

EDIT

Le logiciel que j'utilise sur le PC est X-CTU for Xbee. Voici le code sur mon microcontrôleur:

include reg51.h 
void SerTx(unsigned char);  
void main(void)  
{  
  TMOD = 0x20;  
  TH1 = 0xFD;  
  SCON = 0x50;  
  TR1 = 1;   

  SerTx('O');  
  SerTx('N');  
  SerTx('L');  
  SerTx('Y'); 

}

void SerTx(unsigned char x)  
{  
  SBUF = x;  
  while(TI==0);   
  TI = 0;   
}  

Quelqu'un pourrait-il s'il vous plaît vérifier qu'il n'envoie en fait la chaîne qu'une seule fois?

EDIT

On dirait que Steve, Brookesmoses et Neil ont mis le doigt sur le clou quand ils ont dit que c’était ce qui se passait APRÈS ma fonction principale qui était à l’origine du problème. Je viens d'essayer le code suggéré par Steve (plus précisément le for (;;); et la définition de serTX en dehors de main) et cela a parfaitement fonctionné. Le contrôleur est probablement redémarré et le même code continue donc à se répéter.

Merci beaucoup pour l'aide! :)

Était-ce utile?

La solution

Pouvez-vous confirmer que le 8051 n’envoie réellement les données qu’une seule fois? Une façon de vérifier consiste à utiliser un oscilloscope pour voir ce qui se passe sur la broche TX de l'UART.

Quels logiciels utilisez-vous sur le PC? Je suggérerais d'utiliser un logiciel de communication simple comme HyperTerminal ou PuTTY . S'ils affichent plusieurs fois la chaîne envoyée au PC, il est probable que l'erreur soit dans le logiciel exécuté sur le 8051.

EDIT: Pour être honnête, cela ressemble au genre de débogage auquel les ingénieurs sont régulièrement confrontés. C'est donc une bonne occasion pour vous de résoudre de bons problèmes méthodiques à l'ancienne- résoudre.

Si je peux être très direct, je vous suggère de procéder comme suit:

  1. Déboguer. Essayez des solutions, mais ne devinez pas . Expérience. Faites de petits changements dans votre code et voyez ce qui se passe. Essayez tout ce que vous pouvez penser. Recherchez plus d'informations sur le Web.
  2. Si cela ne permet pas de trouver une solution, revenez ici et donnez-nous toutes les informations dont nous avons besoin. Cela inclut des éléments pertinents du code, des détails complets sur le matériel que vous utilisez et des informations sur ce que vous avez essayé à l'étape 1.

MODIFIER: Je n'ai pas le représentant pour modifier la question. Voici donc le code affiché par l'OP dans le commentaire de sa question:

#include<reg51.h>

void SerTx(unsigned char);

void main(void)
{
    TMOD = 0x20; TH1 = 0xFD; SCON = 0x50; TR1 = 1;
    SerTx('O'); SerTx('N'); SerTx('L'); SerTx('Y');

    void SerTx(unsigned char x)
        { SBUF = x; while(TI==0); TI = 0; } 
}

Comme Neil et Brooksmoses le mentionnent dans leurs réponses, dans un système embarqué, la fonction principale n’est jamais autorisée à se terminer. Vous devez donc soit placer votre code dans une boucle infinie (ce qui peut être ce qui se passe par inadvertance), soit ajouter une boucle infinie à la fin, afin que le programme s’arrête effectivement.

De plus, la fonction SerTx doit être définie en dehors de main. Cela est peut-être correct du point de vue de la synchronisation, mais cela simplifie les choses, sans déclarer de fonctions dans d'autres fonctions.

Alors essayez ceci (j'ai également ajouté quelques commentaires pour tenter de rendre le code plus facile à comprendre):

#include<reg51.h>

void SerTx(unsigned char);

void main(void)
{
    /* Initialise (need to add more explanation as to what
        each line means, perhaps by replacing these "magic
        numbers" with some #defines) */
    TMOD = 0x20;
    TH1  = 0xFD;
    SCON = 0x50;
    TR1  = 1;

    /* Transmit data */
    SerTx('O'); SerTx('N'); SerTx('L'); SerTx('Y');

    /* Stay here forever */
    for(;;) {}

}

void SerTx(unsigned char x)
{
    /* Transmit byte */
    SBUF = x;

    /* Wait for byte to be transmitted */
    while(TI==0) {}

    /* Clear transmit interrupt flag */
    TI = 0;
} 

Autres conseils

Le code que vous avez posté n'a pas de boucle dans main (), vous devez donc déterminer ce que le runtime C de votre compilateur fait lorsque main () retourne après l'envoi de 'Y'. Compte tenu de votre problème, j’imagine que le compilateur génère du code pour effectuer un nettoyage, puis redémarre le micro (peut-être une réinitialisation matérielle, peut-être simplement un redémarrage du moteur d’exécution C). Il semble que votre programme fonctionne exactement comme vous l'avez écrit, mais vous avez ignoré ce qui se passe avant et après l'appel de main ().

Si vous souhaitez que votre chaîne soit envoyée une seule et unique fois, vous avez besoin de quelque chose comme tant que (1) {} est ajouté après l'envoi du dernier caractère. Mais alors, votre programme ne fait rien - il exécutera simplement une boucle vide pour toujours. Une réinitialisation (telle que le cycle d'alimentation) est nécessaire pour redémarrer et envoyer la chaîne.

Notez que si votre micro est doté d’un minuteur de surveillance, il risque d’intervenir et de forcer une réinitialisation inattendue. Si cela se produit, votre chaîne sera envoyée une fois pour chaque réinitialisation du chien de garde (ce qui pourrait ressembler à une fois par seconde, le débit dépendant de votre matériel).

De plus, le fait que serTx () soit imbriqué dans main () n’est probablement pas ce que vous voulez.

Il est difficile de dire quel est le problème sans consulter le code 8051. Par exemple, une erreur logique de ce côté peut entraîner l'envoi de données à plusieurs reprises, ou le logiciel 8051 peut attendre un accusé de réception, qui n'a jamais été reçu, etc.

Normalement, un code 8051 doit envoyer explicitement chaque caractère, mais je suppose que cela est pris en charge pour vous par le C-run-time.

L’utilisation de RTS / CTS (demande d’envoi / suppression d’envoi) sert au contrôle de flux (c'est-à-dire pour éviter les dépassements de mémoire tampon - les mémoires tampon sont généralement assez petites sur ces microcontrôleurs) et pour ne pas arrêter complètement la transmission.

Répondant à la réponse de Neil (dans une réponse, vu que je n'ai pas encore le représentant à commenter): dans une situation typique de microcontrôleur sans système d'exploitation, on ne sait pas tout de suite quelle est la fonction exit () qui est appelée implicitement à la fin. of main () devrait faire - ou, plus exactement, il ne peut pas faire l’habituel "mettre fin au programme et retourner à l’OS", car il n’ya pas d’OS sur lequel retourner.

De plus, dans une application réelle, vous ne voulez presque jamais que le programme s’arrête, à moins d’éteindre le système. Donc, une chose que l’implémentation de exit () ne devrait absolument pas faire, c’est beaucoup de place pour le code.

Dans certains systèmes sur lesquels j'ai travaillé, exit () n'est pas du tout implémenté - si vous ne l'utilisez pas, ne perdez même pas un octet dessus! Le résultat est que, lorsque le chemin d’exécution arrive à la fin de main (), la puce se perd dans l’arrière-plan et exécute tout ce qui se trouve dans le prochain bit de mémoire, et finit généralement rapidement par rester coincée dans une boucle ou faute avec un opcode illégal. Et le résultat habituel d’une erreur avec un opcode illégal est… le redémarrage de la puce.

Cela semble être une théorie plausable de ce qui se passe ici.

Cet article concerne l'assemblage, pas C, mais il pourrait s'avérer utile: http://www.8052.com/tutser.phtml

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