PIC18 et langage C : j'ai un pb de débutant...

Bonjour à tous, avant j'étais pic16 et assembleur mais comme je passe aux pic18 je me confronte maintenant au langage C, et c'est le début j'ai du mal... Il me semble que je passe a côté de trucs élémentaires, donc si tu veux bien jeter un oeuil sur mon code, merci de critiquer !

Je vous expose mon problème : sur le portB j'ai un clavier en matrice

4x4. RB0-3 en entrées, RB4-7 en sorties, Résistances de pullup actives, interruptions désactivés.

Mon programme principal fait régulièrement un appel de la fonction "LireTouche()", elle met à jour ma variable "touche" qui devrait contenir le code de la touche activée. Le problème est que "Touche" ne contient pas toujours le bon code, ça marche bien pour environ 80% des touches, mais pour certaines elle me renvoie un mauvais code.

BOOL LireTouche(void) { /* Variables Locales */ BYTE CLAVier;

/* Instructions */ mInitClavier(); Touche=0; // variable qui contiendra le code de la touche appuyée

CLAV=0b00001110; // Charge le masque de la 1ere ligne (RB0=0) (RB0-3 en sorties) CLAVier=CLAV; // effectue une lecture du Clavier (RB4-7 en entrées) if(CLAVier & 0b00010000) ; else Touche = 0b00010001; //RB4 Clic Droit if(CLAVier & 0b00100000) ; else Touche = 0b00100001; //RB5 Bas Droite if(CLAVier & 0b01000000) ; else Touche = 0b01000001; //RB6 Bas if(CLAVier & 0b10000000) ; else Touche = 0b10000001; //RB7 Bas Gauche

CLAV=0b00001101; // Charge le masque de la 2e ligne (RB1=0) CLAVier=CLAV; if(CLAVier & 0b00010000) ; else Touche = 0b00010010; //RB4 if(CLAVier & 0b00100000) ; else Touche = 0b00100010; //RB5 if(CLAVier & 0b01000000) ; else Touche = 0b01000010; //RB6 if(CLAVier & 0b10000000) ; else Touche = 0b10000010; //RB7

CLAV=0b00001011; // Charge le masque de la 3e ligne (RB2=0) CLAVier=CLAV; if(CLAVier & 0b00010000) ; else Touche = 0b00010100; //RB4 if(CLAVier & 0b00100000) ; else Touche = 0b00100100; //RB5 if(CLAVier & 0b01000000) ; else Touche = 0b01000100; //RB6 if(CLAVier & 0b10000000) ; else Touche = 0b10000100; //RB7

CLAV=0b00000111; // Charge le masque de la 4e ligne (RB3=0) CLAVier=CLAV; if(CLAVier & 0b00010000) ; else Touche = 0b00011000; //RB4 if(CLAVier & 0b00100000) ; else Touche = 0b00101000; //RB5 if(CLAVier & 0b01000000) ; else Touche = 0b01001000; //RB6 if(CLAVier & 0b10000000) ; else Touche = 0b10001000; //RB7

if (Touche!=0) return TRUE; } //Fin de LireTouche()

Voilà, j'espère que l'exposé de ma situation aura été asses clair. Qu'est-ce qui ce passe d'après vous ?

Laurent

Reply to
Laurent CLAUDE
Loading thread data ...

Pourquoi tu utilises une variable globale eu lieu de renvoyer la valeur directement par la fonction ?

Ensuite tu écris des choses du genre if() ; else Touche = ; ... Ce qui veut dire, "si est vrai, alors ne rien faire, sinon mettre Touche = ". Je ne pense pas que ce soit ce que tu veux faire. Ca m'étonne même que ton code marche dans 80% des cas ;-)

La fonction peut être remplacée par :

BYTE LireTouche(void) { BYTE row, col;

mInitClavier();

for(row=0x08; row != 0; row >>= 1) { CLAV = 0x0F & ~row; for(col = 0x80; col != 0x08; col >>= 1) { if(CLAV & col) return row | col; } }

return 0; }

v.

Reply to
vic

Le 15/04/2010 15:02, vic a écrit :

Parce que j'y vais progressivement...

si si, c'est ce que j'ai besoin, car si ma touche est appuyée alors je lit un zéro en entrée (logique inverse). et je ne sais pas faire le test 'ET-NON' !

waow, nickel, c'est dense ! j'ai juste modifié le 'if' par : if(CLAV & col) ; else return (col | row);

pour l'histoire du ET-NON, et pour rétablir l'ordre des lignes/colonnes qui étaient inversées.

En tous cas merci beaucoup vic, c'est efficace et ça tourne au poil ! Tu viens de m'aider d'une étape dans mon ascension du mont "C" ...

Laurent

Reply to
Laurent CLAUDE

vic a tapoté du bout de ses petites papattes :

C'est, je suppose, une vieille coutume qui vient de certains compilos qui ne permettaient pas d'utiliser directement le retour d'une fonction et il fallait la mettre dans une variable pour jouer avec. Je fais toujours pareil par précaution. Mais quand on fait du C proche machine, surtout avec des ressources limitées, c'est évidemment un peu grossier. C'est l'avantage de l'assembleur (en plus de la vitesse), on a un nombre précis (et des formats) de registres et des emplacements mémoire. Un assembleur ne peut pas te jeter à cause d'un retour de fonction mal utilisé (enfin sauf si c'est dans la stack et que tu dépiles mal, mais bon, c'est un métier, hein ? ;) ).

--
LeLapin
Reply to
LeLapin

OK, je n'avais pas trop fait attention à ça en répondant, car je ne savais pas comment était branché ton clavier. Le "NON" en C, c'est "!" :

Tu peux écrire aussi : if(!(CLAV & col)) return col | row;

Pour info col | row == row | col.

Essaie de trouver un tutoriel sur Internet avec les bases du langage, les opérateurs logiques, les structures de contrôle, etc, ça te sera utile ;-)

v.

Reply to
vic

Sur PIC il me semble que la pile est dans un espace mémoire différent de la RAM normale. Mais sur AVR, il se passe parfois des choses marrantes quand le bas de la pile vient toucher le haut du tas. Le problème apparaît quand il y a trop de fonctions imbriquées, et si on débugge la fonction qui pose problème seule, tout marche très bien. Pas évident à debugger la première fois :-)

v.

Reply to
vic

Pour faire cela en C, la fa=E7on la plus idiomatique est:

if ( !(CLAV & col) ) return ( col | row );

ou

#define true 1 #define false 0

if ( (CLAV & col) =3D=3D false) { return col | row; }

l'inconv=E9nient d'un if sans instruction, c'est le risque d'erreur en lisant le code.

--

-Stan

Reply to
Stan

Le Thu, 15 Apr 2010 16:05:29 +0200, Laurent CLAUDE a écrit :

une bonne pratique dans ce genre de chose est de tirer un listing avec les lignes de C et d'assembleur imbriquées.

Ton programme teste les bits. Il y a une instruction test de bit qui existe. Un petit "pragma" (une ligne d'assembleur) ne serait pas une solution ? Je ne connais pas ton compilateur mais cela serait un bon exercice.

Après compares l'expansion entre les 2 solutions ... et le temps CPU.

N'oublies pas que ton environnement est limité.

CH

Reply to
moi-meme

Waow, nickel, merci à tous de vos réactions Oui c'est sûr je dois me documenter un peu plus sur ce langage, mais je ne trouve pas beaucoup d'infos (en français) sur le C pour PIC

j'ai une nouvelle question ! (...qui n'a pas grand chose a voir avec la première, alors je l'imbrique dans ce post pour ne pas surcharger le forum)

J'ai mon prog principal qui est dans le fichier "main.c" et depuis un fichier "MesRoutinesClavier.c" je voudrais avoir accès a une variable déclarée dans main.c On fait comment ?

Laurent

Reply to
Laurent CLAUDE

et toujours dans le registre 'chuicunepovtruf' :

comment faire en sorte qu'une fonction renvoie plusieurs valeurs ?

Ben oui avec "BYTE mafonction(void)" alors ma fonction retourne un octet, mais comment je fais si je veut en retourner 3 d'un coup ?

Reply to
Laurent CLAUDE

Il faut passer l'adresse des variables a l'appel de fonction (avec des pointeurs), la fonction écrit dedans et voila.

Reply to
cLx

Stan, le 15/04/2010 a écrit :

Il me semble que *c'est* la bonne façon. Ou si c'est plus parlant:

if ( !CLAV | !col ) return ( col | row );

C'est risqué. Déjà, une coquetterie fait qu'on préfère parfois:

#define false 0 #define true !false

Mais ça ne change rien.

if (condition == false)

n'est vraiment pas idiomatique, par rapport à tout simplememt:

if(!condition)

Et puis le danger est de définir true à 1 et d'écrire:

if(cond == true)

cond est par exemple cond1 || cond2, ça va bien se passer. Mais si c'est cond1 | cond2, voire 0b00000010, alors ça risque de merder. En revanche, le truc suivant doit être sûr, mais assez ugly:

if(!!cond == true) ou if(!cond != true)

Et comme vous-mêmes utilisez (pourquoi ?) des opérateurs bitwise là où la sémantique est booléenne, il vaut mieux éviter. A mon avis.

En fait, pour la lisibilité, il est préférable de se concentrer sur le nommage que d'introduire des booléens artificiels.

Tout ceci dans le cadre d'un compilateur standard, je n'ai du PIC que l'expérience d'un projet en assembleur. Donc je peux me tromper, si le compilateur PIC est spécifique.

Ou encore pire en le maintenant.

--
Pierre Maurette
Reply to
Pierre Maurette

AVR ? Kézako ? Instruis-moi de toutes ces modernités, j'en suis avide !

--
LeLapin
Reply to
LeLapin

Le Thu, 15 Apr 2010 23:01:26 +0200, Laurent CLAUDE a écrit :

AMHA pour les bases comme pour du C classique en enlevant tout ce qui est en calcul flottant.

Pour les accès bits par contre cela doit dépendre du compilateur. Pour ton traitement particulier il doit y avoir moyen d'y mettre de l'assembleur pour optimiser cette partie.

compares : if(!(CLAV & col)) return col | row; avec : btfsc var,bit goto xx

pas photo au niveau code généré.

Reply to
moi-meme

Voil=E0 ce que c'est de r=E9pondre =E0 un post en regardant la t=E9l=E9 :-)

La conversion implicite d'un int vers le bool n'existe qu'en C++. Mais dans ce cas, la d=E9finition d'un boolean est inutile puisqu'elle existe d=E9ja.

--

-Stan

Reply to
Stan

Je n'ai pas la norme du C99 sous les yeux, mais c'est sans doute pareil.

Mais avant qu'un compilo PIC soit C99...

--

-Stan

Reply to
Stan

"Laurent CLAUDE" a écrit dans le message de news: 4bc77ea9$0$22388$ snipped-for-privacy@news.free.fr...

=============== Vois dans ton livret d'instruction les types de variable (static, extern, auto ...) . Pour un compilateur "c" classique il suffit de les déclarer avant la fonction "main" , elle sera utilisable universellement dans le main et les fichiers < include>

>
Reply to
maioré

Ça passerait avec:

if ( (CLAV && col) == false)

Mais c'est ripoux...

--
Pierre Maurette
Reply to
Pierre Maurette

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.