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
Mesurer une suite de délais avec Timer5
-
Superphénix
Débutant- Messages : 54
- Enregistré en : mars 2020
Bonjour
Je souhaite mesurer précisément (au moins au 2000ème près) le temps qui s'écoule entre les fronts descendants sur le pin RC0 d'un PIC16F1779. J'utilise déjà des interruptions pour 4 autres pins.
Ce que j'ai pensé faire c'est que ma fonction d'interruption teste en tout premier si l'interruption viens de RC0 et si oui, alors elle prends directement la valeur du Timer5 (16bits) pour l'envoyer vers une fonction qui fait la soustraction avec la valeur précédente. Et si non, elle teste si l'interruption vient des autres boutons pour renvoyer vers d'autres fonctions...
Les délais à mesurer entre deux fronts descendants feront entre approximativement 0.04 et 4 secondes. Et si jamais on dépasse environ 4s, alors le compteur doit être remis à 0 et le timer éteint jusqu'au prochain front descendant.
Est ce que c'est la meilleur méthode pour mesurer le temps dans mon cas ? Et quelle source d'horloge vaut t-il mieux choisir ?
Ne se pourrait t-il pas qu'après avoir lu TMR5L pile au moment où TMR5=0b1111111111111111, je lise TMR5H qui est en train de passer à 0b00000000 et que le résultat lu donne 0b0000000011111111 ?
Je souhaite mesurer précisément (au moins au 2000ème près) le temps qui s'écoule entre les fronts descendants sur le pin RC0 d'un PIC16F1779. J'utilise déjà des interruptions pour 4 autres pins.
Ce que j'ai pensé faire c'est que ma fonction d'interruption teste en tout premier si l'interruption viens de RC0 et si oui, alors elle prends directement la valeur du Timer5 (16bits) pour l'envoyer vers une fonction qui fait la soustraction avec la valeur précédente. Et si non, elle teste si l'interruption vient des autres boutons pour renvoyer vers d'autres fonctions...
Les délais à mesurer entre deux fronts descendants feront entre approximativement 0.04 et 4 secondes. Et si jamais on dépasse environ 4s, alors le compteur doit être remis à 0 et le timer éteint jusqu'au prochain front descendant.
Est ce que c'est la meilleur méthode pour mesurer le temps dans mon cas ? Et quelle source d'horloge vaut t-il mieux choisir ?
Ne se pourrait t-il pas qu'après avoir lu TMR5L pile au moment où TMR5=0b1111111111111111, je lise TMR5H qui est en train de passer à 0b00000000 et que le résultat lu donne 0b0000000011111111 ?
Mesurer une suite de délais avec Timer5
Bonjour, tu chômes pas :)
Le mode capture du module CCP il sert pas à ça ? je le connais pas bien.
Le fait qu'il y ait plusieurs sources d'interruption et pas de réglage des priorités sur les 16F, rallonge le temps de prise en compte des événements, mais bon si on parle de ms cela devrait passer, mais pour le 2000ème (de quoi ?), c'est une autre histoire, tout dépend de ton horloge. L'oscillateur interne est moins précis qu'un quartz, la PLL monte à Fosc = 32MHz avec les deux.
Pour le timer 16 bits lu en 2 fois, j'ai rien vu dans le datasheet si ce n'est qu'il parle de ce problème. Tu peux faire 2 lectures de TMRH avec entre les deux la lecture de TMRL. Si TMRH a changé, TMRL doit être de faible valeur.
Dans l'exemple plus bas, si TMRH a changé ils font une nouvelle lecture complète.
https://www.google.fr/url?sa=t&rct=j&q= ... h20zCiybHs
Example 12-2: Reading a 16-bit Free-Running Timer
Writing a 16-bit value to the 16-bit TMR1 register is straight forward. First the TMR1L register is
cleared to ensure that there are many Timer1 clock/oscillator cycles before there is a rollover into
the TMR1H register. The TMR1H register is then loaded, and finally the TMR1L register is loaded.
Example 12-3 shows this:
Example 12-3: Writing a 16-bit Free Running Timer
Sinon il existe des pic 16 bits, adapté au C, et très bons contre les maux de tête.
Le mode capture du module CCP il sert pas à ça ? je le connais pas bien.
Le fait qu'il y ait plusieurs sources d'interruption et pas de réglage des priorités sur les 16F, rallonge le temps de prise en compte des événements, mais bon si on parle de ms cela devrait passer, mais pour le 2000ème (de quoi ?), c'est une autre histoire, tout dépend de ton horloge. L'oscillateur interne est moins précis qu'un quartz, la PLL monte à Fosc = 32MHz avec les deux.
Pour le timer 16 bits lu en 2 fois, j'ai rien vu dans le datasheet si ce n'est qu'il parle de ce problème. Tu peux faire 2 lectures de TMRH avec entre les deux la lecture de TMRL. Si TMRH a changé, TMRL doit être de faible valeur.
Dans l'exemple plus bas, si TMRH a changé ils font une nouvelle lecture complète.
https://www.google.fr/url?sa=t&rct=j&q= ... h20zCiybHs
Example 12-2: Reading a 16-bit Free-Running Timer
Code : Tout sélectionner
; All interrupts are disabled
MOVF TMR1H, W ; Read high byte
MOVWF TMPH ;
MOVF TMR1L, W ; Read low byte
MOVWF TMPL ;
MOVF TMR1H, W ; Read high byte
SUBWF TMPH, W ; Sub 1st read with 2nd read
BTFSC STATUS,Z ; Is result = 0
GOTO CONTINUE ; Good 16-bit read
;
; TMR1L may have rolled over between the read of the high and low bytes.
; Reading the high and low bytes now will read a good value.
;
MOVF TMR1H, W ; Read high byte
MOVWF TMPH ;
MOVF TMR1L, W ; Read low byte
MOVWF TMPL ;
; Re-enable the Interrupt (if required)
CONTINUE ; Continue with your code
Writing a 16-bit value to the 16-bit TMR1 register is straight forward. First the TMR1L register is
cleared to ensure that there are many Timer1 clock/oscillator cycles before there is a rollover into
the TMR1H register. The TMR1H register is then loaded, and finally the TMR1L register is loaded.
Example 12-3 shows this:
Example 12-3: Writing a 16-bit Free Running Timer
Code : Tout sélectionner
; All interrupts are disabled
CLRF TMR1L ; Clear Low byte, Ensures no
; rollover into TMR1H
MOVLW HI_BYTE ; Value to load into TMR1H
MOVWF TMR1H, F ; Write High byte
MOVLW LO_BYTE ; Value to load into TMR1L
MOVWF TMR1H, F ; Write Low byte
; Re-enable the Interrupt (if required)
CONTINUE ; Continue with your code
Sinon il existe des pic 16 bits, adapté au C, et très bons contre les maux de tête.
Mesurer une suite de délais avec Timer5
Mesurer une suite de délais avec Timer5
Salut a tous,
Sacré Temps-X. Toujours là pour glisser un petit "ASM"
@++
Sacré Temps-X. Toujours là pour glisser un petit "ASM"
@++
Mesurer une suite de délais avec Timer5
-
Superphénix
Débutant- Messages : 54
- Enregistré en : mars 2020
Bonjour, tu chômes pas :)
Je profite du confinement ^^
Bon, j'ai passé toute la journée à lire la doc sur CCP, et le Timer1. Du coup j'ai déjà mieux compris tout ça et j'ai réglé quelques problèmes, dont la "lecture" de TMR1H/L que je vais bien faire avec le mode capture de CCP :)
Ce que j'ai écrit pour l'instant :
Code : Tout sélectionner
CCP2CAP = 0b00000000 ; // RC0 ─┐
CCP2PPS = 0b00010000 ; // xPPS <─┘
SSP2CON = 0b10000100 ; // Capture sur front descendant.
TSCON = 0b00110001 ; // Tosc/4 , :1/8
T5GCON = 0b00000000 ; // GE=0
PIE4bits.TMR5IE = 1 ; // Enable overflow interrupt
Ensuite j'ai prévu utiliser le interrupt flag généré par un overflow du Timer5 (TMR5IF) pour remettre le timer à 0 et éteindre le module, quand il ne se passe plus rien au bout du temps d'overflow.
Par contre j'arrive pas à trouver ce qui lie le bon CCPx au bon Timer. (CCP2 --> Timer5)
Le 2ème problème est qu'au maximum je peut mesurer des temps de 0.52s, alors qu'il me faudrait aller jusqu'à environ 4s. Je pourrais éventuellement régler le problème plus tard en utilisant un quartz de 500kHz au lieux du 4MHz. Pour le mode 32kHz j'ai trouver la tolérance dans la doc, elle n'est que de 1% (pas assez). Mais je me demande s'il n'y aurait pas une autre solution?
Sinon il existe des pic 16 bits, adapté au C, et très bons contre les maux de tête.
Pour l'instant j'ai pas l'intention de changer parce que dans les filtres de recherches de Microship c'était le seul PIC qui correspondait à ce que je cherchais, par contre c'est quoi un PIC adapté au C ?
Si tu veux de la précision sur les temps, il faut passer par ASM
Je sais, mais si je réapprends à utiliser l'ASM pour un programme aussi long j'y suis encore après le confinement, la 2ème vague de l'épidémie et la découverte de Sars cov 3 en 2035.
Mesurer une suite de délais avec Timer5
Bonjour,
Dans le datasheet il y a beaucoup de choses, alors quand tu lis une info, bien vérifier à quoi elle correspond, quel chapitre. Par exemple SSP2CON (introuvable dans la doc) pourrait concerner le module MSSP qui permet de communiquer en SPI ou I2C, qu'est ce qu'il fait là ?.
Pour la compréhension le premier paragraphe décrivant une fonction est souvent bien résumé.
Le paragraphe 24.1 capture dit qu'elle utilise exclusivement le Timer 1, stocke TIM1H:L dans CCPRH:L dès qu'un front est détecté.
Au choix :
- Every edge (rising or falling)
- Every falling edge
- Every rising edge
- Every 4th rising edge
- Every 16th rising edge
Une fois le Timer 1 configuré avec Fosc/4, le réglage de la capture se fait avec CCPxCON et CCPxCAP, tout y est.
Ensuite on dispose de 2 flags d'interruption, celui de la capture et celui du timer overflow.
Pour les temps longs, tu peux compter le nombre d'overflow du Timer 1.
Je sais pas si Timer 1 est remis à 0 à chaque capture, je te laisse le découvrir :)
Avec un quartz de 4MHz, Tcap est à 1 us, c'est suffisant non ?
C'est 1/2000 de seconde ou 1/2000 de la valeur mesurée ?
Un langage évolué a besoin d'une ram linéaire intégrant la pile, de nombreux registres, et des instructions facilitant le passage d'arguments aux sous-programmes.
Les pic 8 bits n'ont rien de tout ça. La ram est paginée, un seul registre W, la pile ne stocke que les adresses de retour lors d'appels de sous-programmes, pas les arguments. Sur les modèles récents de 16F et 18F ils ont ajouté des instructions pour améliorer la situation.
Dans le datasheet il y a beaucoup de choses, alors quand tu lis une info, bien vérifier à quoi elle correspond, quel chapitre. Par exemple SSP2CON (introuvable dans la doc) pourrait concerner le module MSSP qui permet de communiquer en SPI ou I2C, qu'est ce qu'il fait là ?.
Pour la compréhension le premier paragraphe décrivant une fonction est souvent bien résumé.
Le paragraphe 24.1 capture dit qu'elle utilise exclusivement le Timer 1, stocke TIM1H:L dans CCPRH:L dès qu'un front est détecté.
Au choix :
- Every edge (rising or falling)
- Every falling edge
- Every rising edge
- Every 4th rising edge
- Every 16th rising edge
Une fois le Timer 1 configuré avec Fosc/4, le réglage de la capture se fait avec CCPxCON et CCPxCAP, tout y est.
Ensuite on dispose de 2 flags d'interruption, celui de la capture et celui du timer overflow.
Pour les temps longs, tu peux compter le nombre d'overflow du Timer 1.
Je sais pas si Timer 1 est remis à 0 à chaque capture, je te laisse le découvrir :)
Avec un quartz de 4MHz, Tcap est à 1 us, c'est suffisant non ?
C'est 1/2000 de seconde ou 1/2000 de la valeur mesurée ?
Un langage évolué a besoin d'une ram linéaire intégrant la pile, de nombreux registres, et des instructions facilitant le passage d'arguments aux sous-programmes.
Les pic 8 bits n'ont rien de tout ça. La ram est paginée, un seul registre W, la pile ne stocke que les adresses de retour lors d'appels de sous-programmes, pas les arguments. Sur les modèles récents de 16F et 18F ils ont ajouté des instructions pour améliorer la situation.
Mesurer une suite de délais avec Timer5
- paulfjujo
Expert- Messages : 2597
- Âge : 73
- Enregistré en : juillet 2015
- Localisation : 01800
- Contact :
Bonjour,
La capture CCP ayant un domaine de capture restreint ...
utilises -tu la pin RB0 ?
si RB0 Int est disponible pour capturer l'evenement qui t'interesse sur RC0 ( liaison hard RC0 -> RB0)
It RB0 sur front Montant =>
* déclencher TMRxON sur un timer 16 bits (TRM1 ?)
avec un compteur d'overflow (si multiple overflow prévus ), ou simplement le test du TRMxIF pour savoir si il faut rajouter 1x65536
* modifier interrupt RB0 pour pouvoir agir sur l'evenement front Descendanrt
sur evenement Front Descendant RB0 :
lecture du timer
Meme en C, via l'usage du comptage par timer , on arrive à une bonne résolution de mesure temporelle ..
on a pas inventé le C pour rien ...
avec les 18F rescent, on ne se preoccupe plus du tout de la pagination des bank RAM ( en C)
(sauf si MikroC a des buggs !) contrairement au vieux 16F et le IRP_bit à gerer
ou si on veut y mettre un registre à decalage 96 bits en ASM
La capture CCP ayant un domaine de capture restreint ...
utilises -tu la pin RB0 ?
si RB0 Int est disponible pour capturer l'evenement qui t'interesse sur RC0 ( liaison hard RC0 -> RB0)
It RB0 sur front Montant =>
* déclencher TMRxON sur un timer 16 bits (TRM1 ?)
avec un compteur d'overflow (si multiple overflow prévus ), ou simplement le test du TRMxIF pour savoir si il faut rajouter 1x65536
* modifier interrupt RB0 pour pouvoir agir sur l'evenement front Descendanrt
sur evenement Front Descendant RB0 :
lecture du timer
Meme en C, via l'usage du comptage par timer , on arrive à une bonne résolution de mesure temporelle ..
on a pas inventé le C pour rien ...
avec les 18F rescent, on ne se preoccupe plus du tout de la pagination des bank RAM ( en C)
(sauf si MikroC a des buggs !) contrairement au vieux 16F et le IRP_bit à gerer
ou si on veut y mettre un registre à decalage 96 bits en ASM
Mesurer une suite de délais avec Timer5
-
Superphénix
Débutant- Messages : 54
- Enregistré en : mars 2020
SSP2CON (introuvable dans la doc)
Oups, faute de frappe, c'est : CCP2CON
Le paragraphe 24.1 capture dit qu'elle utilise exclusivement le Timer 1, stocke TIM1H:L dans CCPRH:L dès qu'un front est détecté.
Hmm, je l'utilise déjà pour le mode PWM... A la page 275 il est marqué "All references to Timer1 and Timer1 Gate apply to Timer3 and Timer5." Du coup je me suis dit qu'à chaque fois que je vais rencontrer le mot "Timer1" je vais considérer que ça vaut pour mon Timer5. Et j'ai vu qu'il existe aussi CCPR2H:L, CCPR7H:L, CCPR8H:L. C'est pour ça que j'ai fini par me poser la question de comment lier un CCPRxH:L au bon Timer.
Pour les temps longs, tu peux compter le nombre d'overflow du Timer 1.
Ok. Je vais faire comme ça.
Je sais pas si Timer 1 est remis à 0 à chaque capture, je te laisse le découvrir :)
J'ai cherché mais n'ayant rien trouvé je m'étais dit que j'allais le savoir en testant.
C'est 1/2000 de seconde ou 1/2000 de la valeur mesurée ?
C'est 1/2000 de la valeur mesuré. Selon mes calculs avec un préscalaire de 1:8 et sans pertes de temps j'ai 1/5000 pour un temps mesuré de 0.04s. Mais vue que je vais finalement faire la technique du comptage d'overflows je peut la remettre à 1:1. Donc 1/40000. Si on compte le temps perdu par la mise à 0 éventuelle après lecture de TIM1H:L, je ne sais pas où j'arrive mais ça devrait passer...
utilises -tu la pin RB0 ?
Oui, elle me sert pour autre chose déjà.
D'accord pour les PICs adaptés aux langages évolués.
Mesurer une suite de délais avec Timer5
Bonjour,
Il doit pas le remettre à zéro le Timer 1, afin de pouvoir programmer plusieurs captures différentes.
En soustrayant les captures de type unsigned int, on obtient la bonne valeur, même si le timer a fait un overflow entre les deux.
unsigned int mesure = capture_2 - capture_1
c'est valable s'il y a 0 ou 1 overflow.
S'il peut y avoir plus d'1 overflow
unsigned long mesure = capture_2 - capture_1
if (nb_overflow) mesure += 65536UL * (nb_overflow - (capture_2 < capture_1))
En remettant à zéro le timer, on simplifie, mais la mesure est moins précise car ce reset n'est pas immédiat.
unsigned long mesure = 65536UL * nb_overflow + capture;
C'est une vraie bête de course ce pic. Et j'ai rien contre les 8 bits, hein
C'est quoi le sujet de demain, qu'on puisse se préparer à l'avance
Il doit pas le remettre à zéro le Timer 1, afin de pouvoir programmer plusieurs captures différentes.
En soustrayant les captures de type unsigned int, on obtient la bonne valeur, même si le timer a fait un overflow entre les deux.
unsigned int mesure = capture_2 - capture_1
c'est valable s'il y a 0 ou 1 overflow.
S'il peut y avoir plus d'1 overflow
unsigned long mesure = capture_2 - capture_1
if (nb_overflow) mesure += 65536UL * (nb_overflow - (capture_2 < capture_1))
En remettant à zéro le timer, on simplifie, mais la mesure est moins précise car ce reset n'est pas immédiat.
unsigned long mesure = 65536UL * nb_overflow + capture;
C'est une vraie bête de course ce pic. Et j'ai rien contre les 8 bits, hein
C'est quoi le sujet de demain, qu'on puisse se préparer à l'avance
Mesurer une suite de délais avec Timer5
-
Superphénix
Débutant- Messages : 54
- Enregistré en : mars 2020
Bon, ça fait 2 jours que je suis bloqué, et je me rends compte maintenant que mon blocage est dû à une fonction d'affichage de nombres, créé il y a presque un mois et que j'utilise pour débuger, qui n'affiche pas correctement les valeurs supérieurs où = à 2^15. Du coup je ne peut pas encore répondre par rapport aux timer.
Il faut donc d’abord résoudre le problème de ma fonction d'affichage ^^
Je pense que le problème vient du type de donné "unsigned long" que j'utilise pour mon nombre.
Normalement le unsigned long avec XC8 devrait faire 32 bits et donc permettre de monter jusqu'à 4,2Mrd. Là on dirait un signed int...
Quand mon nombre est supérieur à 2^15 l’affichage me donne un nombre très élevé qui commence par un 9.
Du coup je ne comprends pas
Il faut donc d’abord résoudre le problème de ma fonction d'affichage ^^
Code : Tout sélectionner
void AFF_NBERS(unsigned long nbr, char rng, char ali) // Nombre de 0 à 999999 ; Digit N°4 à N°27 ; Alignement 1 à 6 digits ou 'L' à gauche, 'R' à droite.
{
unsigned char i=0, flag=0, DIG[6]={0, 0, 0, 0, 0, 0} ;
DIG[0] = (nbr%1000000)/100000 ; // Problème par ici ???
DIG[1] = (nbr%100000)/10000 ;
DIG[2] = (nbr%10000)/1000 ;
DIG[3] = (nbr%1000)/100 ;
DIG[4] = (nbr%100)/10 ;
DIG[5] = nbr%10 ;
if (ali=='L')
for(i=0; i<6; i++)
{
if ((DIG[i]!=0)||(i==5)) flag = 1 ;
if (flag==0) rng-- ;
if (flag==1) DIGIT(rng+i, DIG[i]+48) ; // La fonction DIGIT sert juste à afficher un chiffre entre 0 et 9 sur un digit de l'écran, et elle marche bien.
}
else if (ali=='R')
{
for(i=0; i<6; i++)
{
if (DIG[i]!=0) flag = 1 ;
if ((flag==0)&&(i!=5)) DIG[i]=127 ;
}
for(i=0; i<6; i++) if(DIG[5-i]!=127) DIGIT(rng-i, DIG[5-i]+48) ;
}
else
for(i=0; i<ali; i++) DIGIT(rng-i, DIG[5-i]+48) ;
}
Je pense que le problème vient du type de donné "unsigned long" que j'utilise pour mon nombre.
Normalement le unsigned long avec XC8 devrait faire 32 bits et donc permettre de monter jusqu'à 4,2Mrd. Là on dirait un signed int...
Quand mon nombre est supérieur à 2^15 l’affichage me donne un nombre très élevé qui commence par un 9.
Du coup je ne comprends pas
Qui est en ligne
Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 52 invités