Formation aux PIC

"LeLapin" a écrit dans le message de news: XnF9C8AC470BE1B9lapinou@217.112.180.250...

========== Les operations mathématiques (particuliérement chez HP) sur les premiers ordinateurs (langage proche du langage machine , comme d'ailleurs certaines calculatrices programmables un peu après ) s'organisaient en notation polonaise (inverse) exemple:

2 [enter] 5 [enter]
  • [enter] resultat 7
3 [enter]
  • [enter] résultat 21
Reply to
maioré
Loading thread data ...

Exact ! J'avais essayé de faire avec deux entiers :

a = a^b; b = a^b; a = a^b;

Cela inverse a et b sans utiliser de variable temporaire, moins d'accès mémoire et tout ça, en seulement trois cycles...

Gcc avec les options d'optimisations activées a compris la manoeuvre, a viré les xors et a codé ça de façon différente. Outch !

Et le pire, c'est que le test était au début, avant que je ne lui empêche :

printf("%d %d\n", a, b); a = a^b; b = a^b; a = a^b; printf("%d %d\n", a, b);

... qu'il a remplacé par :

printf("%d %d\n", a, b); printf("%d %d\n", b, a);

Le petit malin ;))

N'empêche, c'est assez impressionnant, je trouve.

--
cLx
Reply to
cLx

maioré se fendait de cette prose :

Je ne considère pas les calculettes programmables comme des µP, ni même comme des processeurs de minis et de mainframes, ça n'a rien à voir. Je ne vois donc toujours pas le rapport. La syntaxe de tous les processeurs depuis Von Neumann est sous la forme "instruction - cible et/ou objet". Votre exemple serait donc (dans un code simplifié imaginaire) : Mov x, #2 Add x, #5 Mul x, #21... Je ne vois rien de polonais là-dedans, à la rigueur un peu de hongrois ;)

--
LeLapin
Reply to
LeLapin

"Philippe" a écrit dans le message de news:

4ab3cde0$0$10016$ snipped-for-privacy@news.free.fr...

wouha, super obfuscatoire !

si je dois recruter un programmeur, je disqualifie un gars qui m'écrit ça... :-)

Reply to
Stephane Legras-Decussy

"cLx" a écrit dans le message de news: h90koq$1i3$ snipped-for-privacy@news.trigofacile.com...

pareil.... et encore plus impressionnant, l'intelligence des gars capables d'écrire GCC...

Reply to
Stephane Legras-Decussy

"Eric PETIT" a écrit dans le message de news:4ab29a3a$0$11330$ snipped-for-privacy@news.free.fr...

Moi je trouve pas, pour le fun je colle ci dessous un programme en C que j'ai écris en 2 ou 3 soirées, sur un tout petit 12F675 (8 broches) vraiment minuscule, je précise que je n'avais jamais approché de près ni de loin ce composant, c'est un petit automate à état pour controler de façon soit manuelle soit full-automatique suivant le temps d'appui sur les boutons, avec gestion des e/s (capteurs, vérins, boutons, un buzzer) l'ouverture et la fermeture d'une capote électrique de voiture sans connaitre le moins du monde l'assembleur de ce composant et comme vous pouvez le voir il n'y a pas la moindre ligne de code asm("....") .

Je suis sur que même un débutant saura comprendre comment ça marche sans y passer des nuits parce que "visuellement" ça ressemble à quelque chose, c'est simpliste et j'aurais pu le faire en assembleur, mais franchent, aucun interet. et si demain ce composant n'est plus dispo, en adaptant quelques trucs je peux passer à un autre modèle qui n'a rien à voir ou même une autre marque (atmel par exemple que j'aime bien aussi car très performants) en changeant juste les port io, l'initialisation et la gestion du timer qui est un peu différente.

#include

__CONFIG(CPD & PROTECT & BOREN & MCLRDIS & PWRTEN & WDTEN & INTIO);

// Tempo de passage en automatique #define AUTO_TIMEOUT 20 // 2 secondes (valeur exprimée en 1/10 de s car le timer tourne à 10Hz)

// E/S #define OPEN_PUSHED GPIO0 // ENTREE bouton 'ouverture' logique positive #define CLOSE_PUSHED GPIO1 // ENTREE bouton 'fermeture' logique positive #define CMD_BUZZER GPIO2 // SORTIE buzzer, logique positive #define PUMP_STOPPED GPIO3 // ENTREE entrée pompe, logique inverse (1 = pompe arrétée, 0 = pompe en marche) #define CMD_NOT_OPENING GPIO4 // SORTIE commande d'ouverture logique NEGATIVE (1 = repos, 0 = simul bouton ouverture) #define CMD_NOT_CLOSING GPIO5 // SORTIE commande de fermeture logique NEGATIVE (1 = repos, 0 = simul bouton fermeture)

// Etats de l'automate typedef enum STATE { STOPPED, // A l'arret (capote ouverte, fermée ou arrétée en cours de cycle) MANUAL_OPENING, // Ouverture en mode manuel MANUAL_CLOSING, // Fermeture en mode manuel AUTO_OPENING, // Début d'ouverture en mode auto après tempo et bouton toujours appuyé AUTO_CLOSING, // idem en fermeture FULL_AUTO, // mode séquentiel entièrement automatique, les boutons sont relachés WAIT_RELEASE // mode séquentiel ou manuel stoppé en cours de route, attend le relachement des boutons } STATE;

// déclare les fonctions de chaque état void stopped(void); void manual_opening(void); void manual_closing(void); void auto_opening(void); void auto_closing(void); void full_auto(void); void wait_release(void);

// Etat courant, à l'arret par défaut au boot static volatile STATE state;

// Timeout d'appui pour passer en auto après X secondes static volatile char timeout_auto;

// Programme principal void main() { // efface les flags de reset PCON = 0; // tous les ports sont des E/S numériques ANSEL = 0b00000000; // minimise la conso des ports analogiques inutilisés CMCON = 0b00000111; // les options (presacler timer 0 au maxi 1:256) weak pullup OPTION = 0b00000111; // Règle le sens des ports d'entrée/sorties TRISIO = 0b00001011; // Weak pull up WPU = 0b00000011;

// désactive les sorties CMD_BUZZER = 0; CMD_NOT_OPENING = 1; CMD_NOT_CLOSING = 1;

// efface timeout timeout_auto = 0; // efface timer TMR0 = 0;

// Etat par défaut au reset // on vérifie que les touches ne sont pas appuyées state = WAIT_RELEASE;

// Boucle infinie while(1) { // efface chien de garde anti-plantage CLRWDT();

// Effectue les actions suivant l'état de l'automate // uniquement quand le timer 0 déclenche pour limiter // la vitesse de traitement (et les rebonds intempestifs)

// Le timer tourne à 1Mhz / 256 soit 3904Hz donc 195 = 20Hz if(TMR0 > 194) { // Reset du timer TMR0 = 0; switch(state) { case STOPPED: stopped(); break; case MANUAL_OPENING: manual_opening(); break; case MANUAL_CLOSING: manual_closing(); break; case AUTO_OPENING: auto_opening(); break; case AUTO_CLOSING: auto_closing(); break; case FULL_AUTO: full_auto(); break; case WAIT_RELEASE: wait_release(); break; } } } }

// A l'arret void stopped() { // Si on appuie sur ouverture ou fermeture (mais pas les 2 en même temps...) if((OPEN_PUSHED || CLOSE_PUSHED) && !(OPEN_PUSHED && CLOSE_PUSHED)) { char closing; // reinitialise le timeout de passage en automatique timeout_auto = 0; // active la fermeture / ouverture closing = CLOSE_PUSHED; CMD_NOT_CLOSING = ! closing; CMD_NOT_OPENING = closing; // change d'état et passe en manuel state = closing ? MANUAL_CLOSING : MANUAL_OPENING; } }

// début de l'ouverture (en manuel) void manual_opening() { // bouton d'ouverture relaché if(! OPEN_PUSHED) { CMD_NOT_OPENING = 1; // stoppe la commande d'ouverture state = STOPPED; // change d'état passe à l'arret } else { // ne passe pas en mode auto tant que la pompe n'a pas démarré // ou si elle s'arrete en cours de route en mode manuel (fin de séquence) if(PUMP_STOPPED) { if(timeout_auto > 0) { timeout_auto = 0; CMD_NOT_OPENING = 1; // stoppe la commande d'ouverture CMD_BUZZER=1; // allume le buzzer state = WAIT_RELEASE; // attend que le bouton soit relaché } } else { // incrémente le timer du mode automatique // si le timer auto est arrivé au bout, on passe en auto if(timeout_auto++ >= AUTO_TIMEOUT) { CMD_BUZZER = 1; // active le buzzer state = AUTO_OPENING; // change d'état, passe en ouverture automatique } } } }

// début de la fermeture (en manuel) void manual_closing() { // bouton de fermeture relaché if(! CLOSE_PUSHED) { CMD_NOT_CLOSING = 1; // stoppe la commande de fermeture state = STOPPED; // change d'état passe à l'arret } else { // ne passe pas en mode auto tant que la pompe n'a pas démarré // ou si elle s'arrete en cours de route en mode manuel (fin de séquence) if(PUMP_STOPPED) { if(timeout_auto > 0) { timeout_auto = 0; CMD_NOT_CLOSING = 1; // stoppe la commande de fermeture CMD_BUZZER=1; // allume le buzzer state = WAIT_RELEASE; // attend que le bouton soit relaché } } else { // incrémente le timer du mode automatique // si le timer auto est arrivé au bout, on passe en auto if(timeout_auto++ >= AUTO_TIMEOUT) { CMD_BUZZER = 1; // active le buzzer state = AUTO_CLOSING; // change d'état, passe en fermeture automatique } } } }

// début du mode automatique, le bouton ouverture est toujours appuyé void auto_opening() { // abandonne le mode auto si la pompe s'arrete en cours de route (fin de séquence) if(PUMP_STOPPED) { timeout_auto = 0; CMD_NOT_OPENING = 1; // stoppe la commande d'ouverture CMD_BUZZER = 1; // stoppe le buzzer state = WAIT_RELEASE; // attend que le bouton soit relaché } else { // le bouton d'ouverture est relaché, on passe en mode full auto if(! OPEN_PUSHED) { CMD_BUZZER = 0; // stoppe le buzzer au relachement state = FULL_AUTO; // passe en état full auto } } }

// début du mode automatique, le bouton fermeture est toujours appuyé void auto_closing() { if(PUMP_STOPPED) { timeout_auto = 0; CMD_NOT_CLOSING = 1; // stoppe la commande de fermeture CMD_BUZZER=1; // allume le buzzer state = WAIT_RELEASE; // attend que le bouton soit relaché } else { // le bouton de fermeture est relaché, on passe en mode full auto if(! CLOSE_PUSHED) { CMD_BUZZER = 0; // stoppe le buzzer au relachement state = FULL_AUTO; // passe en état full auto } } }

void full_auto() { // stoppe la commande si la pompe ne tourne plus if(PUMP_STOPPED) { // cycle terminé normalement CMD_NOT_OPENING = 1; // stoppe la commande d'ouverture CMD_NOT_CLOSING = 1; // stoppe la commande de fermeture CMD_BUZZER = 0; // stoppe le buzzer state = STOPPED; // change d'état passe à l'arret } // stoppe en cours de route si un des boutons est appuyé else if(OPEN_PUSHED || CLOSE_PUSHED) { // stoppé en cours de route, met le buzzer en route CMD_NOT_OPENING = 1; // stoppe la commande d'ouverture CMD_NOT_CLOSING = 1; // stoppe la commande de fermeture CMD_BUZZER=1; // allume le buzzer state = WAIT_RELEASE; // attend que le bouton soit relaché } }

// abandon du mode auto en cours de route // ou fin de cycle normal en manuel void wait_release() { // on attend que le bouton soit relaché pour repasser en mode stoppé if(! (OPEN_PUSHED || CLOSE_PUSHED)) { CMD_BUZZER=0; state = STOPPED; // passe en état stoppé } }

Reply to
Pinball-Man

"jj" a écrit dans le message de news:

4ab27a39$0$23486$ snipped-for-privacy@news.orange.fr...

?? dédales tortueux ?

ça c'est de la méconnaissance du C...

les plus timides peuvent meme écrire du C sans fonction et sans pointeur...

une seule fonction principale main(), que des variables globales... des goto pour les branchements...

un débutant pige le truc en une demi-heure...

Reply to
Stephane Legras-Decussy

e

bonjour =E0 tous,

qu'est ce que j'avais dit ;O] j'aurai jamais du parler de l'asm ;O]

bon dimanche =E0 tous, vede ;O]

Reply to
vede

Oui, mais relis ma phrase et essaye d'=E9crire un switch sans break... Ca en limite quelque peu l'utilisation, alors que dans les autres cas...

--

-Stan

Reply to
Stan

=A0se

in")

N'importe quoi. Il ne faut pas confondre =E9dition des liens et compilation.

--

-Stan

Reply to
Stan

N'importe quoi. Il ne faut pas confondre édition des liens et compilation. ========== C'est toi le " n'importe quoi" le nouveau programme compile forcement les fichiers include edités "en clair" et comme je l'ai dit , seulement les fonctions suceptibles d'etre utilisées

Reply to
Pierre_Edouard

c'est de la discrimination, je vais contacter la Halde bouhhhhh ;-)

Reply to
Philippe

"Pierre_Edouard" a écrit dans le message de news:4ab71c6c$0$23444$ snipped-for-privacy@news.orange.fr...

Sans rentrer dans une polémique, les includes, c'est quand même fait pour déclarer les prototypes des fonctions et les types mais pas pour y écrire du code.

Même si en effet le compilo s'en fout complètement et ça ne le gène pas du tout que le code soit dans les includes parce qu'en réalité il ne fait que "merger" les .h avec les .c, rien n'empèche de mettre tout le code dedans, et beaucoup de programmeurs, par facilité et moi le premier(j'ai pas dit fainéantise :-) ) y mettent des fonctions dans des #define (c'est pas bien non plus), dans des inline (mieux) ou carrément des fonctions complètes (crado :-)) ).

Ca se fait d'ailleurs assez souvent de façon assez natuelle en c++ on a tendance à laisser dans les .h les prototypes et aussi le code des méthodes microscopiques (quelques lignes) et les méthodes inline, et les const mais bon, si on veut faire proprement, c'est le code dans le .c et uniquement les prototypes et déclarations de types dans les .h il ne doit rien avoir à compiler qui "produise" du code autre que les glue d'appel aux fonctions/méthodes externes. le mieux c'est de faire une ou plusieurs librairie + des headers, dont les fonctiones ne sont linkées automatiquement au programme final que si elles sont utilisées, c'est propre et réutilisable, et on ne compile la lib que lorsqu'elle évolue et tous les programmes en bénéficient (tant qu'on ne fait qu'ajouter de nouvelles fonctiones sans changer les prototypes des fonctions existantes évidemment) et moins il y a de code dans les .h, moins il y a de dépendances avec les programmes qui s'en servent (dans une lib, il y a les .h "internes" juste pour compiler la lib et les .h "interfaces" qui sont des .h simplifiés à destination des clients de la librairie, sorte de contrat d'interface avec le strict minimum).

bon si c'est pour faire un petit prog en C de quelques parges sur un µc, ça change pas la face du monde si tout est dans 1 seul .c même sans include ou si on mets quelques fonction dans des .h...

Pascal

Reply to
Pinball-Man

"Pinball-Man" a écrit

============ Mon outil de travail procède de cette façon ../.. #include #include #include #include ../.. Les "fichiers include" certains compris dans la bibliothèque du fournisseur ou élaborés soi-même sont écrit en code ( C ou ASM ou les deux ) et sont compilés en même temps que le nouveau programme, par le compilateur dont on sait bien sûr que c'est le travail du "près processeur"

Reply to
Pierre_Edouard

e
s

les

e
s

les

' elles ne se compilent que si elles peuvent etre appel=E9es par le programme "main") ', si cette phrase se rapporte aux fonctions, est est fausse ou mal exprim=E9e.

L'appel et la compilation du corps de la fonction (d=E9finition / d=E9claration) sont deux choses ind=E9pendantes. L'un comme l'autre peut =EAtre effectu=E9 ind=E9pendemment lors de la compilation.

C'est =E0 l'=E9dition des liens que cela est r=E9solu.

Et comme indiqu=E9 plus loin dans le fil, mettre du code dans des includes est une mauvaise habitude.

Sur un projet tr=E8s gros, si la modularit=E9 des fichiers est mauvaise, une simple modif d'un source fera perdre un temps fou en recompilant des choses qui ne devraient pas l'=EAtre.

D'ou l'importance de dissocier la d=E9claration de la d=E9finition.

--

-Stan

Reply to
Stan

"Pierre_Edouard" a écrit dans le message de news:4ab735a8$0$12652$ snipped-for-privacy@news.orange.fr...

Normalement le lcd_elcd.c et pcf8583.c devraient être compilés à part (ajoutés dans le projet ou bien en faire une lib) et donc générer un .o (ou équivalent), il devrait y avoir un lcd_elcd.h et un pcf8583.h qui ne servent qu'à déclarer les fct/types utilisés dans les .c et rien d'autre et c'est l'édition des lien finale qui recompose le binaire définitif avec tous les fichiers compilés .o

Mais comme j'ai dit, tel que tu le montres ça marche aussi, juste que c'est pas élégant, c'est détourner la fonction de preprocesseur et c'est surtout pas efficace chaque fois que tu changes 1 ligne de codes quelque part, il faut tout recompiler, alors que si les .o sont recombinés à la fin (les .c étant corrcetement déclarés dans un makefile ou dans le projet), seul le fichier .c touché se recompile et pas les autres

Pascal

Reply to
Pinball-Man

"Stan" a écrit

.../... D'ou l'importance de dissocier la déclaration de la définition. .../... =========== Inutile de se perdre dans un bavardage inutile , je n'admet simplement pas les remarques à l'accent désobligeant comme "n'importe quoi" En sus, je n'ai pas opposé la déclaration est la définition j'ai simplement fait remarqué aux tenants du basic que les "c" permet l'élaboration de fonctions "universelles" que l'on peut regrouper dans des "fichiers include" et que l'on peut appeler et compiler lors de la création d'un programme .

Reply to
Pierre_Edouard

================ C'est la façon recommandée de procéder par le fabricant de l'outil de développement, la façon la plus simple. les "fichiers include" , ( que l'on peut aussi baptiser xxx.h que xxx.c , ) sont stockés en code source, cela permet de les modifier à loisir. Il est possible bien sûr avec cet outil de compiler les fichiers sources , header et les autres , séparément mais je ne vois pas l'inélégance de cliquer sur pour compiler ou recompiler le tout . au final, le volume est le même. Après quoi le préprosesseur, c'est son rôle, les appelle pour générer le code exécutable dans l'ordre ou " ils sont déclarés"

Rappelons que le sujet discuté concerne la mise en oeuvre et la programmation c ou basic "amateur" de µC, de peu souvent plus de 64 k, le temps d'exécution de la recompilation de l'ensemble ne prend que quelques secondes. Et qu'en outre ma réflexion de comparaison basic C sur le sujet [ n'etait que] ( le "C" bien pratique (entre autre) à cause surtout du principe des fonctions dont certaines universelles, stockées (en clair) dans un répertoire de réserve et rappelables très simplement par l'instruction "#include"). c'est tout.

Reply to
Pierre_Edouard

Après mûre réflexion, Pierre_Edouard a écrit :

C'est ce que je craignais: chacun a ses habitudes et trouve que c'est la solution 'la meilleure'. Un autre demande pourquoi et dit que non, et c'est parti dans des échanges d'experts. je ne suis pas programmeur, ne souhaite pas le devenir, je veux juste faire des bricoles sans me prendre la tête. OK pour connaître ce qu'il faut (registres etc.) mais pas OK pour mordre dans la discussion sur les 'includes': c'est du chinois.

donc je crois que je vais qd même aller vers le basic avec tous ses inconvénients, c'est le plus éloigné de l'esprit programmeur. merci de vos lumières, cela m'a bien aidé en creux.

Reply to
Guillaume

"Guillaume" a écrit dans le message de news:4ab8e3dd$0$382$ snipped-for-privacy@news.free.fr...

Mais non, c'est un détail, on peut très bien faire du C pour µC dans 1 seul fichier on peut très bien vivre sans faire de lib, de projets avec plusieurs .c séparés et includes ni même faire de fonctions, on peut tout coder dans le main ça ne marchera pas plus mal :)

Et petit à petit, tu pourras apprendre les concepts plus poussés, fonctions, include, librairies, etc... il n'y a pas besoin d'être un expert en C pour faire du bidouillage sur µC.

Oublions la discussion sur les bonnes pratiques du C:

Nul besoin d'être un expert en C pour s'y mettre, ça va te prendre le même temps que le basic à apprendre, il est très simple, if/else, for(), quelques accolades et avec ça on fait à peu près tout, (même le switch on peut aussi très bien s'en passer au début :-) ), mais au moins, tu auras appris un langage universel.

voilà un squelette minimal par exemple, tu télécharges mplab

formatting link

il est livré avec (copié betement de la doc du compilo htc) c'est un example tout bete pour faire clignoter les sorties du port B d'un pic 16f877 bien connu:

#include

__CONFIG(XT & WDTDIS & PWRTDIS & BORDIS & LVPEN & WRTEN & DEBUGEN & DUNPROT & UNPROTECT); void init(void) { // port directions: 1=input, 0=output TRISB = 0b00000000; }

char counter; void main(void) { counter = 0; init(); while (1){ PORTB = counter; _delay(10000); counter++; } }

voilà, c'est quand même simple tu trouves pas ?

tu peux partir de là pour faire quelque chose de plus complexe petit à petit, sans forcément faire de fonctions, juste en ajoutant des initialisations au besoin dans init() et en ajoutant du code intelligent dans le "while".

et quand tu auras fait un peu trop de code dans le main ou trop de copié/coller, alors tu te diras qu'il sera temps de faire des fonctions, etc et petit à petit tu feras évoluer le code en même temps que tu apprends les base du langage, qui reste, faut il le rappeler, simpliste.

tu remarqueras qu'on ne doit jamais sortir du while(), sinon on sort de main() aussi et là le cpu s'arrete ou reset tout seul mais ça n'a rien à voir avec le C c'est valable en assembleur et en basic aussi il faut toujours une boucle infinie quelque part sur les µC.

Si tu as activé le watchdog il faut régulièrement appeler CLRWDT() avant qu'il que le watchdog ne déclenche un reset automatique, note que le watchdog, c'est aussi super facultatif en "bidouillage" on peut très bien s'en passer aussi.

Pascal

Reply to
Pinball-Man

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.