Réception de données avec TCOMPORT - caractères manquants [Résolu]

YB28 39 Messages postés lundi 23 avril 2012Date d'inscription 29 juillet 2012 Dernière intervention - 24 mai 2012 à 16:55 - Dernière réponse : YB28 39 Messages postés lundi 23 avril 2012Date d'inscription 29 juillet 2012 Dernière intervention
- 30 mai 2012 à 10:06
Bonjour,
Un autre soucis...Je récupère des données à l'évènement onRxChar comme ceci:
var   Chaine  : array[0..250] of Byte;
      FileDeTraitement :array[0..250] of Byte;

procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
var
    j:integer;
begin
  Long:=ComPort1.InputCount;
  ComPort1.Read(Chaine, Long);
  for j := 0 to Long do
    begin
      FileDeTraitement[ucQueueFilepocket + j] := Chaine[j];
    end;
  ucQueueFilepocket := ucQueueFilepocket + Long;
  if ucQueueFilepocket >= 249 then
    begin
      ucQueueFilepocket := 0;
    end;
    Timer1.Enabled:=true;
end;


Je mets les données dans FileDeTraitement que je traite ensuite dans un timer:

procedure TForm1.Timer1Timer(Sender: TObject);
  repeat
  begin
    {Dépilement file dans CaractereRecu à partir de Index}
     CaractereCourant := Widechar(FileDeTraitement[ucTeteFilepocket]);
     CaractereRecu[Index] := CaractereCourant;
     Index := Index + 1;
     ucTeteFilepocket := ucTeteFilepocket + 1;
     memo2.Text:=memo2.Text+CaractereCourant;
     if ucTeteFilepocket >= 249 then  //test si ucTeteFilepocket dépasse 250 caractères
     begin
        ucTeteFilepocket := 0;
     end;
  end
  until (ucTeteFilepocket ucQueueFilepocket) or (ucTeteFilepocket 0);

Cependant de temps en temps il y a des caractères manquant dans FileDeTraitement alors qu'ils sont bien présent dans Chaine. D'où pourrais provenir la perte de données qui n'arrive pas à chaque fois mais assez souvent?

Merci ;)
Afficher la suite 

Votre réponse

6 réponses

Meilleure réponse
cs_yanb 260 Messages postés lundi 27 octobre 2003Date d'inscription 4 mars 2016 Dernière intervention - 26 mai 2012 à 12:21
3
Merci
Salut,
un petit tour ici
ensuite un tableau de [0..250] représente 251 bytes...
Ensuite si tu as une trame de 150 bytes puis une autre de 150 dans ton programme, ben il va en manquer 50 dans ton FileDeTraitement...si tu veux utiliser les tableaux alors allou la taille à ton besoin avec setlength...
Pourquoi utiliser un timer...
Voilà les pistes à creuser pourquoi tu perds des caractères...
Bon courage @+

Merci cs_yanb 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 98 internautes ce mois-ci

Commenter la réponse de cs_yanb
YB28 39 Messages postés lundi 23 avril 2012Date d'inscription 29 juillet 2012 Dernière intervention - 29 mai 2012 à 11:40
0
Merci
C'est bon j'ai réussi!!
J'ai rajouté la variable valeurMax dans l'évènement de réception.

if ucQueueFilepocket >= 249 then
  begin
    valeurMax:=ucQueueFilepocket;
    ucQueueFilepocket := 0;
  end;


et dans le timer j'ai donc changer comme ceci en utilisant valeurMax

if ucTeteFilepocket >= valeurMax+1 then
     begin
        ucTeteFilepocket := 0;
        Index:=Index-1;
     end;
Commenter la réponse de YB28
cs_yanb 260 Messages postés lundi 27 octobre 2003Date d'inscription 4 mars 2016 Dernière intervention - 29 mai 2012 à 12:43
0
Merci
Salut,
Mouais effectivement...
Pourquoi un timer ?
Pourquoi des tableaux de 250 bytes ?
...
var   
  Chaine  : array of Byte;
  ...
procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
  ...
  SetLength(Chaine, Count);//taille de Chaine en fonction de count
  ComPort1.Read(Chaine, Count);
  ...

Pourquoi n'utilises-tu pas simplement ReadStr ?
procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
var 
  Chaine : String;
begin
  ComPort1.ReadStr(Chaine, Count);
  Memo2.Lines.Text := Memo2.Lines.Text + Chaine;
end;

@+
Commenter la réponse de cs_yanb
YB28 39 Messages postés lundi 23 avril 2012Date d'inscription 29 juillet 2012 Dernière intervention - 29 mai 2012 à 14:57
0
Merci
salut,
J'ai mis un timer car je voulais séparer la réception de données et le traitement des données. C'est vrai que la longueur 250 est une taille peut être un peu grande mais je travail avec des tableaux car je traite caractère par caractère. Selon le caractère que je recois celui d'après aura une autre importance. Je te joint le code du timer où tu verras bien cela. (désolé un peu long ;) )

procedure TForm1.Timer1Timer(Sender: TObject);
var CaractereCourant  : WideChar;
    CaractereRecu     : array[0..250] of WideChar;
//    ReponsePresente   : array[0..250] of WideChar;
    i                 : integer;
    j	              : integer;
    CaractereCommande : Byte;
    CaractereLigne    : Byte;
    CaractereColone   : Byte;
    CaractereSpeciaux : Byte;

begin

Index:=0;
{initialisation de la chaine CaractereRecu}
  for i := 0 to 249 do
  begin
    CaractereRecu[i] := #255;
  end;

if demarrage<>true then
begin
{implante les Caracteres Precedent à partir de emplacementESC dans le début de la file CaractereRecu}
  j:=0;
  for i:=emplacementESC to Long2 do
  begin
   CaractereRecu[j]:=CaracterePrecedent[i];
   inc(j);
  end;

{positionne l'Index pour décaler la Chaine CaractereRecu}
  Index:=Index+Long2-emplacementESC;
end;
demarrage:=false;
j:=0;
  repeat
  begin
    {Dépilement file dans CaractereRecu à partir de Index}
     CaractereCourant := Widechar(FileDeTraitement[ucTeteFilepocket]);
     CaractereRecu[Index] := CaractereCourant;
     StringGrid2.Cells[0,j+1]:=inttostr(j);
     StringGrid2.Cells[1,j+1]:=chr(FileDeTraitement[ucTeteFilepocket]);
     ucTeteFilepocket := ucTeteFilepocket + 1;
     inc(j);
     Index := Index + 1;
     if ucTeteFilepocket >= valeurMax+1 then  //test si ucTeteFilepocket dépasse 250 caractères
     begin
        ucTeteFilepocket := 0;
        Index:=Index-1;
     end;
  end
  until (ucTeteFilepocket = ucQueueFilepocket);
  Index:=Index-1;
  
  Edit3.Text:=inttostr(ucTeteFilepocket);
  Edit4.Text:=inttostr(ucQueueFilepocket);

{initialisation de la chaine CaracterePrecedent}
for j :=0 to 249 do
begin
CaracterePrecedent[j]:=#255;
end;

{implantation les Caracteres Recu dans la file CaracterePrecedent sans les #5 et #0}
  j:=0;
  for i:=0 to Index do
  begin
    if CaractereRecu[i]<>#5 then
    begin
      if CaractereRecu[i]<>#0 then
      begin
        CaracterePrecedent[j]:=CaractereRecu[i];
        inc(j);
      end;
    end;
  end;

{Détermination de la longueur de la chaine CaracterePrecedent 'Long2'}
j:=0;
Long2:=0;
repeat
if CaracterePrecedent[j]<>#255 then
  begin
    Long2:=Long2+1;
    j:=j+1;
  end;
until CaracterePrecedent[j]=#255;

{Repérage de la dernière Commande reçu}
  for i:=0 to Long2 do
begin
if CaracterePrecedent[i]=#27 then
begin
emplacementESC:=i;
end;
end;

{Traitement des caractères reçu}
  for i := 0 to Index do
  begin
    case CaractereRecu[i] of
{réponse de la présence de la pocket}
      #5:
        begin
    //        ReponsePresente[0]:=#6;
    //        Comport1.Write(ReponsePresente,1);
        end;
{initialisation de l'écran}
      #12:
        begin
           fEffaceToutEcran();
        end;
{Commandes}
      #27:
        begin
          CaractereCommande := Byte(CaractereRecu[i+1]);
          case CaractereCommande of
            69: begin
                CaractereSpeciaux := Byte(CaractereRecu[i+2]);
                  case CaractereSpeciaux of
                    49: begin
                          CaractereRecu[i+2] := #255;
                          CaractereRecu[i+3] := #255;
                          CaractereRecu[i+4] := #255;
                          CaractereRecu[i+5] := #255;
                          CaractereRecu[i+6] := #255;
                          CaractereRecu[i+7] := #255;
                          CaractereRecu[i+8] := #255;
                          CaractereRecu[i+9] := #255;
                        end;
                    50: begin CaractereRecu[i+2] := #255; end;
                    51: begin CaractereRecu[i+2] := #255; end;
                  end;
                end;
            81: begin richedit1.Color:=clSkyBlue end;//Active éclairage
            82: begin richedit1.Color:=clWindow end;//Désactive éclairage
            76: begin//placement du curseur au début de l'écran
                  Ligne:=0;
                  Colonne:=0;
                  richedit1.SelStart := SendMessage(richedit1.Handle, EM_LINEINDEX, ligne, 0)+colonne;
                end;
            74: begin //Efface jusqu'à la fin de l'écran
                  Ligne:=SendMessage(richedit1.Handle,EM_LineFromChar,richedit1.SelStart,0);
                  fEffacePartieEcran(ligne);
                end;
            105:begin bt_PP.SetFocus end;//Désactive curseur
            118:begin //Active curseur
                  richedit1.Enabled:=true;
                  richedit1.SelStart := SendMessage(richedit1.Handle, EM_LINEINDEX, ligne, 0)+colonne;
                  richedit1.SetFocus
                end;
            89: begin
                  if CaractereRecu[i+2]<>#255 then
                  begin
                    CaractereLigne  := Byte(CaractereRecu[i+2]);
                    CaractereColone := Byte(CaractereRecu[i+3]);
                    fLigneColonne(CaractereLigne,CaractereColone);
                    CaractereRecu[i+2] := #255;
                    CaractereRecu[i+3] := #255;
                  end;
                end;
          else
            begin
              break;
            end;
          end;
          CaractereRecu[i+1] := #255;
        end;
      #255:
        begin
          //Rien à faire
        end
      else
        begin
          {place le curseur d'insertion}
          richedit1.SelStart := SendMessage(richedit1.Handle, EM_LINEINDEX, ligne, 0)+colonne;
          {insert le caractère de CaractereRecu[i] dans L à partir de l'emplacement du curseur}
         case ligne of
            0:begin
                  if CaractereRecu[i]=#1 then
                    begin
                      delete(L0,richedit1.SelStart+1,1);
                      richedit1.Lines[0]:=L0;
                      sendmessage(Richedit1.handle,WM_IME_CHAR,$2192,0);
                    end
                  else
                    begin
                      delete(L0,richedit1.SelStart+1,1);
                      insert(CaractereRecu[i],L0,richedit1.SelStart+1);
                      richedit1.Lines[0]:=L0; //Affiche la ligne 0 du memo
                    end;
                              L0 := richedit1.Lines[0];
              end;
            1:begin
                  if CaractereRecu[i]=#1 then
                    begin
                      delete(L1,richedit1.SelStart-21,1);
                      richedit1.Lines[1]:=L1;
                      sendmessage(Richedit1.handle,WM_IME_CHAR,$2192,0);
                    end
                  else
                    begin
                      delete(L1,richedit1.SelStart-21,1);
                      insert(CaractereRecu[i],L1,richedit1.SelStart-21);
                      richedit1.Lines[1]:=L1; //Affiche la ligne 1 du memo
                    end;
                     L1 := richedit1.Lines[1];
              end;
            2:begin
                  if CaractereRecu[i]=#1 then
                    begin
                      delete(L2,richedit1.SelStart-43,1);
                      richedit1.Lines[2]:=L2;
                       richedit1.SelStart := SendMessage(richedit1.Handle, EM_LINEINDEX, ligne, 0)+colonne;
                      sendmessage(Richedit1.handle,WM_IME_CHAR,$2192,0);
                    end
                  else
                    begin
                      delete(L2,richedit1.SelStart-43,1);
                      insert(CaractereRecu[i],L2,richedit1.SelStart-43);
                      richedit1.Lines[2]:=L2; //Affiche la ligne 2 du memo
                    end;
                    L2 := richedit1.Lines[2];
              end;
            3:begin
              if CaractereRecu[i]=#1 then
                begin
                  delete(L3,richedit1.SelStart-65,1);
                  richedit1.Lines[3]:=L3;
                   richedit1.SelStart := SendMessage(richedit1.Handle, EM_LINEINDEX, ligne, 0)+colonne;
                  sendmessage(Richedit1.handle,WM_IME_CHAR,$2192,0);
                end
              else
                begin
                  delete(L3,richedit1.SelStart-65,1);
                  insert(CaractereRecu[i],L3,richedit1.SelStart-65);
                  richedit1.Lines[3]:=L3; //Affiche la ligne 3 du memo
                end;
                 L3 := richedit1.Lines[3];
              end;
          end;
           inc(colonne);
//          L0 := richedit1.Lines[0];
//          L1 := richedit1.Lines[1];
//          L2 := richedit1.Lines[2];
//          L3 := richedit1.Lines[3];
        end;
      end;
  end;
    Timer1.Enabled := false;
end;
Commenter la réponse de YB28
cs_yanb 260 Messages postés lundi 27 octobre 2003Date d'inscription 4 mars 2016 Dernière intervention - 30 mai 2012 à 09:34
0
Merci
Salut,
effectivement c'est un peu long
Le principal c'est que ça fonctionne...
Je vais quand même faire quelques remarques
Pourquoi véritablement utiliser une limite de 250 bytes alors que tu pourrais traiter la trame complète, chaque événement de RxChar est bien une trame complète ?
Peut-être même utiliser SetLength, High, Low, Length, String, StringReplace, TList, TStringList, PWideChar, Trunc...
En fait c'est juste une idée pour simplifier ton code et t'éviter des boucles for, des remplacements, recherche de position etc...
C'est aussi un peu en fonction de la "tête" de la trame...
Voilà c'était juste une idée pour te donner des pistes d'amélioration et d'optimisation mais si ton code de convient dans la forme actuelle
Bon courage @+
Commenter la réponse de cs_yanb
YB28 39 Messages postés lundi 23 avril 2012Date d'inscription 29 juillet 2012 Dernière intervention - 30 mai 2012 à 10:06
0
Merci
C'est vrai que 250 c'est grand. Je recois des tarmes qui varies autour d'une vingtaines de caractères.
Je te remercie de tes remarques, je vais en tenir compte pour l'optimisation de mon projet ;)
Merci !
Commenter la réponse de YB28

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.