Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Forum général sur le langage C !

Modérateur : Jérémy

Comprendre les bases de la programmation PIC
djviper16
Débutant
Débutant
Messages : 60
Enregistré en : décembre 2020

#11 Message par djviper16 » lun. 14 déc. 2020 00:39

Mmmh les réponses sont compliquées je n'ai pas le niveau pour toutes les comprendre.

#define PIN_A0 0x05.0
Tu en fais quoi de cette ligne ?

L'idée c'était que "0x05" indique l'adresse du portA et ".0" indique le bit 0 de ce registre, ce qui me paraissais plus logique que "PIN_A0 40".

#byte PORTA = 5
#bit pin_A0 = PORTA,0
pin_A0 = 1

Oui ça, ça marche.

IL doit y avoir un autre ficher include avec les registres, et donc contenant "#byte PORTA = 5"

Non, j'ai rien trouvé de tel ni dans les fichiers du compilateur ni dans mon projet MPLAB.

output(0x05.0)
essaie de compiler cela :)

Non ça passe pas, par contre j'ai la possibilité de :
- "output_a (value)" --> "Output an entire byte to a port. The direction register is changed in accordance with the last specified #USE *_IO directive."
- "output_bit (pin, value)" --> "Outputs the specified value (0 or 1) to the specified I/O pin. The method of setting the direction register is determined by the last #USE *_IO directive"

Des fonctions C de ce type éviteraient les defines.
output_low(port, pin)
output_high(port, pin)

Non il n'en veut pas non plus, il ne connait pas les ports, ils sont définis nulle part.


tres confortable pour mettre la datasheet d'un coté et MPLab de l'autre

Pour ma part j'ai un écran 49" en 32/9 avec une GTX980Ti, et je fais comme toi. D'ailleurs je ne pourrais plus revenir à un écran unique.
Si mon bureau le permettait j'en mettrais même un 3ème !

En C on peut créer une variable de taille 1 bit, elle est stockée dans un octet avec d'autres, or le processeur n'adresse que des octets, pas des bits. C'est pour cela qu'ils ont créé ces defines spécifiques permettant d'adresser un bit particulier du port, avec des fonctions elles-mêmes spécifiques.

Ah mais oui ça c'est très clair, je n'y avais pas pensé.

Pour le reste #bit permet de créer des variables bit, mais non adressables.
#bit pin PORTA,0
on peut faire :
pin = 1;
pin = 0;
pin = !pin;
v = pin; // v passe à 0 ou 1
l'adresse de pin n'est pas accessible, on ne peut pas faire :
output_low(&pin)

Là je t'avoue que j'ai rien compris. :oops: :lol:
En fait j'ai pas les bases, je ne sais pas pourquoi parfois on met les valeurs entre parenthèses, d'autres fois non, dès fois on met égale, d'autres fois juste un espace, etc

Comprendre les bases de la programmation PIC
satinas
Expert
Expert
Messages : 1497
Enregistré en : novembre 2015

#12 Message par satinas » lun. 14 déc. 2020 05:48

Bonjour
Tous ces langages avec plein de directives et fonctions sont souvent redondants, alors si tu te demandes pourquoi ils ont fait ça plutôt que ça, t'es pas arrivé.

Je vois pas de différence entre cette ligne C standard (#define a pour effet "find and replace before compil" )
#define PORTA 5
et cette seconde ligne qui est une directive propre à CCS :
#byte PORTA = 5
Il doit y en avoir car ils n'ont pas créé cette directive pour rien.
Les directives commencent par un #, elles ont leur propre syntaxe.

Une fonction output_low(port,pin) serait idéale car elle est calquée sur l'instruction assembleur du pic 16F :
bcf 0x05,0
Il semble qu'elle existe, voir doc bit_clear(var, bit)

Exemples d'utilisation :
output_low(0x05, 0)
ou
#define PORT_A 0x05
#define BIT_0 0
output_low(PORT_A, BIT_0)

A la compil cela se traduirait en une seule instruction processeur.
Pour simplifier la fonction, ils ont prévu un seul argument output_low(adr_pin) en créant des "adresses de bit" de type PIN_A0. J'ai lu la doc sur les directives "#USE *_IO", qu'est ce que c'est compliqué !

Le C pic est pas évident car on manipule souvent des bits, et c'est difficile pour les débutants, un peu comme les pointeurs.
En fait le C stocke les variables bit dans des structures, le #bit permet de masquer ou remplacer ça. Si on commence à dérouler tout cela, on a pas fini :)
C'est pourquoi je préfère un C sec comme C18 ou xc8. C'est moins confortable mais on est pas tout le temps entre de chercher une directive ou une fonction.

Pour la liste des registres et leurs bits, certains se la créent, parce que utiliser directement les registres, c'est quand même sympa. Mais on sort de la couche d' abstraction qu'offre CCS.
http://www.ccsinfo.com/forum/viewtopic.php?t=20697

Commence avec des exemples simples.
Là je t'avoue que j'ai rien compris.

Pas de miracle, il faut lire la doc (ccs_c_manual.pdf)

Code : Tout sélectionner

#byte PORTA = 0x05  // crée une variable 8 bits, c'est le registre SFR d'adresse 0x05 (PORTA)
#bit pin PORTA.0    // crée une variable 1 bit, qui prend les valeurs 0 ou 1 (pin A0)
int v = pin;        // v prend la valeur de la pin A0
pin = 1;            // pin A0 high
pin = 0;            // pin A0 low
pin = !pin;         // toggle pin A0

Entre parenthèses l'exemple de la doc pour #bit explose la fameuse abstraction.
#bit T0IF = 0xb.2
C'est pas portable, on adresse direct le registre INTCON et son bit T0IF de certains pic 16F :-)

Comprendre les bases de la programmation PIC
djviper16
Débutant
Débutant
Messages : 60
Enregistré en : décembre 2020

#13 Message par djviper16 » lun. 14 déc. 2020 22:29

@satinas

Oui je me pose beaucoup de questions, parce que mon niveau en programmation est vraiment faible. Du coup je ne sais pas ce qu'il est important de savoir et de comprendre.

A mon avis le #byte de CCS en remplacement de #define c'est juste pour savoir qu'on parle d'un octet au premier coup d'oeil. Comme #bit pour savoir qu'on parle d'un bit. Selon moi c'est par confort, pour la lisibilité, mais bon c'est peut-être autre chose. En tout cas les deux se compilent sans erreur, individuellement.
Par contre si je mets les deux dans le programme, si #byte puis #define ça compile. Si #define puis #byte il me sort 2 erreurs et refuse de compiler. Bizarre.
De toute façon c'est l'un ou l'autre il n'y a pas d'intérêt à faire ça, c'était pour l'expérience.

Les #USE *_IO je ne les utilise pas, visiblement c'est pour indiquer au compilateur comment il doit générer son code... j'imagine que c'est utile lorsqu'on est super balèze et qu'on veut optimiser la mémoire ou le nombre d'instructions pour exécuter le programme.

Pour la liste des registres et leurs bits, certains se la créent, parce que utiliser directement les registres, c'est quand même sympa. Mais on sort de la couche d' abstraction qu'offre CCS.

D'après mes fichiers je l'avais fait au lycée pour un 18F4520 :

Code : Tout sélectionner

#byte PORTA = 0xF80
#byte PORTB = 0xF81
#byte PORTC = 0xF82
#byte PORTD = 0xF83
#byte PORTE = 0xF84
#byte LATA = 0xF89
#bit    LATA6 = LATA.6
#bit    LATA7 = LATA.7
#byte LATB = 0xF8A
#byte LATC = 0xF8B
#byte LATD = 0xF8C
#byte LATE = 0xF8D
#byte TRISA = 0xF92
#byte TRISB = 0xF93
#byte TRISC = 0xF94
#byte TRISD = 0xF95
#byte TRISE = 0xF96
#bit    PSPMODE = TRISE.4
#bit    IOBV = TRISE.5
#bit    OBF = TRISE.6
#bit    IBF = TRISE.7
#byte OSCTUNE = 0xF9B
#bit    TUN0 = OSCTUNE.0
#bit    TUN1 = OSCTUNE.1
#bit    TUN2 = OSCTUNE.2
#bit    TUN3 = OSCTUNE.3
#bit    TUN4 = OSCTUNE.4
#bit    PLLEN = OSCTUNE.6
#bit    INTSRC = OSCTUNE.7
#byte PIE1 = 0xF9D
#bit    TMR1IE = PIE1.0
#bit    TMR2IE = PIE1.1
#bit    CCP1IE = PIE1.2
#bit    SSPIE = PIE1.3
#bit    TXIE = PIE1.4
#bit    RCIE = PIE1.5
#bit    ADIE = PIE1.6
#bit    PSPIE = PIE1.7
#byte PIR1 = 0xF9E
#bit    TMR1IF = PIR1.0
#bit    TMR2IF = PIR1.1
#bit    CCP1IF = PIR1.2
#bit    SSPIF = PIR1.3
#bit    TXIF = PIR1.4
#bit    RCIF = PIR1.5
#bit    ADIF = PIR1.6
#bit    PSPIF = PIR1.7
#byte IPR1 = 0xF9F
#bit    TMR1IP = IPR1.0
#bit    TMR2IP = IPR1.1
#bit    CCP1IP = IPR1.2
#bit    SSPIP = IPR1.3
#bit    TXIP = IPR1.4
#bit    RCIP = IPR1.5
#bit    ADIP = IPR1.6
#bit    PSPIP = IPR1.7
#byte PIE2 = 0xFA0
#bit    TMR1IE = PIE2.0
#bit    TMR3IE = PIE2.1
#bit    LVDIE = PIE2.2
#bit    BCLIE = PIE2.3
#bit    EEIE = PIE2.4
#bit    CMIE = PIE2.6
#bit    OSCFIE = PIE2.7
#byte PIR2 = 0xFA1
#bit    CCP2IF = PIR2.0
#bit    TMR3IF = PIR2.1
#bit    LVDIF = PIR2.2
#bit    BLICF = PIR2.3
#bit    EEIF = PIR2.4
#bit    CMIF = PIR2.6
#bit    OSCFIF = PIR2.7
#byte IPR2 = 0xFA2
#bit    CCP2IP = IPR2.0
#bit    TMR3IP = IPR2.1
#bit    LVDIP = IPR2.2
#bit    CLIP = IPR2.3
#bit    EEIP = IPR2.4
#bit    CMIP = IPR2.6
#bit    OSCFIP = IPR2.7
#byte EECON1 = 0xFA6
#bit    RD = EECON1.0
#bit    WR = EECON1.1
#bit    WREN = EECON1.2
#bit    WRERR = EECON1.3
#bit    FREE = EECON1.4
#bit    CFGS = EECON1.6
#bit    EEPGD = EECON1.7
#byte EECON2 = 0xFA7
#byte EEDATA = 0xFA8
#byte EEADR = 0xFA9
#bit    EEADR0 = EEADR.0
#bit    EEADR1 = EEADR.1
#bit    EEADR2 = EEADR.2
#bit    EEADR3 = EEADR.3
#bit    EEADR4 = EEADR.4
#bit    EEADR5 = EEADR.5
#bit    EEADR6 = EEADR.6
#bit    EEADR7 = EEADR.7
#byte RCSTA = 0xFAB
#bit    RX9D = RCSTA.0
#bit    OERR = RCSTA.1
#bit    FERR = RCSTA.2
#bit    ADDEN = RCSTA.3
#bit    CREN = RCSTA.4
#bit    SREN = RCSTA.5
#bit    RX9 = RCSTA.6
#bit    SPEN = RCSTA.7
#byte TXSTA = 0xFAC
#bit    TX9D = TXSTA.0
#bit    TRMT = TXSTA.1
#bit    BRGH = TXSTA.2
#bit    SENDB = TXSTA.3
#bit    SYNC = TXSTA.4
#bit    TXEN = TXSTA.5
#bit    TX9 = TXSTA.6
#bit    CSRC = TXSTA.7
#byte TXREG = 0xFAD
#byte RCREG = 0xFAE
#byte SPBRG = 0xFAF
#byte SPBRGH = 0xFB0
#byte T3CON = 0xFB1
#bit    TMR3ON = T3CON.0
#bit    TMR3CS = T3CON.1
#bit    T3SYNC = T3CON.2
#bit    T3CCP1 = T3CON.3
#bit    T3CKPS0 = T3CON.4
#bit    T3CKPS1 = T3CON.5
#bit    T3CCP2 = T3CON.6
#bit    RD16 = T3CON.7
int16 TMR3;
#locate TMR3 = 0xFB2
#byte TMR3H = 0xFB3
#byte CMCON = 0xFB4
#bit    CM0 = CMCON.0
#bit    CM1 = CMCON.1
#bit    CM2 = CMCON.2
#bit    CIS = CMCON.3
#bit    C1INV = CMCON.4
#bit    C2INV = CMCON.5
#bit    C1OUT = CMCON.6
#bit    C2OUT = CMCON.7
#byte CVRCON = 0xFB5
#bit    CVR0 = CVRCON.0
#bit    CVR1 = CVRCON.1
#bit    CVR2 = CVRCON.2
#bit    CVR3 = CVRCON.3
#bit    CVRSS = CVRCON.4
#bit    CVRR = CVRCON.5
#bit    CVROE = CVRCON.6
#bit    CVREN = CVRCON.7
#byte ECCP1AS = 0xFB6
#bit    PSSBD0 = ECCP1AS.0
#bit    PSSBD1 = ECCP1AS.1
#bit    PSSAC0 = ECCP1AS.2
#bit    PSSAC1 = ECCP1AS.3
#bit    ECCPAS0 = ECCP1AS.4
#bit    ECCPAS1 = ECCP1AS.5
#bit    ECCPAS2 = ECCP1AS.6
#bit    ECCPASE = ECCP1AS.7
#byte PWM1CON = 0xFB7
#bit    PDC0 = PWM1CON.0
#bit    PDC1 = PWM1CON.1
#bit    PDC2 = PWM1CON.2
#bit    PDC3 = PWM1CON.3
#bit    PDC4 = PWM1CON.4
#bit    PDC5 = PWM1CON.5
#bit    PDC6 = PWM1CON.6
#bit    PRSEN = PWM1CON.7
#byte BAUDCON = 0xFB8
#bit    ABDEN = BAUDCON.0
#bit    WUE = BAUDCON.1
#bit    BRG16 = BAUDCON.3
#bit    SCKP = BAUDCON.4
#bit    RCIDL = BAUDCON.6
#bit    ABDOVF = BAUDCON.7
#byte CCP2CON = 0xFBA
#bit    CCP2M0 = CCP2CON.0
#bit    CCP2M1 = CCP2CON.1
#bit    CCP2M2 = CCP2CON.2
#bit    CCP2M3 = CCP2CON.3
#bit    DC2B0 = CCP2CON.4
#bit    DC2B1 = CCP2CON.5
int16 CCPR2;
#locate CCPR2 = 0xFBB
#byte CCPR2H = 0xFBC
#byte CCP1CON = 0xFBD
#bit    CCP1M0 = CCP1CON.0
#bit    CCP1M1 = CCP1CON.1
#bit    CCP1M2 = CCP1CON.2
#bit    CCP1M3 = CCP1CON.3
#bit    DC1B0 = CCP1CON.4
#bit    DC1B1 = CCP1CON.5
#bit    P1M0 = CCP1CON.6
#bit    P1M1 = CCP1CON.7
int16 CCPR1;
#locate CCPR1 = 0xFBE
#byte CCPR1H = 0xFBF
#byte ADCON2 = 0xFC0
#bit    ADCS0 = ADCON2.0
#bit    ADCS1 = ADCON2.1
#bit    ADCS2 = ADCON2.2
#bit    ACQT0 = ADCON2.3
#bit    ACQT1 = ADCON2.4
#bit    ACQT2 = ADCON2.5
#bit    ADFM = ADCON2.7
#byte ADCON1 = 0xFC1
#bit    PCFG0 = ADCON1.0
#bit    PCFG1 = ADCON1.1
#bit    PCFG2 = ADCON1.2
#bit    PCFG3 = ADCON1.3
#bit    VCFG0 = ADCON1.4
#bit    VCFG1 = ADCON1.5
#byte ADCON0 = 0xFC2
#bit    ADON = ADCON0.0
#bit    GO/DONE = ADCON0.1
#bit    CHS0 = ADCON0.2
#bit    CHS1 = ADCON0.3
#bit    CHS2 = ADCON0.4
#bit    CHS3 = ADCON0.5
int16 ADRES;
#locate ADRES = 0xFC3
#byte ADRESH = 0xFC4
#byte SSPCON2 = 0xFC5
#bit    SEN = SSPCON2.0
#bit    RSEN = SSPCON2.1
#bit    PEN = SSPCON2.2
#bit    RCEN = SSPCON2.3
#bit    ACKEN = SSPCON2.4
#bit    ACKDT = SSPCON2.5
#bit    ACKSTAT = SSPCON2.6
#bit    GCEN = SSPCON2.7
#byte SSPCON1 = 0xFC6
#bit    SSMP0 = SSPCON1.0
#bit    SSMP1 = SSPCON1.1
#bit    SSPM2 = SSPCON1.2
#bit    SSPM3 = SSPCON1.3
#bit    CKP = SSPCON1.4
#bit    SSPEN = SSPCON1.5
#bit    SSPOV = SSPCON1.6
#bit    WCOL = SSPCON1.7
#byte SSPSTAT = 0xFC7
#bit    BF = SSPSTAT.0
#bit    UA = SSPSTAT.1
#bit    R/W = SSPSTAT.2
#bit    S = SSPSTAT.3
#bit    P = SSPSTAT.4
#bit    D/A = SSPSTAT.5
#bit    CKE = SSPSTAT.6
#bit    SMP = SSPSTAT.7
#byte SSPADD = 0xFC8
#byte SSPBUF = 0xFC9
#byte T2CON = 0xFCA
#bit    T2CKPS0 = T2CON.0
#bit    T2CKPS1 = T2CON.1
#bit    TMR2ON = T2CON.2
#bit    T2OUTPS0 = T2CON.3
#bit    T2OUTPS1 = T2CON.4
#bit    T2OUTPS2 = T2CON.5
#bit    T2OUTPS3 = T2CON.6
#byte PR2 = 0xFCB
#byte TMR2 = 0xFCC
#byte T1CON = 0xFCD
#bit    TMR1ON = T1CON.0
#bit    TMR1CS = T1CON.1
#bit    T1SYNC = T1CON.2
#bit    T1OSCEN = T1CON.3
#bit    T1CKPS0 = T1CON.4
#bit    T1CKPS1 = T1CON.5
#bit    T1RUN = T1CON.6
#bit    RD16 = T1CON.7
int16 TMR1;
#locate TMR1 = 0xFCE
#byte TMR1H = 0xFCF
#byte RCON = 0xFD0
#bit    BOR = RCON.0
#bit    POR = RCON.1
#bit    PD = RCON.2
#bit    TO = RCON.3
#bit    TI = RCON.4
#bit    LWRT = RCON.6
#bit    IPEN = RCON.7
#byte WDTCON = 0xFD1
#bit    SWDTEN = WDTCON.0
#byte HLVDCON = 0xFD2
#bit    HLVDL0 = HLVDCON.0
#bit    HLVDL1 = HLVDCON.1
#bit    HLVDL2 = HLVDCON.2
#bit    HLVDL3 = HLVDCON.3
#bit    HLVDEN = HLVDCON.4
#bit    IRVST = HLVDCON.5
#bit    VDIRMAG = HLVDCON.7
#byte OSCCON = 0xFD3
#bit    SCS0 = OSCCON.0
#bit    SCS1 = OSCCON.1
#bit    IOFS = OSCCON.2
#bit    OSTS = OSCCON.3
#bit    IFCF0 = OSCCON.4
#bit    IRCF1 = OSCCON.5
#bit    IRCF2 = OSCCON.6
#bit    IDLEN = OSCCON.7
#byte T0CON = 0xFD5
#bit    T0PS0 = T0CON.0
#bit    T0PS1 = T0CON.1
#bit    T0PS2 = T0CON.2
#bit    PSA = T0CON.3
#bit    T0SE = T0CON.4
#bit    T0CS = T0CON.5
#bit    T08BIT = T0CON.6
#bit    TMR0ON = T0CON.7
int16 TMR0;
#locate TMR0 = 0xFD6
#byte TMR0H = 0xFD7
#byte STATUS = 0xFD8
#bit    C = STATUS.0
#bit    DC = STATUS.1
#bit    Z = STATUS.2
#bit    OV = STATUS.3
#bit    N = STATUS.4
int16 FSR2;
#locate FSR2 = 0xFD9
#byte FSR2H = 0xFDA
#byte PLUSW2 = 0xFDB
#byte PREINC2 = 0xFDC
#byte POSTDEC2 = 0xFDD
#byte POSTINC2 = 0xFDE
#byte INDF2 = 0xFDF
#byte BSR = 0xFE0
int16 FSR1;
#locate FSR1 = 0xFE1
#byte FSR1H = 0xFE2
#byte PLUSW1 = 0xFE3
#byte PREINC1 = 0xFE4
#byte POSTDEC1 = 0xFE5
#byte POSTINC1 = 0xFE6
#byte INDF1 = 0xFE7
#byte WREG = 0xFE8
int16 FSR0;
#locate FSR0 = 0xFE9
#byte FSR0H = 0xFEA
#byte PLUSW0 = 0xFEB
#byte PREINC0 = 0xFEC
#byte POSTDEC0 = 0xFED
#byte POSTINC0 = 0xFEE
#byte INDF0 = 0xFEF
#byte INTCON3 = 0xFF0
#bit    INT1IF = INTCON3.0
#bit    INT2IF = INTCON3.1
#bit    INT1IE = INTCON3.3
#bit    INT2IE = INTCON3.4
#bit    INT1IP = INTCON3.6
#bit    INT2IP = INTCON3.7
#byte INTCON2 = 0xFF1
#bit    RBIP = INTCON2.0
#bit    TMR0IP = INTCON2.2
#bit    INTEDG2 = INTCON2.4
#bit    INTEDG1 = INTCON2.5
#bit    INTEDG0 = INTCON2.6
#bit    RBPU = INTCON2.7
#byte INTCON = 0xFF2
#bit    RBIF = INTCON.0
#bit    INT0IF = INTCON.1
#bit    TMR0IF = INTCON.2
#bit    RBIE = INTCON.3
#bit    INT0IE = INTCON.4
#bit    TMR0IE = INTCON.5
#bit    PEIE/GIEL = INTCON.6
#bit    GIE/GIEH = INTCON.7
int16 PROD;
#locate PROD = 0xFF3
#byte PRODH = 0xFF4
#byte TABLAT = 0xFF5
int16 TBLPTR;
#locate TBLPTR = 0xFF6
#byte TBLPTRH = 0xFF7
#byte TBLPTRU = 0xFF8
#bit    BIT 21 = TBLPTRU.5
#byte PCL = 0xFF9
#byte PCLATH = 0xFFA
#byte PCLATU = 0xFFB
#byte STKPTR = 0xFFC
#bit    SP0 = STKPTR.0
#bit    SP1 = STKPTR.1
#bit    SP2 = STKPTR.2
#bit    SP3 = STKPTR.3
#bit    SP4 = STKPTR.4
#bit    STKUNF = STKPTR.6
#bit    SKTFUL = STKPTR.7
int16 TOS;
#locate TOS = 0xFFD
#byte TOSH = 0xFFE
#byte TOSU = 0xFFF


Je ne vais pas décortiquer tout ton message mais sache que toutes les infos que tu me donnes me sont très utiles et m'aident à comprendre.

"C'est pas portable" ça veut dire qu'on ne peut pas prendre ce programme tel qu'il est pour mettre dans un autre PIC ?
J'ai la doc ouverte en permanence telle une bible :lol:

Je suis content de moi, j'ai réussi à créer un programme de A-à-Z utilisant le timer0, uniquement à partir de la doc CCS et du PIC16F628. Donc sans copier sur un modèle fait par quelqu'un d'autre. Par contre ce qui m'aurait pris 10 minutes m'a pris 3h, mais j'ai compris des choses.

Code : Tout sélectionner

#include <16F628.h> 

#use delay(clock=4000000)                    //fréquence de l'oscillateur interne : 4MHz
#fuses INTRC_IO,NOWDT,NOPUT,NOBROWNOUT,NOMCLR,NOPROTECT,NOLVP,NOCPD    //il faut tous les mettre sinon ça marche pas
//#INT_RTCC noclear                            //inutile pour que ça fonctionne
//#INT_TIMER0                                //inutile pour que ça fonctionne





void main()

{
SETUP_TIMER_0(RTCC_INTERNAL|RTCC_DIV_256);    //adresse 101h (bank2)->bits de configutration les mêmes que le registre OPTION ??!!
set_TRIS_B(0xff);                            //on définit le portB en sortie


    while(1)
    {
    
        if 
(get_timer0()>250)                //si le timer a débordé (flag levé) au dessus de 250 
                                            //(pour un total de 255 vu que c'est un timer 8 bits)
        {
            set_timer0(0);                    //on remet le timer à 0
            output_low(pin_b5);                //on éteint la led
            delay_ms(200);                    //on attend 200ms
            
        
}
        else                                 //sinon
            output_high(pin_b5);            //on allume la led
        
    
}
}


"if (get_timer0()>250)" je ne suis pas sûr que ce soit correct de faire comme ça car d'après la doc CCS quand le timer arrive à 255 il ne se bloque pas, il reprend à 0. Du coup il serait peut-être plus judicieux d'aller lire l'état du flag (le bit T0IF si j'ai bien compris).

Je vais me pencher sur les interruptions maintenant que j'ai dégrossi le timer0 (ou RTCC). Le but étant de libérer ma boucle "main".

Merci encore.

Comprendre les bases de la programmation PIC
satinas
Expert
Expert
Messages : 1497
Enregistré en : novembre 2015

#14 Message par satinas » mar. 15 déc. 2020 08:53

Bonjour, cela avance bien :)

Ca ira de plus en vite une fois les habitudes prises avec l'environnement. En fait, tout ce qui touche aux registres a été décomposé en fonctions, et il y en a beaucoup.

Pour scruter ou mettre à zéro un flag d'interruption il y a interrupt_active() et clear_interrupt()
On peut travailler en mode polling, on boucle en utilisant ces 2 fonctions, ou en mode interruption en utilisant que la seconde.

On parle de flag d'interruption, mais on les utilise aussi hors interruption, on devrait parler de flag évènement. Ces flags sont levés par le processeur sur évènement, et doivent être remis à zéro par le programme après traitement, s'il y a traitement et si le flag a servi. Dans ton programme, le flag timer n'a pas servi, il passe à 1, ne change plus, et cela ne pose pas de problème, c'est juste un indicateur.
Quelques exceptions, pour la réception uart par exemple, c'est lorsque le programme lit le registre "octet reçu" que le flag est remis à zéro par le pic. Là c'est différent, il faut gérer l'overflow et donc traiter obligatoirement et dans les temps la réception.

Revois ta commande set_TRIS, pas la peine de déclarer tout le port en sortie, et si possible dans le bon sens :)
J'aurais plutôt mis le set_timer0(0) derrière le delay_ms(200).
A+

Comprendre les bases de la programmation PIC
djviper16
Débutant
Débutant
Messages : 60
Enregistré en : décembre 2020

#15 Message par djviper16 » mar. 15 déc. 2020 14:26

Salut,

Ah oui quel idiot, j'ai définit mon port B en entrée avec 0xFF. J'aurais dû mettre set_TRIS_B(0x00), ou set_TRIS_B(0b11111010)(0b11011111) pour n'affecter que la broche RB5 en sortie.

J'ai essayé de faire le même programme en utilisant le flag (T0IF) au lieu du compteur mais je n'ai pas obtenu ce que je veux pour le moment. A creuser d'avantage.

C'est bizarre je n'ai pas les commandes que tu nommes dans ma doc CCS. J'ai une commande enable_interrupts(global) qui passe les bits GIE et PEIE à 1, et enable_interrupts(int_rtcc) qui passe le bit T0IE à 1, mais pas de commande "clear". D'ailleurs le bit T0IF ne semble même pas défini dans mon fichier header. Je crois qu'il faut que je fasse un #bit T0IF = 0x0B.2 puis T0IF=0 pour redescendre le flag.

Jamais entendu parlé du mode polling, je vais me renseigner là dessus ce soir. :wink:
Modifié en dernier par djviper16 le mar. 15 déc. 2020 23:15, modifié 1 fois.

Comprendre les bases de la programmation PIC
satinas
Expert
Expert
Messages : 1497
Enregistré en : novembre 2015

#16 Message par satinas » mar. 15 déc. 2020 14:40

Bonjour,
J'ai celle de la page CCS http://www.ccsinfo.com/downloads/ccs_c_manual.pdf
Pour RB5 c'est set_TRIS_B(0b11011111)
Le mode polling, c'est ce que tu as fait avec un if continuel, c'est mieux de tester le flag timer que le registre TMR0.
IL faut commencer par le mode polling, et quand on a compris, on peut passer aux interruptions.
"Poll to debug, interrupt to run"

Comprendre les bases de la programmation PIC
djviper16
Débutant
Débutant
Messages : 60
Enregistré en : décembre 2020

#17 Message par djviper16 » mar. 15 déc. 2020 19:13

Ah d'accord, en fait j'utilise une vieille version de CCS (elle a 12 ans environ) c'est pour ça qu'on a pas la même doc.

Je me suis fait avoir pour le sens des bits. C'est contre intuitif je trouve, c'est le contraire des docs des composants.
Curieusement que je mette set_trisB(0x00) ou (0xFF) c'est pareil. Après consultation de la doc, c'est parce que par défaut le compilateur CCS affecte automatiquement les ports en utilisant la directive #use_standard_io, même si l'on a rien défini.
Pour définir un port en entrée ou sortie manuellement, il faut que j'utilise #use fast_io(B) avant d'utiliser set_trisB(0x00). J'ai vérifié, ça fonctionne maintenant.

#use fixed_io(B_outputs=PIN_B5) permet quant à lui de se passer de set_triX(). (pas encore testé)

Comprendre les bases de la programmation PIC
satinas
Expert
Expert
Messages : 1497
Enregistré en : novembre 2015

#18 Message par satinas » mar. 15 déc. 2020 20:50

setup timer
set_timer0(start) (start = valeur calculée fonction de la durée voulue)
on met à 0 le flag timer (T0IF) par la fonction clear_interrupt(INT_TIMER0)
timer ON
boucle
.polling sur la fonction interrupt_active(INT_TIMER0) qui donne l'état du flag timer (T0IF)
.lorsque le timer passe de 0xff à 0x00, elle retourne 1 (T0IF est passé à 1)
..on remet à 0 le flag timer (T0IF) par la fonction clear_interrupt(INT_TIMER0)
..set_timer0(start)
.goto boucle

J'ai pas vu comment on fait timer OFF ou ON, pourtant c'est utile.
Si tu passes trop vite au mode interrupt, CCS va tout faire y compris reset du flag, et tu ne comprendras pas le mécanisme.

Comprendre les bases de la programmation PIC
djviper16
Débutant
Débutant
Messages : 60
Enregistré en : décembre 2020

#19 Message par djviper16 » mar. 15 déc. 2020 21:45

Je pensais avoir bien pigé le principe de fonctionnement, mais je n'arrive pas à faire clignoter ma led donc quelque chose m'échappe.
Elle s'allume 200ms environ puis s'éteint à tout jamais.
Ce qui veut dire soit que mon flag ne repasse pas à 0, soit mon compteur ne tourne plus.
J'ai essayé plein de choses mais sans succès.

Code : Tout sélectionner

#include <16F628.h> 

#use delay(clock=4000000)                    //fréquence de l'oscillateur interne : 4MHz
#fuses INTRC_IO,NOWDT,NOPUT,NOBROWNOUT,NOMCLR,NOPROTECT,NOLVP,NOCPD    //il faut tous les mettre sinon ça marche pas
//#INT_RTCC                                    //inutile pour que ça fonctionne
//#INT_TIMER0                                //inutile pour que ça fonctionne
#use fast_io(B)                                // permet d'utiliser set_tris_X(), sinon CCS affecte automatiquement les ports.

#bit T0IE = 0x0B.5                            //adresse du bit pour activer le flag du Timer0
#bit T0IF = 0x0B.2                            //adresse du bit flag du Timer0
#bit INTE = 0x0B.5                            //pour essai

void main()

{

set_TRIS_B(0xDF);                            //définit RB5 en sortie
SETUP_TIMER_0(RTCC_INTERNAL|RTCC_DIV_256);    //active le Timer0 + paramètrage sur horloge interne et prédiviseur réglé à 256
enable_interrupts(GLOBAL);                    //active les interruptions
enable_interrupts(INT_TIMER0);                //active le bit T0IE
T0IE=1;
T0IF=0;
INTE=0;
set_timer0(0);                                //on remet le timer à 0

    while(1)
    {
        if (T0IF==1)                        //si flag du timer0 levé
                                            
        
{
            output_low(pin_b5);                //on éteint la led
            delay_ms(200);                    //on attend 200ms
            set_timer0(0);                  //on remet le timer à 0
            T0IF=0;                            //on remet le flag à 0
        }
        else                                 //sinon
            output_high(pin_b5);            //on allume la led
            delay_ms(200);                    //on attend 200ms
    }
}
Modifié en dernier par djviper16 le mar. 15 déc. 2020 22:39, modifié 2 fois.

Comprendre les bases de la programmation PIC
satinas
Expert
Expert
Messages : 1497
Enregistré en : novembre 2015

#20 Message par satinas » mar. 15 déc. 2020 22:06

Un timer c'est fait pour remplacer les delay, alors les 2 ensemble ça va pas.

Code : Tout sélectionner

main
{
  set_TRIS_B(0x50);                            //définit RB5 en sortie
  SETUP_TIMER_0(RTCC_INTERNAL|RTCC_DIV_256);   //active le Timer0 + paramètrage sur horloge interne et prédiviseur réglé à 256
  T0IF=0;
  set_timer0(0);                              //on remet le timer à 0
  while(1)
  {
    if (T0IF==1)                              //si flag du timer0 levé
      {
        output_toggle(pin_b5);
        T0IF=0;                               //on remet le flag à 0
        set_timer0(0);                        //on remet le timer à 0
     }
  }
}


Si tu veux utiliser l'interrupt timer, il faudra une routine interrupt
#int_timer0


Retourner vers « Langage C »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 14 invités