ABCelectronique : portail d'information dans le domaine de l'électronique
Recherche sur le site
  Home » Forums de disscussion  

Voir la version complète : Buffer circulaire


mali3
10/05/2006, 15h50
Voila j'ai réalisé un buffer circulaire dans lequel des données provenant d'un hyperterminal, via un port série. Ceci fonctionne parfaitement.
Mon probleme est de pouvoir réaliser des test sur les caractères reçus.
Par exemple, si je reçoit "p1234567891234567" je dois réaliser une programmation d'une étiquette (non détaillée ici). Je regarde si j'ai reçu le caractère "p", puis j'attends les 16 prochains caractères.
A savoir que mon buffer, s'appelle buff[32].
Tout se passe bien quand les 17 caractères se situe avant la fin du buffer. En effet si par exemple j'ai ceci dans buff:

buff[30]=p
buff[31]=1
buff[0]=2
buff[1]=3
.
.
.
.
buff[14]=7

(buffer ciculaire)

Dans ce cas je ne sais pas comment pouvoir tester les caractères reçus.
Je possède un pointeur "b" qui s'incremente suivant le nbr de caractère reçu..

Si quelqu'un peux m'aider..

Merci

mali3
10/05/2006, 15h55
Petit détails je programme un pic 18f252 en langage c avec Mplab ICD2.

Beldin
10/05/2006, 16h24
Je ne vois pas trop où tu as un problème.
Il suffit de gérer la lecture comme l'écriture.
A savoir test apres chaque lecture du pointeur correspondant et remise à 0 si il vaut 33.

mali3
10/05/2006, 16h29
voici le bout de prgramme d'écriture:


void high_isr0 (void) // interruption sur reception usart
{
bu1[b]=RCREG; // stockage des caractères recus dans bu1[]
b++;

if(b==33)
{
b=0;
}
b1=1; // b1=1 mode reception


}


Comment ferais tu pour pouvoir réaliser la lecture avec les test?

Beldin
10/05/2006, 16h46
Je réfléchirais ;-). Bon ok elle est facile....
Plus sérieusement. Voci comment je ferais :

int index_lect; //initialisé à 0 en début de prog dans le main

int lect(int size)
{
for(i=0; i<=size; i++)
{
if (bu1[index_lect] == 'x')
//traitement
else if....
//traitement 2
index_lect ++;
if (index_lect == 33)
index_lect = 0;
}
}

size représentant le nombre d'octets à lire. C'est une solution parmi tant d'autres qui devrait marcher (boiter?).
Attention, il faut encore réfléchir à comment gérer le compteur size.
Un conseil, commence par mettre sur le papier avec des "mots" ce que tu veux faire.
Un soft ca commence par une spécification, une définition de protocole quand on parle d'échange de données. Ensuite on fait la conception, le codage et enfin la validation.
Il me semble que tu veux aller trop vite. Essaie de relire le post #31 et les suivants de Vincent++ sur la précédente discussion. Ce sont des bases qu'il faut arriver à assimiler. Cela fait gagner beaucoup de temps ensuite.

mali3
10/05/2006, 16h49
ok merci beaucoup et bonne soirée..

mali3
10/05/2006, 16h58
Mon protocole est deja définit, et en ce qui concerne la taille du message, je ne vois pas comment y traité. En effet j'ai essayé avec deux pointeurs où je réaliser la différence des 2. Mais la donnée reçu est traitée caractère par caractère, donc la différence entre les deux pointeurs est toujours égale à 1.
Mon unique probleme est de réussir a réaliser un test des caractères que je reçoit qui se placent a la fin et au début de mon buffer..

J'ai essayé beaucoup de méthode mais aucune ne marche et je commence à ne plus avoir d'idée..

Beldin
10/05/2006, 17h48
C'est très rudimentaire, peut-être pas adpaté mais il me semble que ca devrait fonctionner :


// hypotheses de départ : on recoit les données par 16 systematiquement.
// Les timing permettent de lire l'ensemble de la trame entre deux receptions
// cette dernière remarque implique que size n'est pas incrémenté
// (interruption jamais activée) pendant la lecture

char buffer[32]
int index_write;
int index_read;
int size;

void high_isr0 (void) // interruption sur reception usart
{
buffer[index_write]=RCREG; // stockage des caractères recus dans bu1[]
index_write++;
size ++;

if(index_write==33)
index_write=0;

if (size==33)
size=0;
}

int lect(int size)
{
if ( (size != 0) && (size < 16))
{
for(i=0; i<size; i++)
{
//exemple de traitement à adapter
if (buffer[index_read] == 'x')
//traitement x
else if (buffer[index_read] == 'y')
// traitement y
else if (buffer[index_read] == 'z')
{
index_read ++;
i++;
if(index_read == 33)
index_read = 0;
if(buffer[index_read] == 'a')
//traitement
}
index_read ++;
if (index_read == 33)
index_read = 0;
}
size = 0;
return 0;
}
else
{
return -1;
}
}

int main(void)
{
index_write = 0;
index_read = 0;
size = 0;
while(1)
{
if (size == 16)
{
if (lect(size) != 0)
print("Reception NOK");
else
print("Reception OK");
}
}

return 0;
}

mali3
11/05/2006, 08h19
Voici le bout de rpog que j'ai réalisé:


void lect1(void)
{
while (b!=y)
{
if((b-y)>0)
{
for(i=y;i<b;i++)
{
temp[i]=bu1[i];
}
}
else
{
nb=b-y+32;
for(i=y;i<33;i++) temp[i]=bu1[i];
nbrestant=nb-(32-y);
for(i=0;i=nbrestant;i++) temp[i]=bu1[i];
}
y++;
if(y==33)
{
y=0;
}

}
}


void high_isr0 (void) // interruption sur reception usart
{
bu1[b]=RCREG;
b++;

if(b==33)
{
b=0;
}
}



void main(void)
{
if(b1==1)
{
lect1();

for(i=0;i<y;i++)
{

if(temp[i]=='p'||temp[i]=='P')
{
if(temp[i+16]!=0)
{
...........
.............
}
}
}
}
}


Voila; j'ai donc deux buffer circulaire, en faite bu1 est recopié dans temp. J'ai aussi 2 pointeurs, b pour le remplissage et y pour la lecture. Les 2 buffers sont bien des buffers circulaires, le seul probleme c'est que quand j'attends les 16 caractères apres la lettre "p", si ceux ci se situent a la fin et au début du buffer cela ne marche pas.
En effet, si par exemple la lettre "p" se trouve a la case 28 (bu1[32] et temp[32]), lorsque je réalise "if(temp[i+16]!=0)" , le pic ne comprends pas car pour lui temp[i+16]=temp[28+16] soit temp[44], or moi je veux que cela soit temp[8]..

Je sais pas si j'ai été clair mais voici le gros probleme que je rencontre..

Merci.

Beldin
11/05/2006, 09h07
J'ai bien compris ton problème. C'est donc que tu as un souci d'algo. Il faut faire autrement.
Si tu veux passer par une copie de bu1[] dans temp[], il te suffit de copier bu[28] à bu[11] dans temp[0] à temp[15]. C'est juste une gestion d'indices. Et dans ce cas ta fonction de traitement avec temp[i+16] sera toujours bonne.

mali3
11/05/2006, 09h21
J'ai deja essayé de le faire mais je ne sait pas comment y faire..dsl ************ Pas de SMS , veuillez corrigez votre texte *** ******************** Pas de SMS , veuillez corrigez votre texte *** ******** je suis débutant en programmation..

Merci pour ton aide

mali3
11/05/2006, 09h23
J'ai deja essayé de le faire mais je ne sait pas comment y faire..désolé mais je suis débutant en programmation..

Merci pour ton aide

Beldin
11/05/2006, 09h48
Ya pas de mal. On en passe tous par là.
Je ferais ca :

//si y pointe sur le prochain caractere à lire : 30
//On a recu 16 octets => b pointe sur le prochain caractère à ecrire : 14
//Rque : le dernier caractere à lire est bien 13
// a la fin de la lecture y vaut 14

void lect1(void)
{
int size=0;
if (b<y)
{
size = 32-y; //size = 2
size += b; //size = 2 + 14 = 16
}
else
size = b-y;

for(i=0;i<size;i++) // Pour i de 0 à 15 : 16 octets
{
temp[i]=bu1[y];
y++;
if(y==32)
y=0;
}
}

mali3
11/05/2006, 10h04
Je veux pas que tu le prenne mal, mais j'ai essayé ton bout de rpog et ça ne marche pas.. quand je tape une premiere fois "p111...1111", ça m'écrit dans temp[] juste un "1" à temp[0], puis si je renvoi "p111...11" ( cas ou le buffer bu1 revient à 0), ça me réecrit tous les caractères que j'ai dans bu1[] dans temp[]..

Merci beaucoup de m'aider ..

Beldin
11/05/2006, 10h19
C'est fort possible.
Ma fonction copie x octets correspondant entre l'ecart b-y de bu1 dans temp.
Si au moment ou elle est appelée y=0 et b=1 elle ne copiera que 1 octet. Si la deuxième fois que tu l'appelles y=1 b=0, ca copie les 31 autres octets.
Bienvenue dans le monde du débogage...

Quelques conseils avant que je me déconnecte sachant que tu as déjà fais la moitie du travail :
1 - développe la fonction de traitement et valide la SEULE en déclarant en dur ton tableau temp.
2 - développe ta fonction de copie (celle que j'ai donnée adaptée?) et valide la SEULE avec deux tableaux codées en dur et des indices que tu fixes toi "à la main".
3 - développe ta fonction de réception et valide la SEULE en vérifiant que ton tableau bu1 est bien rempli et les indices bien mis à jour.
4 - tes trois fonctions sont validées. Tu sais ce qu'elles font exactement. Réunies les dans un même programme et fais les "ajustements" nécessaires au bon fonctionnement de l'ensemble.

Pour moi ton souci viens du main : tu n'appelles pas la fonction de lecture au bon moment.

mali3
11/05/2006, 10h28
le probleme , quand j'envoi plusieurs caractères, ils sont traitées un par un, c'est à dire que l'écart en b et y n'est jamais supérieur à 1, donc il n'est pas possible de calculer la taille du message reçu.
Deplus j'ai l'impression, que par exemple quand b passe de 31 à 0 et que y est à 31 (donc b-y<0), on ne rentre jamais dans la conditon (if(b-y<0)) ...

Le buffer bu1[] fonctionne parfaitement , mon probleme est dans le recopiage de bu1 dans temp à partir de temp[0]..

mali3
11/05/2006, 16h04
Voici mon prog:



void lect1(void)
{
if (b!=y)
{

if(b>y)
{
for(i=y,j=0;i<b;i++,j++)
{
temp[j]=bu1[i];
}


}
else
{

for(i=y,j=0;i<33;i++,j++) temp[j]=bu1[i];

for(i=0,j;i=b;i++,j++) temp[i]=bu1[j];
}
}
}


void high_isr0 (void) // interruption sur reception usart
{
bu1[b]=RCREG;
b++;

if(b==33)
{
b=0;
}

b1=1;
}




main void(main)
{
if(b1==1)
{
for(i=y;i<b;i++)
{

if(bu1[i]==112||bu1[i]==80)
{
if(bu1[i+16]!=0)
{

lect1(); for(i=0;i<y;i++) temp[i]=0;
b1=0;
}
}
}
}



Voila le probleme est que je ne sais pas ou placer l'incrementation du pointeur de lecture (y).

Beldin
11/05/2006, 16h48
void lect1(void)
{
if (b!=y)
{

if(b>y)
{
for(i=y,j=0;i<b;i++,j++)
{
temp[j]=bu1[i];
y++
}


}
else
{

for(i=y,j=0;i<33;i++,j++)
{
temp[j]=bu1[i];
y++;
}
y=0
for(i=0,j;i=b;i++,j++)
{
temp[i]=bu1[j];
y++;
}
}
}
}

pazcal
11/05/2006, 17h26
Le plus simple c'est de gérer des buffers circulaires avec des modulo.... Ou encore des puissances de 2, comme ca, pas de test, un simple incrément.... sans précaution....
Sinon, tu peux aussi utiliser des listes chainées...
mais bon, un truc du genre :
char buffer[32];
char v;
while (TaCondition)
{
v = ++buffer%32;
Traite(v);
}
A plus

mali3
12/05/2006, 10h08
ok merci , je suis pas sur que c'est bien adapté a ce que je recherche . Merci quand meme..
Si quelqu'un a d'autres idées n'hésité pas..

mali3
12/05/2006, 14h20
Pour Beldin:

[code]

void lect1(void)
{
if(ecriture-lecture>0)
{
for(i=lecture,j=0;i<ecriture;i++,j++)
{
temp[j]=bu1[i];
lecture++;
}


}
else
{

nb=ecriture-lecture+32;
for(i=lecture,j=0;i<33;i++,j++) temp[j]=bu1[i];
nbrestant=nb-32-lecture;
for(i=0,j;i=nbrestant;i++,j++) temp[i]=bu1[j];
}
}
}

void high_isr0 (void) // interruption sur reception usart
{

bu1[ecriture]=RCREG;

ecriture++;

if(ecriture==33)
{
ecriture=0;
}

carac_recu=1;

}


void main(void)
{
while(carac_recu==1)
{
for(i=lecture;i<ecriture;i++)
{
if(bu1[i]=='p' || bu1[i]=='P')
{

if(bu1[i+16]!=0)
{
lect1();
carac_recu=0;
}

}
}
}
}

[\code]

Mes deux pointerus (b et y) ont étaient rapellés ecriture(b) et lecture(y).

pazcal
12/05/2006, 14h59
Pourtant ca colle exactement avec ce que tu veux faire .... Lire des données stockées dans un buffer circulaire sans te préoccuper de la fin/début du buffer...

char wbuf[SIZE];
char rbuff[SIZE];
readbuff(char Offset)
{
int i = Offset;
int j = 0;
for (i = Offset; i< Offset + TAILLE_TRAME; i++)
{rbuffer[j] = wbuff[i];
++i%SIZE;
++j%SIZE;
}
}
Ca copier le contenu de ton buffer w (ecrit par l'hyperterm) dnas un buffer de traitement. Il faut fournir l'offset du buffer W ou tu as ton caractere 'p' de debut de trame... les 2 buffers se vident et se remplissent de facon circulaire... sans que tu te préoccupes des bornes...
A plus

Beldin
12/05/2006, 15h17
Mali :
nbrestant=nb-32-lecture;
for(i=0,j;i=nbrestant;i++,j++) temp[i]=bu1[j];

Tu réécrases temp[0].
il faut au moins faire
for (i=0;i<nbrestant;i++,j++) temp[j] = bu1[i];

Beldin
12/05/2006, 15h18
Le soft ce n'est pas du "bidouillage jusqu'a ce que ca marche". Il faut reflechir un peu avant de faire les choses.

mali3
15/05/2006, 08h46
Le probleme c'est que j'ai réfléchis, mais la je suis bloqué et je ne trouve plus d'autre solution pour me débloquer.
Si quelqu'un a des idées qui pourraient m'aider, n'hésité pas ..

Merci et bonne journée.

mali3
16/05/2006, 10h13
Je relance ce post histoire de voir si des personnes peuvent m'aider...

mali3
16/05/2006, 15h22
Hello,
Je vous relance pour savoir si quelqu'n connait un astuce ou une adresse qui pourrait me décoincer..
Merci et bonne journée.

pazcal
16/05/2006, 15h46
Heuuuu, je pige pas trop la... Tu as toutes les infos, ou se situe ton problème?
A mon avis, c'est la bonne adresse.... Tu veux faire un buffer circulaire, le plus simple, c'est d'utiliser les incrément avec un modulo... Le modulo, tu peux le faire avec un masque, ou un opérateur % en C.
A plus

Vincent++
16/05/2006, 17h50
Je pense qu'il faut revoir ton algorithme et ne pas essayer de rafistoler le programme existant.

A+
Vincent

mali3
17/05/2006, 07h41
ok merci, je vais reprendre mon algorithme et je vous tiendrez au courant si il fonctione..