2010-06-11 7 views
2

Tenir compte de ce code en cours d'exécution sur mon unité de microcontrôleur (MCU):Comment recevoir des paquets sur le port série du MCU?

while(1){ 

do_stuff; 
if(packet_from_PC) 
    send_data_via_gpio(new_packet); //send via general purpose i/o pins 
else 
    send_data_via_gpio(default_packet); 
do_other_stuff; 

} 

Le MCU est également relié à un PC via un UART.Whenever le PC envoie des données à la MCU, le new_packet est envoyé, sinon, le paquet par défaut est envoyé.Chaque paquet peut contenir 5 octets ou plus avec une structure de paquets prédéfinie.

Ma question est:

1.Should i recevoir le paquet entier de PC à l'aide à l'intérieur du UART interrut routine de service (ISR)? Dans ce cas, je dois implémenter une machine d'état à l'intérieur de l'ISR pour assembler le paquet (qui peut être long avec des blocs if-else ou switch-case).

    OR 

2.Have le PC envoyer une sorte de demande de commande (un octet), détecter dans mon ISR définir un indicateur, désactiver UART interrompre seul et former le paquet dans ma boucle while (1) en vérifiant pour le drapeau et interroger l'UART? Dans ce cas, l'interruption UART serait réactivée dans la boucle while (1) après la formation du paquet entier.

Répondre

1

Ce ne sont pas les deux seuls choix, et le second semble sous-optimal.

Ma première approche consisterait en une simple file d'attente circulaire, et j'introduirais des octets à partir de l'ISR et je lirais des octets dans votre boucle principale. De cette façon, vous avez un ISR petit et simple et vous effectuez le traitement dans votre boucle principale sans désactiver les interruptions.

Le premier choix est possible en supposant que vous pouvez coder les ISR de façon judicieuse. Vous voulez probablement avoir des délais d'attente pour la construction de paquets; vous devez être capable de gérer cela correctement dans votre ISR. Cela dépend de la vitesse de la ligne, de la vitesse de votre MCU et de ce que vous devez faire d'autre.

Mise à jour:

le faire dans l'ISR est certainement raisonnable. Cependant, l'utilisation d'une file d'attente circulaire est assez simple avec une implémentation standard dans votre sac à malice. Voici une implémentation de file d'attente circulaire; Les lecteurs et les écrivains peuvent fonctionner indépendamment.

#ifndef ARRAY_ELEMENTS 
#define ARRAY_ELEMENTS(x) (sizeof(x)/sizeof(x[0])) 
#endif 

#define QUEUE_DEFINE(name, queue_depth, type) \ 
     struct queue_type__##name { \ 
      volatile size_t m_in; \ 
      volatile size_t m_out; \ 
      type m_queue[queue_depth]; \ 
     } 

#define QUEUE_DECLARE(name) struct queue_type__##name name 

#define QUEUE_SIZE(name) ARRAY_ELEMENTS((name).m_queue) 

#define QUEUE_CALC_NEXT(name, i) \ 
     (((name).i == (QUEUE_SIZE(name) - 1)) ? 0 : ((name).i + 1)) 

#define QUEUE_INIT(name) (name).m_in = (name).m_out = 0 

#define QUEUE_EMPTY(name) ((name).m_in == (name).m_out) 

#define QUEUE_FULL(name) (QUEUE_CALC_NEXT(name, m_in) == (name).m_out) 

#define QUEUE_NEXT_OUT(name) ((name).m_queue + (name).m_out) 
#define QUEUE_NEXT_IN(name) ((name).m_queue + (name).m_in) 

#define QUEUE_PUSH(name) ((name).m_in = QUEUE_CALC_NEXT((name), m_in)) 
#define QUEUE_POP(name) ((name).m_out = QUEUE_CALC_NEXT((name), m_out)) 

utiliser comme ceci:

QUEUE_DEFINE(bytes_received, 64, unsigned char); 
QUEUE_DECLARE(bytes_received); 

void isr(void) 
{ 
    /* Move the received byte into 'c' */ 
    /* This code enqueues the byte, or drops it if the queue is full */ 
    if (!QUEUE_FULL(bytes_received)) { 
     *QUEUE_NEXT_IN(bytes_received) = c; 
     QUEUE_PUSH(bytes_received); 
    } 
} 

void main(void) 
{ 
    QUEUE_INIT(bytes_received); 

    for (;;) { 
     other_processing(); 
     if (!QUEUE_EMPTY(bytes_received)) { 
      unsigned char c = *QUEUE_NEXT_OUT(bytes_received); 
      QUEUE_POP(bytes_received); 
      /* Use c as you see fit ... */ 
     } 
    } 
} 
+0

J'essaie mon premier choix. La mémoire tampon en anneau semble être beaucoup de travail dans le programme en ce qui concerne la comptabilité tête/queue ... Je ne fais pas beaucoup de calcul dans la boucle principale. Les horloges MCU à 4MHz et la ligne baud est 9600bps – itisravi