Timer,Interruption ou Boucle? Pic18f4550
Fermé
mik3five
-
23 juin 2010 à 14:47
mik3fly Messages postés 6 Date d'inscription mercredi 23 juin 2010 Statut Membre Dernière intervention 9 septembre 2011 - 23 juin 2010 à 17:49
mik3fly Messages postés 6 Date d'inscription mercredi 23 juin 2010 Statut Membre Dernière intervention 9 septembre 2011 - 23 juin 2010 à 17:49
A voir également:
- Timer,Interruption ou Boucle? Pic18f4550
- Shutdown timer - Télécharger - Personnalisation
- Le fichier contient un programme écrit en python. le programme construit un mot secret mais il ne l'affiche pas. modifiez ce programme afin que à chaque itération de la boucle : la variable a augmente de 2 la variable b diminue de 1 ajoutez une instruction pour faire afficher le mot secret construit. quel est ce mot secret ? ✓ - Forum Python
- Sleep timer tv tcl ✓ - Forum Téléviseurs
- Mon pc s'allume et s'éteint en boucle ✓ - Forum Matériel & Système
- Samsung a51 redémarre en boucle - Forum Mobile
4 réponses
chuka
Messages postés
965
Date d'inscription
samedi 11 octobre 2008
Statut
Membre
Dernière intervention
29 juillet 2010
378
Modifié par chuka le 23/06/2010 à 14:58
Modifié par chuka le 23/06/2010 à 14:58
Salut,
l'utilisation d'un timer est pas mal pour cela:
tu fais l'init de ton timer (se referrer à la datasheet pour calibrer l'IT timer à 50ms) et dans l'IT timer tu incrémentes une variable (dans l'exemple TopTension) et dans le main:
Ce n'est pas parce que certaines choses semblent inexplicables, qu'il faut faire semblant de les expliquer!
l'utilisation d'un timer est pas mal pour cela:
tu fais l'init de ton timer (se referrer à la datasheet pour calibrer l'IT timer à 50ms) et dans l'IT timer tu incrémentes une variable (dans l'exemple TopTension) et dans le main:
void main(void) { timer_init(); adc_init(); while(1){ if (TopTension){ adc_conv(); calc_tens(); _DINT(); TopTension--; _EINT(); } } }
Ce n'est pas parce que certaines choses semblent inexplicables, qu'il faut faire semblant de les expliquer!
mik3fly
Messages postés
6
Date d'inscription
mercredi 23 juin 2010
Statut
Membre
Dernière intervention
9 septembre 2011
1
23 juin 2010 à 17:49
23 juin 2010 à 17:49
Voici mon code au complet, pour mémoire
Il y'a 4 Transducteurs a ultrasons, qui permettent de connaitre une distance, entre un objet et le transducteur
La valeur analogique des capteurs est sauvegardé dans Vnum et sur le PORTB et le PORTC, toute les 50ms, le capteur suivant est analysé!
Il y'a 4 Transducteurs a ultrasons, qui permettent de connaitre une distance, entre un objet et le transducteur
La valeur analogique des capteurs est sauvegardé dans Vnum et sur le PORTB et le PORTC, toute les 50ms, le capteur suivant est analysé!
#include <p18f4550.h> #pragma config FOSC = HS #pragma const config FCMENB = OFF #pragma const config IESOB = OFF #pragma config PWRT = OFF #pragma const config BOR = BOHW #pragma const config BORV = 20 #pragma config WDT = OFF #pragma config DEBUG = OFF #pragma config LVP = OFF #pragma config PBADEN = OFF /////////////////////////////////////////////////////////////////////////////////////// ///////////////////////// Définitions des PORTS CAP et DEL //////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// #define CAP1 PORTDbits.RD0 #define CAP2 PORTDbits.RD1 #define CAP3 PORTDbits.RD5 #define CAP4 PORTDbits.RD7 #define LED1 PORTDbits.RD2 #define LED2 PORTDbits.RD3 #define LED3 PORTDbits.RD4 #define LED4 PORTDbits.RD6 #define quantum 4.8828e-3 //5/1024 -> 0,0048828 mv #define uchar unsigned char /////////////////////////////////////////////////////////////////////////////////////// ////////////////////// Variables et Prototypes des fonctions ////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// int choix; int result; int Vcap; int TopTension; float Vnum; void timer_init(void); void adc_conv(uchar choix,uchar index); void adc_init(void); void calc_tens(void); void choix_cap(void); void _DINT(void); void _EINT(void); #pragma code highVector=0x008 void atInterrupthigh(void) { _asm GOTO choix_cap _endasm } #pragma code void main(void) { uchar choix[]={0x01,0x05,0x09,0x0D}; uchar index=0; timer_init(); adc_init(); while(1){ if (TopTension){ adc_conv(choix[index],index); calc_tens(); if ((++index)>sizeof(choix)) //evite les debordements index=0; _DINT(); TopTension--; _EINT(); } } } /////////////////////////////////////////////////////////////////////////////////////// //////////////////// Convertion AD pour 4 Transducteur a Ultrasons //////////////////// ////////////////////////// LV-MaxSonar®-EZ0 : 0.50cm a 700cm ////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// void adc_conv(uchar choix,uchar index) { LATD&=0xC3; //mise à zero des led LATD|=0x04<<index; //mise à 1 de la led ADCON0=choix; // Sélection du can; ADCON1=0b00001110; // ADCON2=0b10101100; ADCON0bits.ADON=1; ADCON0bits.GO_DONE=1; // début convertion while(ADCON0bits.GO_DONE); // attente convertion ADCON0bits.GO_DONE=0; // fin convertion LATB=ADRESL; LATC=ADRESH; ADCON0=0x00; // can éteint } /////////////////////////////////////////////////////////////////////////////////////// //////////////////// Calcul AD; 9,8mv/2.54cm soit 3.86mv/1cm ///////////////////////// ///////////////////// Vcap = Vcc/512; Résolution sur 9 Bits /////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// void calc_tens(void) { Vcap=((ADRESH*256)+ADRESL); Vnum = ((float)Vcap) * quantum; } /////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// INITIALISATION µC ////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// void adc_init(void) { LATB=0x00; //PORTB : 0 LATC=0x00; //PORTC : 0 TRISD=0b10000011; //RD0,RD1,RD5,RD7 en entrée TRISB=0b00000000; //RB en sortie TRISC=0b00000000; //RC en sortie } void timer_init(void) { T0CON=0b10000001; //Timer en fonctionnement. Prescaler 1:4 INTCONbits.GIE=1; //Autorisations des interruptions INTCONbits.PEIE=1; //Autorisations des interruptions périphérique INTCONbits.TMR0IE=1; // Autorisations d'interruption pour le débordement du TIMER0 INTCON2bits.TMR0IP=1; //Interruption du TIMER haute priorité. } /////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////// INTERRUPTION 50MS CAPx+1 /////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// #pragma interrupt choix_cap void choix_cap (void) { TopTension++; INTCONbits.TMR0IF=0;//mise à zero du flag d'IT } void _DINT() { INTCONbits.GIE=0; // Desactivations des interruptions } void _EINT() { INTCONbits.GIE=1; // Autorisations des interruptions }
mmh.. à quoi servent les instruction _DINT(); et _EINT();?
Pour les 50 ms je pense avoir trouvé, je possède un quartz 20mhz, donc 1/20mhz=50ns
Si j'utilise un prescaler de 1:16 ainsi qu'un timer de 16bit, ça nous donne , 50ns*16*65536= 0,0524288 Seconde.. Soit 52ms!! ce qui est parfait.
Cependant, sur les schéma de la datasheet, j'aperçois, Fosc/4.. suis-je sur la bonne piste??
(sinon cela me ferai 1/5mhz =200ns, 200ns*4*65536 = 0.052...s soit 52ms)
Donc T0CON=0b10000011 (ou T0CON=0b10000001)
Si j'ai bien compris, le timer va s'incrémenter tout seule, jusqu'au débordement du registre TRM0, TMR0IF passe a 1; et ensuite on passe dans l'IT ??
La variable TopTension dans ton exemple, elle correspond a ma variable choix?? Je comprend pas, comment l'utilisé enfaite.
edit
voici mon timer_init
Pour les 50 ms je pense avoir trouvé, je possède un quartz 20mhz, donc 1/20mhz=50ns
Si j'utilise un prescaler de 1:16 ainsi qu'un timer de 16bit, ça nous donne , 50ns*16*65536= 0,0524288 Seconde.. Soit 52ms!! ce qui est parfait.
Cependant, sur les schéma de la datasheet, j'aperçois, Fosc/4.. suis-je sur la bonne piste??
(sinon cela me ferai 1/5mhz =200ns, 200ns*4*65536 = 0.052...s soit 52ms)
Donc T0CON=0b10000011 (ou T0CON=0b10000001)
Si j'ai bien compris, le timer va s'incrémenter tout seule, jusqu'au débordement du registre TRM0, TMR0IF passe a 1; et ensuite on passe dans l'IT ??
La variable TopTension dans ton exemple, elle correspond a ma variable choix?? Je comprend pas, comment l'utilisé enfaite.
edit
voici mon timer_init
void timer_init(void) { T0CON=0b10000001; //Timer en fonctionnement. Prescaler 1:4 INTCONbits.GIE=1; //Autorisations des interruptions INTCONbits.PEIE=1; //Autorisations des interruptions périphérique INTCONbits.TMR0IE=1; // Autorisations d'interruption pour le débordement du TIMER0 INTCON2bits.TMR0IP=1; //Interruption du TIMER haute priorité. }
chuka
Messages postés
965
Date d'inscription
samedi 11 octobre 2008
Statut
Membre
Dernière intervention
29 juillet 2010
378
Modifié par chuka le 23/06/2010 à 16:27
Modifié par chuka le 23/06/2010 à 16:27
Salut,
Je pense qu'en effet, si ton horloge est à 20mHz, alors tu dois avoir un prescaler de base sur Fosc... donc sinon cela me ferai 1/5mhz =200ns, 200ns*4*65536 = 0.052...s soit 52ms doit etre la soluce...
Tu dois pouvoir choisir le mode de comptage (Up,Down,Up-Down...) regarde dans le registre si cela est le cas...sinon je pense que par defaut, cela doit etre en mode up.
Si j'ai bien compris, le timer va s'incrémenter tout seule, jusqu'au débordement du registre TRM0, TMR0IF passe a 1; et ensuite on passe dans l'IT ??
Tu as parfaitement compris!!
Tu dois juste définir le vecteur d'IT (c'est en fait la fonction qui va être appelé quand tu as ton débordement...). Je suis pas sur de la declaration du vecteur d'IT....mais cela ressemble à cela!!
#pragma nterruptlow Timer_0
void Timer_0(void)
{
TopTension++;
INTCONbits.TMR0IF=0;//mise à zero du flag d'IT
}
_DINT(); et _EINT(); sont des fonction que tu dois creer pour disable IT et Enable IT...en effet ta variable TopTension sera modifier sous IT...donc quand tu la decremente...il faut arreter les IT...c'est une bonne pratique de codage!!;)
@+
Je pense qu'en effet, si ton horloge est à 20mHz, alors tu dois avoir un prescaler de base sur Fosc... donc sinon cela me ferai 1/5mhz =200ns, 200ns*4*65536 = 0.052...s soit 52ms doit etre la soluce...
Tu dois pouvoir choisir le mode de comptage (Up,Down,Up-Down...) regarde dans le registre si cela est le cas...sinon je pense que par defaut, cela doit etre en mode up.
Si j'ai bien compris, le timer va s'incrémenter tout seule, jusqu'au débordement du registre TRM0, TMR0IF passe a 1; et ensuite on passe dans l'IT ??
Tu as parfaitement compris!!
Tu dois juste définir le vecteur d'IT (c'est en fait la fonction qui va être appelé quand tu as ton débordement...). Je suis pas sur de la declaration du vecteur d'IT....mais cela ressemble à cela!!
#pragma nterruptlow Timer_0
void Timer_0(void)
{
TopTension++;
INTCONbits.TMR0IF=0;//mise à zero du flag d'IT
}
_DINT(); et _EINT(); sont des fonction que tu dois creer pour disable IT et Enable IT...en effet ta variable TopTension sera modifier sous IT...donc quand tu la decremente...il faut arreter les IT...c'est une bonne pratique de codage!!;)
@+
chuka
Messages postés
965
Date d'inscription
samedi 11 octobre 2008
Statut
Membre
Dernière intervention
29 juillet 2010
378
Modifié par chuka le 23/06/2010 à 16:45
Modifié par chuka le 23/06/2010 à 16:45
#define uchar unsigned char void main(void) { uchar choix[]={0x01,0x05,0x09,0x0D}; uchar index=0; timer_init(); adc_init(); while(1){ if (TopTension){ adc_conv(choix[index],index); calc_tens(); if ((++index)>sizeof(choix))//evite les debordements index=0; _DINT(); TopTension--; _EINT(); } } } void adc_conv(uchar choix,uchar index) { LATD&=0xC3; //mise à zero des led LATD|=0x04<<index;//mise à 1 de la led ADCON0=choix; // Sélection du can; ADCON1=0b00001110; // ADCON2=0b10101100; ADCON0bits.ADON=1; ADCON0bits.GO_DONE=1; // début convertion while(ADCON0bits.GO_DONE); // attente convertion ADCON0bits.GO_DONE=0; // fin convertion LATB=ADRESL; LATC=ADRESH; ADCON0=0x00; // can éteint }
mik3fly
Messages postés
6
Date d'inscription
mercredi 23 juin 2010
Statut
Membre
Dernière intervention
9 septembre 2011
1
Modifié par mik3fly le 23/06/2010 à 17:20
Modifié par mik3fly le 23/06/2010 à 17:20
merci pour ton aide!! Je vais continuer avec ce que tu me propose!! et essayer plusieurs autres possibilité !!
pour _DINT()
{
INTCONbits.GIE=0;
}
et EINT()
{
INTCONbits.GIE=1;
}
rien de plus simple non???
(après tous ça, je m'attaque au filtre numérique^^)
pour _DINT()
{
INTCONbits.GIE=0;
}
et EINT()
{
INTCONbits.GIE=1;
}
rien de plus simple non???
(après tous ça, je m'attaque au filtre numérique^^)