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

Résolu
YB28 Messages postés 38 Date d'inscription lundi 23 avril 2012 Statut Membre Dernière intervention 29 juillet 2012 - 24 mai 2012 à 16:55
YB28 Messages postés 38 Date d'inscription lundi 23 avril 2012 Statut Membre Dernière intervention 29 juillet 2012 - 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 ;)

6 réponses

cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
26 mai 2012 à 12:21
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 @+
3
YB28 Messages postés 38 Date d'inscription lundi 23 avril 2012 Statut Membre Dernière intervention 29 juillet 2012 1
29 mai 2012 à 11:40
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;
0
cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
29 mai 2012 à 12:43
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;

@+
0
YB28 Messages postés 38 Date d'inscription lundi 23 avril 2012 Statut Membre Dernière intervention 29 juillet 2012 1
29 mai 2012 à 14:57
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;
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
30 mai 2012 à 09:34
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 @+
0
YB28 Messages postés 38 Date d'inscription lundi 23 avril 2012 Statut Membre Dernière intervention 29 juillet 2012 1
30 mai 2012 à 10:06
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 !
0
Rejoignez-nous