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 ---
- 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 ---
Modérateur : Jérémy
Comprendre les bases de la programmation PIC
Mmmh les réponses sont compliquées je n'ai pas le niveau pour toutes les comprendre.
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".
Oui ça, ça marche.
Non, j'ai rien trouvé de tel ni dans les fichiers du compilateur ni dans mon projet MPLAB.
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"
Non il n'en veut pas non plus, il ne connait pas les ports, ils sont définis nulle part.
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 !
Ah mais oui ça c'est très clair, je n'y avais pas pensé.
Là je t'avoue que j'ai rien compris.

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
#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.
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
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.
Pas de miracle, il faut lire la doc (ccs_c_manual.pdf)
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
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
@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.
D'après mes fichiers je l'avais fait au lycée pour un 18F4520 :
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
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.
"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.
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
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
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+
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
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.
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.
Modifié en dernier par djviper16 le mar. 15 déc. 2020 23:15, modifié 1 fois.
Comprendre les bases de la programmation PIC
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"
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
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é)
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
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.
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
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.
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
Un timer c'est fait pour remplacer les delay, alors les 2 ensemble ça va pas.
Si tu veux utiliser l'interrupt timer, il faudra une routine interrupt
#int_timer0
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
Qui est en ligne
Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 14 invités


