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 : Gérard
[PASCAL] problème interruptions timer0 et UART
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!!
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- Messages : 2722
- Âge : 45
- Enregistré en : juillet 2015
- Localisation : Dans le sud
- Contact :
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 !
[PASCAL] problème interruptions timer0 et UART
Bonjour
Si tu as 3 digits pour quoi :
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
Si tu as 3 digits pour quoi :
Code : Tout sélectionner
if iDisp = 4 then
iDisp := 1;
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
Bonjour Jérémy. Merci pour ton accueil!! C'est mon premier post concernant les PIC. DS ajoutée
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 , là le flag bit est bien remis a zéro.)
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 , là le flag bit est bien remis a zéro.)
[PASCAL] problème interruptions timer0 et UART
[PASCAL] problème interruptions timer0 et UART
Code : Tout sélectionner
Pourquoi avoir configurer ton UART à 9615 bauds ? et non 9600 Bauds ?
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.
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- Messages : 2722
- Âge : 45
- Enregistré en : juillet 2015
- Localisation : Dans le sud
- Contact :
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
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
[PASCAL] problème interruptions timer0 et UART
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
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
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
Re-bonjour!
En modifiant les données envoyées, le code du pic récepteur se comporte beaucoup mieux.
Voici les instructions d'émissions:
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:
idem pour l'envoi du caractère 'z'
devient
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.
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');
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 58 invités