Probléme avec interruption INTCON.RBIE sur 16F88...

Bonjour =E0 tous,

j'essaie d'utiliser l'interruption RBIE pour compter des impulsions sur le PortB.7

=E7a fonctionne, mais mal, car chaque impulsion d=E9clenche 2 fois l'interruption... au lieu d'une...

pour le cablage, j'ai mis un BP sur le PortB.7 configur=E9 en entr=E9e, et 7 leds sur les ports PortB.0:6 configur=E9s en sorties, leds pour visualiser en binaire le comptage des impulsions...

ci-dessous, le code complet, en MikroBasic...

si je met les leds sur PortA, =E7a fonctionne... mais je veux les garder sur le PortB...

merci d'avance pour tous vos eclaircissements,

vede ;O]

program testint

dim i, compteur as byte

sub procedure interrupt PortB =3Dcompteur ' allume des leds inc(compteur) ' incr=E9mente le compteur Delay_ms(200) ' d=E9lai avant re-activation interruption INTCON =3D%10001000 ' GIE =3D 1; RBIE =3D 1; RBIF =3D 0; end sub

main: OSCCON=3D%1110000 ' choix oscillateur interne, =E0

8Mhz while testbit(OSCCON,IOFS)=3D0 wend ' attente stabilisation oscillateur

ANSEL =3D%00000000 ' met tous les ports en num=E9rique TrisA =3D%00000000 ' met tous les ports A en sorties TrisB =3D%10000000 ' met RB7 en entr=E9e, autres ports RBx en sorties PortA =3D%00000000 ' met tous les ports A =E0 0 PortB =3D%00000000 ' met tous les ports B =E0 0

i =3D0 compteur =3D0 ' init compteur INTCON =3D%10001000 ' GIE =3D 1; RBIE =3D 1; RBIF =3D 0; while i =3D0 wend ' boucle infinie

end.

Reply to
vede
Loading thread data ...

vede a écrit :

ben t'as tout simplement des rebonds sur le bouton poussoir.

dans toute application, toutes les entrées doivent être filtrées correctement...

JJ

Reply to
jj

compteur

tivation

x oscillateur interne, =E0

en num=E9rique

rts A en sorties

=E9e, autres ports

A =E0 0

B =E0 0

ur

Bonsoir jj,

j'aimerais bien que ce soit simplement =E7a... mais je crois pas... vu que le cablage fonctionne si j'utilise l'interruption INTE sur RB0 comme entr=E9e.... et surtout qu'il y a une temporisation de 200ms avant re-activation de l'interruption... qui fait "office" d'anti-rebonds....

en fait le probl=E9me vient du fait que quand j'assigne le PortB pour allumer les leds, cela re-engendre une interruption... bizarre... car c'est avant que j'ai remis RBIF =E0 0...

et si je met les leds sur le PortA (j'ai fait le test), =E7a fonctionne... avec PortA=3Dcompteur au lieu de PortB=3Dcompteur

merci d'avance pour vos eclaircissements,

vede ;O]

Reply to
vede

Bonsoir,

comme il y avait une petite erreur dans le copi=E9/coll=E9 du code, je le remet, c'est plus clair...

program testint

dim compteur as byte

sub procedure interrupt INTCON =3D%00000000 PortB =3Dcompteur ' allume des leds inc(compteur) ' incr=E9mente le compteur Delay_ms(200) ' d=E9lai avant re-activation INTCON =3D%10001000 ' GIE =3D 1; RBIE =3D 1; RBIF =3D 0; end sub

main: OSCCON=3D%1110000 ' choix oscillateur interne, =E0 8Mhz while testbit(OSCCON,IOFS)=3D0 wend ' attente stabilisation oscillateur

ANSEL =3D%00000000 ' met tous les ports en num=E9rique TrisA =3D%00000000 ' met tous les ports A en sorties TrisB =3D%10000000 ' met RB7 en entr=E9e, autres ports RBx en sorties PortA =3D%00000000 ' met tous les ports A =E0 0 PortB =3D%00000000 ' met tous les ports B =E0 0

compteur =3D0 ' init compteur INTCON =3D%10001000 ' GIE =3D 1; RBIE =3D 1; RBIF =3D 0; while true wend ' boucle infinie

end.

Reply to
vede

vede a écrit :

ben oui, mais ça c'est pas bon du tout !

d'abord, mettre une tempo dans une interruption, c'est à proscrire, le code sous interruption doit être conçu pour être exécuté le plus rapidement possible, car tu bloques toutes les ressources.

Ce qui se passe :

- premier changement => tu entre dans la routine d'interruption

- tu mets à 0 le GIE

- un rebond arrive et est latché

- après ta tempo, tu repasses GIE à 1 et la 2eme interruption est appelée.

effectivement tu en auras deux, à condition que tu aies moins de 200ms de rebonds, en général, un filtrage à 50ms suffit.

Ce que je te propose et qui est plus simple et plus fiable :

1) tu utilises un timer pour générer des impulsions toutes les ms environ

2) dans cette routine d'interruption, tu lis la valeur de ton port: si il est à 0 => tu places 50 dans une variable "bouton" par exemple si il est à 1 => tu décrémentes la variable jusque 0 (pour ne pas être négatif)

3) la lecture de la valeur de "bouton" te permet de connaitre l'état de ton bouton : si bouton est == 0, alors le bouton est appuyé.

la lecture se fait de préférence dans la boucle principale, plutôt que dans l'interruption.

très simple et très fiable.

si tu veux générer une seule exécution sur l'appui, il faut alors créer un front montant, c'est très simple : tu utilises une seconde variable: bouton_précédent

ensuite, tu testes que ((bouton==0) et (bouton_précédent==1))

si ok tu exécutes ton code

et enfin tu fais bouton_précédent=bouton.

ainsi bouton_précédent aura toujours un "tour" de retard, et la combinaison testée n'apparaitra qu'une seule fois.

c'est simple, logique, rigoureux, efficace.

JJ

Reply to
jj

jj a écrit :

J'ai un peu plus simple à proposer sinon, mais par contre le filtrage sera moins efficace et ce sera plus sensible aux parasites:

si tu détectes une interruption, tu passes la variable bouton à 1

dans ta boucle, tu tests la variable bouton qui va passer à 1 sur un appui...

tu attends ensuite 200ms et tu remets à 0

toutes les mises à 1 intempestives seront ignorées pendant 200ms

exemple (je ne connais pas la syntaxe basic, il faudra sans doute corriger)

program testint

dim compteur as byte

dim bouton as byte

sub procedure interrupt bouton = 0 INTCON =%10001000 ' GIE = 1; RBIE = 1; RBIF = 0; end sub

main: OSCCON=%1110000 ' choix oscillateur interne, à 8Mhz while testbit(OSCCON,IOFS)=0 wend ' attente stabilisation oscillateur

ANSEL =%00000000 ' met tous les ports en numérique TrisA =%00000000 ' met tous les ports A en sorties TrisB =%10000000 ' met RB7 en entrée, autres ports RBx en sorties PortA =%00000000 ' met tous les ports A à 0 PortB =%00000000 ' met tous les ports B à 0

compteur =0 ' init compteur bouton = 0 INTCON =%10001000 ' GIE = 1; RBIE = 1; RBIF = 0;

while true

if (bouton=1) then

delay(200) bouton=0 endif

wend ' boucle infinie

end.

Reply to
jj

le compteur

activation

0;

' choix oscillateur interne,

s en num=E9rique

ports A en sorties

ntr=E9e, autres ports

ports A =E0 0

ports B =E0 0

ompteur

=3D 0;

le

plus

ms

environ

emple

ne pas

=F4t que

s
e
1))

ger)

;

choix oscillateur interne,

en num=E9rique

orts A en sorties

r=E9e, autres ports

rts A =E0 0

rts B =E0 0

pteur

=3D 0;

=3D 0;

Bonsoir jj,

et merci pour ton aide

mais bon, comme cette hitoire de "double interruption" m'=E9nerve, je vais utiliser INTE (RB0) en attendant de mieux comprendre...

vede ;O]

Reply to
vede

Ne mets pas de tempo dans une IT, ca fait mal de voir ca ;-) Est-ce que ton IT se d=E9clenche sur front montant ET front descendant ? Ca expliquerait le doublement.

Reply to
Jean-Christophe

En relisant la question de départ, en espérant qu'elle soit bien formulée, cela ne semble pas un probleme lié aux interruptions, mais plutot lié a la gestion du port par le compilateur Basic. en effet il dit "si je met les leds sur PortA, ça fonctionne..." donc il ne change pas le bouton poussoir de place ni sa tempo, ni anti-rebond ni autre. Simplement il deplace les leds ( sorties 0 a 6) d'un port a l'autre. Donc c'est plutot un probleme sur la commutatation des configs de port ( a priori dans la bibliotheque de Mikro Basic) et cela pourrait créer un probleme dans ce compilo si on mélange une entrée interruption et 7 sorties. sur le meme port. J'ai eu un probleme similaire avec les include d'un autre compilo basic. Le seul moyen de trouver a été de décortiquer le code assembleur généré, d'isoler le bug et de créer une routine corrigée. Cela date de 6 ou 8 ans donc je ne me souviens plus des details, mais les routines contenues dans les includes ( qui traduisent les macros du langage Basic) contiennent parfois des pièges.

--

Alain
Reply to
alain denis

Bonjour =E0 tous,

=E9n=E9r=E9...

en effet, j'en suis l=E0...

apr=E9s avoir enlev=E9/d=E9plac=E9 la temporisation et la re-init. de l'int= en dehors de l'int. elle-m=EAme... puis avec un anti-rebond hardware (RC)... sans r=E9sultats... merci =E0 tous pour votre soutien... et je vous tiens au jus.... quand =E7a fonctionnera....

vede ;O]

ps

-il faut "lire ou =E9crire" le portB, avant de pouvoir re-initialiser RBIF...

-l'interruption RBIE g=E9n=E9re une interruption sur chaque flanc (Interrupt On Change)

-=E9viter de mettre une temporisation dans une interruption....

-=E9viter de re-initialiser l'interruption dans l'interruption...

d'apr=E9s le datasheet (paragraphes 2.3, 5.2 et 15.10.3 du 16F88)...et des avis... ce que je m'efforce de faire...sans succ=E9s...;O[

pour info, mon code d'interruption actuel>

sub procedure interruption inc (compteur) i=3D1 end sub

je peux pas faire plus court... d'ailleurs plus rien ne marche.... aucune led s'allume... bon, bonn'nuit... et =E0 demain... ;O]

Reply to
vede

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.