Bah, compile ce que tu as posté, tu verras bien...Citation:
Envoyé par Emcy
Version imprimable
Bah, compile ce que tu as posté, tu verras bien...Citation:
Envoyé par Emcy
ça compile chez moi mais je ne t'ai pas mis tout le code...
Ben oui, donc ça ne compile pas chez moi. C'est si dur à comprendre, ça ?Citation:
Envoyé par Emcy
1 - Compile CE QUE TU AS POSTE.
2 - Tant que ça ne compile pas, ajoute ce qui manque...
3 - Poste le code.
Si ton code ne compile pas, je ne regarde pas.
OK, désolé...je saurais pour la prochaine fois
rebonjour,
voila ma structure
=> le problème est mon µC n'a pas l'air d'apprécier ce système sur des champs de plus de 8bits, j'ai le message :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 typedef struct _StructL { unsigned int Member:6; unsigned int Tagged:6; unsigned int FID:4; } StructL; typedef struct _StructH { unsigned int VID:12; unsigned int Priority:3; unsigned int Enb:1; } StructH; typedef struct _StructVLAN { StructL L; StructH H; } StructVLAN; extern StructVLAN TabVLAN_Filter2[16];
Error [1171] bitfield width greater than 8 detected
y a t-il un moyen de resoudre le problème ?
remarque :
si je remplace : unsigned int VID:12; par unsigned int VID:6;
=> je n'ai plus d'erreur
Coupe le en deux et gère le à la main (opérateurs binaires) :Citation:
Envoyé par Emcy
ecriture :Code:
1
2
3
4
5
6
7
8 typedef struct /* _StructH -ed- tag inutile et non conforme supprimé... */ { unsigned int VID_MSB:4; /* 0000 xxxxxxxx .. 1111 xxxxxxxx*/ unsigned int VID_LSB:8; /* xxxx 00000000 .. xxx 11111111 */ unsigned int Priority:3; unsigned int Enb:1; } StructH;
Lecture :Code:
1
2
3
4
5 unsigned vid = 4095; xxx.VID_MSB = vid >> 8; xxx.VID_LSB = vid;
Code:
1
2
3
4
5 unsigned vid = 0; vid |= xxx.VID_MSB << 8; vid |= xxx.VID_LSB;
on perds l'avantage d'utiliser des champs de bits
finalement, je vais partir sur une autre solution
je crée deux structure (une pour mes données sérialisées et une pour facilité l'utilisation) :
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 typedef struct _StructVLAN { unsigned int L; unsigned int H; } StructVLAN; extern StructVLAN TabVLAN_Filter[16]; typedef struct _StructVLAN_var { unsigned char FID; unsigned char Tagged; unsigned char Member; unsigned char Enb; unsigned char Priority; unsigned int VID; } StructVLAN_var;
je crée deux fonction : une pour la lecture et une pour l'écriture :
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 StructVLAN_var GetVLANFilter_Elm(unsigned char i) { StructVLAN_var varVLAN; unsigned int temp; temp = TabVLAN_Filter[i].L; varVLAN.Member = temp & 0x003F; // 6 bits temp >>= 6; varVLAN.Tagged = temp & 0x003F; // 6 bits temp >>= 6; varVLAN.FID = temp; // 4 bits // ****************************************** temp = TabVLAN_Filter[i].H; varVLAN.VID = temp & 0x0FFF; temp >>= 12; varVLAN.Priority = temp & 0x0007; temp >>= 3; varVLAN.Enb = temp; // ****************************************** return varVLAN; } void SetVLANFilter_Elm(StructVLAN_var varVLAN, unsigned char i) { unsigned int temp = 0; temp = varVLAN.FID; // 4 bits temp <<= 4; temp |= varVLAN.Tagged; // 6 bits temp <<= 6; temp |= varVLAN.Member; // 6 bits TabVLAN_Filter[i].L = temp; // ***************************************** temp = varVLAN.Enb; // 1 bit temp <<= 1; temp |= varVLAN.Priority; // 3 bits temp <<= 3; temp |= varVLAN.VID; // 12 bits TabVLAN_Filter[i].H = temp; }
après, l'utilisation est assez simple :
Code:
1
2
3
4
5
6
7
8
9
10 StructVLAN_var varVLAN; varVLAN = GetVLANFilter_Elm(i); varVLAN.Enb = 1; ... ... varVLAN.Member = 6; SetVLANFilter_Elm(varVLAN, i);
Bah, quand on a des int de 8-bit (non conforme C standard), on fait comme on peut..., mais ce que je propose est d'une banalité affligeante... Pas besoin d'en faire plus...Citation:
Envoyé par Emcy
Argh, non. Tu vas bouffer de la mémoire auto comme un fou... Interdit en 8-bit, pas assez de ressources. Utilise les pointeurs :Citation:
je crée deux fonction : une pour la lecture et une pour l'écriture :
Code:
1
2
3
4 StructVLAN_var GetVLANFilter_Elm(unsigned char i) { StructVLAN_var varVLAN; unsigned int temp;
ou tu retournes la valeur.Code:
1
2 set (T *p, ... data) get (T const *p, ... *pdata)
Ok, merci beaucoup
j'ai pas bien compris, c'est quoi le parametre que tu passe en "const" ?
c'est quoi de la memoire auto ?
J'avoue que je ne maitrise pas beaucoup la gestion de consommation des ressources (gestion des différentes memoires, consommation CPU,....)
Est-ce que tu as des conseils la dessus (ou un cours) ?
Personnelement, j'aurais tendance à passer à mes fonctions que des pointeurs : dans quel cas faut-il passer les parametres par pointeur et dans quel cas, faut-il les passer par valeur ?
L'adresse d'un objet (pour toi, une structure). Comme la fonction ne modifie pas l'objet, j'ajoute le qualificateur const (signifie 'lecture seule'). Ca évite de coder n'importe quoi !Citation:
Envoyé par Emcy
Ayant beaucoup codé en assembleur sur microcontrôleur (8051), dans les années 90, j'ai appris à économiser la mémoire. Je ne connais pas le PIC, mais je suppose qu'il y a les même problèmes (mémoire très réduite, quelques centaines d'octets en interne, quelque milliers en externe, c'est ça ?)Citation:
J'avoue que je ne maitrise pas beaucoup la gestion de consommation des ressources (gestion des différentes memoires, consommation CPU,....)
Est-ce que tu as des conseils la dessus (ou un cours) ?
Le C sur petit micro-contrôleur doit être manié avec encore plus de précautions, car on a vite fait de faire n'importe quoi et à exploser sa pile (mémoire automatique)...
Ben c'est pas ce que j'ai vu !Citation:
Personnelement, j'aurais tendance à passer à mes fonctions que des pointeurs :
Les passages de paramètres en C se font exclusivement par copie de valeur, mais cette valeur peut être une adresse !Citation:
dans quel cas faut-il passer les parametres par pointeur et dans quel cas, faut-il les passer par valeur ?
On choisi ce qui fait le moins de recopies et qui prend le moins de mémoire auto (pile).
mon µC (c'est du standard) a 64Ko de falsh, 3986Ko de SRAM, 1024Ko d'EEPROM et tourne à 25MHz.
cette solution consome moins de memoire auto :
que cele-ci ?Code:
1
2
3
4 void ecriture(char *toto) { *toto *= 2; }
si c'est le cas, je ne vois pas dans quel cas il ne faut pas utiliser les pointeurs....Code:
1
2
3
4
5 char ecriture(char toto) { toto *= 2; return toto; }
Je pense que les deux consomment autant dans un cas comme celui-ci.
Mais la seconde est sans doute plus performante.
pour la mémoire je sais pas, mais char*2 a de bonnes chances de plus être un char.... :mouarf:
129*2 .......
Pour le topic originel, j'aurai plutôt utiliser une union (c'est ce que je fait tout le temps). Ca donne un truc du genre
L'accès mémoire se fait avec tabVal et l'accès données se fait avec strVal.Code:
1
2
3
4
5
6
7
8
9 typedef union { char tabVal[2]; struct strVal{ unsigned int VID_MSB:4; /* 0000 xxxxxxxx .. 1111 xxxxxxxx*/ unsigned int VID_LSB:8; /* xxxx 00000000 .. xxx 11111111 */ unsigned int Priority:3; unsigned int Enb:1; }tMyData;
C'est assez robuste et fait un code clair.
=> ah je connaissais pas, merciCitation:
Envoyé par DaffyDuck
"pour la mémoire je sais pas, mais char*2 a de bonnes chances de plus être un char.... "
=> c'est juste pour donner un exemple...
"Mais la seconde est sans doute plus performante."
=> pourquoi ?
Parce qu'il y a un niveau d'indirection en moins, et que la valeur de retour est souvent stockée directement dans un registre.
Avec un accès par un pointeur, la variable est forcément en mémoire, à moins que l'optimiseur ne choisisse d'inliner la fonction.
=> oulala, c'est trop compliquer pour moi ça :(Citation:
Envoyé par Médinoc
puis-je avoir les définitions de :
- niveau d'indirection
- inliner la fonction
- niveau d'indirection : Dans le contexe 'pointeurs', une indirection = une *.Citation:
Envoyé par Emcy
- inliner la fonction : le compilateur replace l'appel de la fonction par du code direct (C ou assembleur 'inline').
Il n'y a plus d'appel de fonction. C'est particulièrement efficace pour des petites fonctions très simples. On conserve une organisation bien structurée, mais le compilateur simplifie le code et l'optimise (pas d'appel, pas d'empilage de paramètres...). Pour du code très court, c'est intéressant. Par exemple strlen() ou strcpy() est souvent 'inliné' par le compilateur. C'est particulièrement recherché en embarqué.
d'accord, merci
Pour étoffer le coté inline, tu peux aussi écrire des fonctions qui ne te servent qu'à un endroit du code, de façon à éclaircir ton code (par exemple ecrire une fonction initPeripheriques() dans ton main()). Si elle ne sert qu'une fois, tu la mets inline pour éviter d'avoir à faire des appels et prendre de la place mémoire et du temps d'exécution et ce sans éviter de faire un code lisible.