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 en BASIC et PASCAL !

Modérateur : Gérard

[PASCAL] problème interruptions timer0 et UART
k_lab
Membre
Membre
Messages : 10
Enregistré en : septembre 2016

#1 Message par k_lab » sam. 10 sept. 2016 17:50

Bonjour à tous,

je développe avec mikroPascal un module d'affichage (3 x 7 segments) multiplexés (ils s'allument tour à tour). Cet affichage reçoit ses données via UART.

Les interruptions du timer0 cadencent l'affichage alterné et les données à afficher. L'interrution UART s'occupe de réceptioner les données. Les deux interruptions (timer0 et UART) fonctionnent bien chacune de leur côté mais dès qu'elles sont ensemble dans le code, les interruptions du module UART pilote aussi les interruptions du timer0. En clair, les afficheurs s'allument tour à tour au rythme des données reçues, alors que ça devrait être indépendant... Autre info: la led du PORTC.6 ne clignote plus dès qu'une donnée est reçue et la boucle "while true" semble bloquée jusqu'au prochain reset.

Je sais que les procédures d'interruptions sont chargées, mais quand je sors des éléments vers la boucle principale, l'affichage ne fonctionne plus bien ou les données UART ne sont plus récupérées correctement... ou alors le problème se trouve ailleurs...

Le PIC en question est un 16F687 oscillateur interne à 8 Mhz.

Merci pour votre lecture et aide éventuelle!!

Code : Tout sélectionner

program DISPLAYV2;

{
 Declarations section }

var
iValue: word;
iDisp: byte;
txt: string[5];
RxStatus: byte;
RxData: byte;

function DispChar(charnum: byte): byte;
begin
     case charnum of
          0 
: result := %11000000;
          1 : result := %11111001;
          2 : result := %10100100;
          3 : result := %10110000;
          4 : result := %10011001;
          5 : result := %10010010;
          6 : result := %10000010;
          7 : result := %11111000;
          8 : result := %10000000;
          9 : result := %10010000;

     end;
end;

procedure Disp_Refresh;
var
toDisp: byte;

begin
     PORTC.5 
:= 0;     // display 1 off
     PORTA.4 := 0;     // display 2 off
     PORTA.5 := 0;     // display 3 off

     case iDisp of
          1 
: begin
            toDisp 
:= iValue mod 10;   // unités
            PORTC.5 := 1;              // display 1 on
            end;
          2 : begin
            toDisp 
:= (iValue div 10) mod 10;   // dizaines
            if iValue >= 10 then
            PORTA.4 
:= 1;              // display 2 on
            end;
          3 : begin
            toDisp 
:= (iValue div 100) mod 10;  // centaines
            if toDisp <> 0 then
            PORTA.5 
:= 1;              // display 3 on
            end;
      end;

      toDisp := DispChar(toDisp);

      PORTA.2 := toDisp.0;
      PORTC.0 := toDisp.1;
      PORTB.6 := toDisp.2;
      PORTB.4 := toDisp.3;
      PORTC.2 := toDisp.4;
      PORTA.1 := toDisp.5;
      PORTA.0 := toDisp.6;
      PORTC.1 := toDisp.7;
end;

procedure Interrupt;
begin
if INTCON
.T0IF =  1 then        // timer 0 overflow
   begin
        INTCON
.T0IF := 0;         // reset flag to enable further interrupts
        Inc(iDisp);
        if iDisp = 4 then
        iDisp 
:= 1;
        Disp_Refresh;

        PORTC.7 := PORTC.7 xor 1
   end
;
   
if PIR1
.RCIF = 1 then // interruption réception donnée module UART
begin

     RxStatus 
:= RCSTA;    // détection erreur flux de données reçues
     RxData := RCREG;      // lire ce registre pour reset UART Interrupt flag
     if (RxStatus and %00000110) = 0 then  // si pas d'erreur
        begin
        UART1_Read_Text
(txt, '*', 10);

        if txt[0] = 'z' then

          PORTC.4 
:= PORTC.4 xor 1;
          if txt[0] <> 'z' then

          iValue 
:= StrToword(txt)

else
begin                        // si erreur on efface!
Clearbit(RCSTA , CREN);
Setbit(RCSTA, CREN);//
end;



end;
end;
end;

procedure mainInit;

begin

  OSCCON
.SCS := 1;               // Internal oscillator is used for system clock
  OSCCON.IRCF0 := 1;           // 8 Mhz Internal Clock
  OSCCON.IRCF1 := 1;           // 8 Mhz Internal Clock
  OSCCON.IRCF2 := 1;           // 8 Mhz Internal Clock

  CM1CON0 := 0;                 // comparator C1 off
  CM2CON0 := 0;                 // comparator C2 off

  TRISA := %00001000;
  TRISB := %00100000;            // RB5 = RX = USART IN
  TRISC := %00000000;

  ANSEL := %00000000;          // disable analog channels
  ANSELH := %00000000;         // disable analog channels
  //ADC_Init;                    // initialize adc module

  INTCON.GIE := 1;             // global Interrupts enable
  INTCON.PEIE := 1;            // peripheral interrupts enable

  OPTION_REG.T0CS := 0;        // source: internal FOSC/4 for timer 0
  OPTION_REG.PSA := 0;         // prescale assigned to timer 0
  OPTION_REG.PS0 := 1;         //
  OPTION_REG.PS1 := 0;         // 1:64
  OPTION_REG.PS2 := 1;         //

  INTCON.T0IE := 1;            // enable timer 0 interrupts
  INTCON.T0IF := 1;            // reset timer 0 flag


  delay_ms(100);               // stabilize

  
  
///////////////USART
  
  TXSTA
.TX9 :=0;
  TXSTA.TXEN := 1;
  RCSTA.CREN := 1;
  RCSTA.SPEN :=1;
  PIE1.RCIE := 1;              // enable uart RX interrupts
  PIE1.TXIE := 0;              // no TX interrupt
  UART1_init(9615);            // initialize UART module for RS232 display
  delay_ms(200);               // stabilize


  


  
// display off

  PORTA.0 :=  1;
  PORTA.1 :=  1;
  PORTA.2 :=  1;
  PORTC.0 :=  1;
  PORTB.6 :=  1;
  PORTB.4 :=  1;
  PORTC.2 :=  1;
  PORTC.1 :=  1;

end;



begin
  
{ Main program }
  mainInit;

  iDisp := 1;
  iValue := 0;


  while true do
  begin
    PORTC.6 
:= PORTC.6 xor 1;
    delay_ms(200);
  end;




end
Modifié en dernier par k_lab le sam. 10 sept. 2016 20:17, modifié 1 fois.

[PASCAL] problème interruptions timer0 et UART
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#2 Message par Jérémy » sam. 10 sept. 2016 18:58

 ! Message de modération :
Bonjour et bienvenue K_Lab,

Le forum FantasPic n'a pas encore de catégorie pour le PASCAL. Une fusion avec le langage BASIC me semble judicieux, car vous êtes peu nombreux dans ces langages.

J'ai donc déplacé ton message et rajouté un index sur ton titre afin de reconnaitre en un seul coup d’œil le langage utilisé.

Afin d'obtenir un maximum de réponse, mais aussi pour me servir de cobaye pour un bug non résolu, je te propose de suivre cette procédure pour mettre le lien de la DS de ton PIC : Procédure

Merci à toi


Je ne connais pas du tout le PASCAL . Mais effectivement les deux INT devraient ne pas avoir de liens. Je les utilise très bien dans le même genre .

je trouve cette ligne bizarre :
INTCON.T0IF := 1; // reset timer 0 flag
Pour RAZ le flag il faudrait le mettre à 0 et non à 1 ?

J’espère qu'un expert pourra mieux t'aider que cela !

Encore bienvenue à toi !
C'est en faisant des erreurs, que l'on apprend le mieux !!!

[PASCAL] problème interruptions timer0 et UART
Guest
Confirmé
Confirmé
Messages : 800
Enregistré en : mars 2017

#3 Message par Guest » sam. 10 sept. 2016 19:11

Bonjour

Si tu as 3 digits pour quoi :

Code : Tout sélectionner

       if iDisp = 4 then
        iDisp := 1;
en compte 4

Lorsque tu as 2 int, et que tu n'as d'un seul "Vecteur d'interruption" il faut déterminer celle qui sera prioritaire, le timer ou l'UART. AMHA c'est l'UART ,pour bloquer le timer soit tu arrêtes le timer soit tu bloques son INT voir la DS

A+

soit le bienvenu, dommage en pascal ma tasse de thé c'est ASM

[PASCAL] problème interruptions timer0 et UART
k_lab
Membre
Membre
Messages : 10
Enregistré en : septembre 2016

#4 Message par k_lab » sam. 10 sept. 2016 20:26

Bonjour Jérémy. Merci pour ton accueil!! C'est mon premier post concernant les PIC. DS ajoutée :-D
Merci pour ta remarque très juste! (je me suis rué dans mon code, mais cette ligne se trouve dans la routine d'initialisation et pas dans la routine d'interruption qui m'occupe :sad: , là le flag bit est bien remis a zéro.)

[PASCAL] problème interruptions timer0 et UART
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#5 Message par Jérémy » sam. 10 sept. 2016 20:38

Merci pour le lien de la DS.

Le conseil de maï est juste . essaye de désactiver l'INT du timer0 pendant le traitement de l'UART !

Pourquoi avoir configurer ton UART à 9615 bauds ? et non 9600 Bauds ?
C'est en faisant des erreurs, que l'on apprend le mieux !!!

[PASCAL] problème interruptions timer0 et UART
k_lab
Membre
Membre
Messages : 10
Enregistré en : septembre 2016

#6 Message par k_lab » dim. 11 sept. 2016 09:18

Code : Tout sélectionner

Pourquoi avoir configurer ton UART à 9615 bauds ? et non 9600 Bauds 
car le PIC qui envoie les données est configuré à 9615 bauds, j'ai vu que mikropascal a "optimisé" ce paramètre lors de la compilation...

Je viens d'essayer le conseil de maï (merci!) j'ai inversé les deux procédures et désactivé le timer0 enable bit dans la procédure interrupt liée à l' UART. Pas de changement. :sad:

Code : Tout sélectionner

procedure Interrupt;
begin

if PIR1
.RCIF = 1 then // interruption réception donnée module UART
begin
     INTCON
.T0IE := 0;      // désactive les interruptions du timer 0
     RxStatus := RCSTA;    // détection erreur flux de données reçues
     RxData := RCREG;      // lire ce registre pour reset UART Interrupt flag
     if (RxStatus and %00000110) = 0 then  // si pas d'erreur
        begin
        UART1_Read_Text
(txt, '*', 10);
        if txt[0] = 'z' then
        PORTC.4 
:= PORTC.4 xor 1;
        if txt[0] <> 'z' then
        iValue 
:= StrToword(txt);
        INTCON.T0IE := 1;     // réactive les interruptions du timer 0
      end
      else
      begin                        
// si erreur on efface!
      Clearbit(RCSTA , CREN);
      Setbit(RCSTA, CREN);//
      INTCON.T0IE := 1;           // réactive les interruptions du timer 0
      end;

end;

if INTCON.T0IF =  1 then        // timer 0 overflow
   begin
        INTCON
.T0IF := 0;         // reset flag to enable further interrupts
        Inc(iDisp);
        if iDisp = 4 then
        iDisp 
:= 1;
        Disp_Refresh;

        PORTC.7 := PORTC.7 xor 1
   end
;
end;


Autre signe inquiétant: la boucle main loop qui elle s'arrète complètement...

[PASCAL] problème interruptions timer0 et UART
Jérémy
Administrateur du site
Administrateur du site
Messages : 2722
Âge : 44
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#7 Message par Jérémy » dim. 11 sept. 2016 10:03

Bonjour,

Edit:
Merci à toi, je viens de trouver la cause du probléme. il ne me reste qu'a transmettre pour le résoudre . On va y arriver !

Sinon en décodant un peu le PASCAL, je trouve ta façon de traiter l'INT UART pas très catholique ou alors j'ai pas tout saisi ( fort probable).
Quelles sont les données que tu reçois par l'UART ?
Tu stock la donnée reçue dans la variable RxData, celle si par la même occasion RAz le flag . Mais ensuite tu n'en fais rien?

L'UART reçoit un caractère par un caractère il faut délimiter ta reception , pour connaitre la fin de ta donnée
C'est en faisant des erreurs, que l'on apprend le mieux !!!

[PASCAL] problème interruptions timer0 et UART
Guest
Confirmé
Confirmé
Messages : 800
Enregistré en : mars 2017

#8 Message par Guest » dim. 11 sept. 2016 10:30

bonjour

il serai bien de voir tout les combien ton réactivation des digits se fait amha c'est du rapide puisque pas le temps de voir ta boucle il faudrait etre a 500ms entre chaque reactualisation

je te propose cela
tu mets une variable dans le timer a chaque int timer, tu incréments variable lorsque variable =4 (avoir) tu fais une réactivation de affichage et variable=0

ps: pour idisp me suis plante c'est bien 3, attention dans case pas vue par default

[PASCAL] problème interruptions timer0 et UART
k_lab
Membre
Membre
Messages : 10
Enregistré en : septembre 2016

#9 Message par k_lab » dim. 11 sept. 2016 15:21

Jérémy a écrit :Bonjour,

Edit:
Merci à toi, je viens de trouver la cause du probléme. il ne me reste qu'a transmettre pour le résoudre . On va y arriver !

Sinon en décodant un peu le PASCAL, je trouve ta façon de traiter l'INT UART pas très catholique ou alors j'ai pas tout saisi ( fort probable).
Quelles sont les données que tu reçois par l'UART ?
Tu stock la donnée reçue dans la variable RxData, celle si par la même occasion RAz le flag . Mais ensuite tu n'en fais rien?

L'UART reçoit un caractère par un caractère il faut délimiter ta reception , pour connaitre la fin de ta donnée


Salut Jérémy, merci pour ton attention!

Effectivement, je ne fais rien directement de RxData cette ligne est facultative car le registre est lu avec la routine UART1_Read_Text. Cette routine utilise le délimiteur * . La réception marche bien. Je reçois un entier (word) sous forme de texte (wordToString puis String to word). La donnée est bien reçue et iValue prend la bonne valeur. L'action prévue a la réception du caractère 'z' fonctionne aussi. J'ai augmenté la dimension de la variable txt (string[5] -> string[6]) mais c'est pas ça non plus. Je vais poster plus de détails sur le code du PIC qui envoie les données.

@maï: j'ai réglé le prescaler du timer0 afin d'avoir un affichage correctement rafraîchi. (pas trop vite mais pas trop lent non plus pour que l'affichage ne tremble pas). Je vais essayer de sortir de la procédure d'interruption, les opérations d'extraction des unités / dizaines / centaines.

Merci pour vos remarques constructives!

[PASCAL] problème interruptions timer0 et UART
k_lab
Membre
Membre
Messages : 10
Enregistré en : septembre 2016

#10 Message par k_lab » dim. 11 sept. 2016 16:49

Re-bonjour!

En modifiant les données envoyées, le code du pic récepteur se comporte beaucoup mieux.

Voici les instructions d'émissions:

Code : Tout sélectionner

wordtostr(tempo, txtA);
              txtB := txtA + '*0';
              UART1_Write_Text(txtB);


j'envoie la donnée "tempo" (20 - 270) sous forme de string. Lorsque que j'enlève le caractère nul après le délimiteur "*", magie mon affichage fonctionne comme prévu. Le code fonctionnel est donc celui-ci:

Code : Tout sélectionner

wordtostr(tempo, txtA);
              txtB := txtA + '*';
              UART1_Write_Text(txtB);


idem pour l'envoi du caractère 'z'

Code : Tout sélectionner

UART1_Write_Text('z*0');
devient

Code : Tout sélectionner

UART1_Write_Text('z*');


Seul bémol: l'envoi du caractère 'z' ne déclenche plus l'action escomptée dans le PIC réception (allumer ou éteindre PORTC.4).
Si je laisse le caractère nul '0' pour terminer la chaine envoyée, mon PIC récepteur adopte le comportement décris plus haut mais la led réagit comme je voudrais!

Peut-être mes envois de données sont maladroits (ce sont mes premiers essais avec l'UART).

Merci pour votre lecture et vos réflexions.


Retourner vers « Langage BASIC & PASCAL »

Qui est en ligne

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