2010-11-18 22 views
0

Nous programmons une image et nous avons diagnostiqué que si nous envoyons des données au port série alors qu'il essaie de nous envoyer des données, le programme se verrouille (notre code python et notre hyperterminal vont planter quand testé). Il travaillait en hyperterminal et l'entrait lentement (> 0,5 secondes entre les traits), et se bloquait lorsque le clavier était défoncé. Nous avons donc introduit un time.sleep qui est plus long que .5 secondes, mais il ne fonctionne toujours pas.pySerial gel après avoir lu 3 fois

Voici notre code de test.

import serial 
import time 

ser = serial.Serial("COM1") 
ser.baudrate=2400 

while 1: 
    for i in range(23): 
     ser.write(0x41)  
     time.sleep(.5) 
     print("ok") 

    rec = ser.read() 
    rec2 = ser.read() 
    rec3 = ser.read() 
    print(rec) 
    print(rec2) 
    print(rec3) 

    for i in range(23): 
     data = ser.read() 
     print(data) 
     print("ok") 
    time.sleep(5) 

notre fonction de données de réception. Nous avions l'habitude d'avoir le "ok" étant envoyé chaque fois qu'il a reçu un char (qui est comment nous savons qu'il se fige après 3 itérations). Nous l'avons amené en dehors de la boucle pour voir si cela causait le problème et ce n'était pas le cas. Il n'envoie pas le "ok" du tout avec ce code.

unsigned char receiveData(unsigned char *rxData, int length){ 
    // 1. Flag bit, RCIF, will be set when reception is complete and an interrupt will be generated if enable bit, RCIE, was set. 
char send[3] = "ok"; 

int index = 0; 

if(rxData==(void*)0 || rxInitialized==FALSE) return FAILURE; 
while(index<length){ 
    while(PIR1bits.RCIF==0);  
    rxData[index]= RCREG; 
    Delay1KTCYx(5); 
    index++; 
} 
    configureTransmission(); 
    sendData(send,3); 

    // 2. Read the RCSTA register to get the 9th bit (if enabled) and determine if any error occurred during reception. 
    // 3. Read the 8-bit received data by reading the RCREG register. 
    // 4. If any error occurred, clear the error by clearing enable bit CREN. 
return SUCCESS; 
} 
+0

Probablement la question la plus importante ici est, est-ce un vrai port de communication ou un USB <-> dongle série? Si c'est un dongle, quelle est la marque et le modèle? – synthesizerpatel

+0

Quel PIC? Parce que si c'est le PIC16F87XA ou similaire, cette fonction 'receiveData' est fausse - l'indicateur' RCIF' est placé quand le tampon de réception est plein, et est effacé quand 'RCREG' est vide, c.-à-d. lis. – detly

+0

Attendez, j'ai mal lu le code. Je vais en penser plus. – detly

Répondre

1

Est-ce que la communication de l'utilisation PIC faire du RTS/CTS lines du port série? Le PIC s'attend probablement à un contrôle de flux quelconque et vous envoyez des données trop rapidement sans contrôle de flux. Lire sur les limitations de la PIC et, si nécessaire ouvrir le port avec flow control activé.

2

(Cette réponse suppose que vous utilisez un PIC16, suggéré par les noms de certains registres.)

En bref, il ressemble à un débordement de tampon couplé à un bogue dans cette boucle dans receiveData. Le fait qu'il gèle après trois caractères sont envoyés successivement à court pourrait être expliqué par P117 du manuel:

Il est possible pour deux octets de données à recevoir et transférées à la FIFO RCREG et un troisième octet commencer à passer au registre RSR

Cela expliquerait le nombre magique trois. En passant par votre code PIC, considérez le scénario suivant (juste un exemple). Première fois autour de:

// One character already in RCREG - RCIF set 
while(PIR1bits.RCIF==0); 
// Reads ONE character - RCIF clear 
rxData[index]= RCREG; 
// While waiting here, two more characters are received - RCIF set 
Delay1KTCYx(5); 
index++; 

deuxième fois autour de:

// RCIF set from before 
while(PIR1bits.RCIF==0); 
// Reads ONE character - RCIF STILL set, ONE character remains in UART FIFO! 
rxData[index]= RCREG; 
// While waiting here, three more characters are received 
// RCIF set, RCREG fills up and the third character is discarded! 
Delay1KTCYx(5); 
index++; 

Le reste de la boucle gardera la lecture de RCREG jusqu'à index == length, mais étant donné que certains caractères ont été mis au rebut alors que le FIFO UART était pleine, vous Je n'y arriverai jamais et semblerais geler!

Ce qui est encore plus probable, c'est que vous recevez des caractères avant même d'avoir cette fonction, donc l'UART FIFO se remplit avant même d'y arriver.

Il y a plusieurs façons de contourner cela. Faites-le dans une interruption afin qu'il soit un peu plus rapide de déplacer les caractères entrants dans le tampon.

  • Utilisez une boucle pour lire à partir de RCREG: while(RCIF) rxData[index]= RCREG; cela vous assure de vider le tampon lors de la lecture du tampon UART, mais il n'arrêtera pas les débordements en dehors de cette fonction ou pendant ce délai.
  • Vérifiez le drapeau OERR - s'il est défini, supposez que quelque chose de mal est arrivé et recommencez.Avoir un caractère d'arrêt ou un caractère de début (par exemple, fin de ligne, ponctuation, etc.) qui vous indique quand une commande valide est en train de démarrer ou d'arrêter. Si vous obtenez deux caractères de début sans un caractère d'arrêt, ou une autre combinaison confuse, supposer que vous êtes dans un mauvais état et recommencer. Un conseil supplémentaire: vous pouvez devenir complètement fou en essayant de comptabiliser et de compenser chaque caractère manqué ou un problème comme celui-ci dans votre code PIC, mais finalement c'est juste une autre erreur comms. Les priorités dans le code PIC devraient être: la récupération rapide des erreurs et non le verrouillage. La détection d'erreur et la récupération saine devraient être traitées par le code client, où c'est beaucoup, beaucoup plus facile.