Attention ! Fermeture imminente du forum d’Elektor (pour en savoir plus, cliquer ici). À partir du vendredi 1er mars il ne sera plus possible de s’identifier sur ce forum, mais son contenu restera disponible en lecture seule jusqu’à la fin du mois. Le 1er avril, il sera fermé définitivement.

Interruptions avec UART ???

Postby scorpion » Wed May 30, 2007 12:00 am

Salut nlc.

Malgré toutes tes explications et tes indications, je n’arrive pas à faire fonctionner les interruptions.
Je suis en train de me tirer les cheveux depuis 2 jours sans succès. J’ai plus ou moins tout essayé mais rien n’y fait.
Quand j’envoie un octet, la fonction d’interruption de réception n’est pas exécutée.

Explication :
J’ai établi un programme (ci-dessous) sur base de ton code en utilisant le principe des buffers mais uniquement pour la réception dans un premier temps (histoire de faire des tests d’interruptions).
En toute logique, le programme est censé stocker les octets reçus dans un buffer de réception, et ensuite renvoyer ces octets grâce à la fonction _uart0SendDirect (sans passer par un buffer de transmission).
Histoire de faire des test sur base d’exemples simples, j’essaie d’envoyer un seul octet à la fois et je ne tient pas compte du cas ou le buffer de réception est rempli. Grâce à mes leds témoin, je peux constater que la fonction interruption de réception n’est jamais exécutée et que le buffer de réception est donc toujours vide.

#include "sfr_r813.h"
#include "def.h"

#define UART0_RECEIVE_BUFFER_SIZE 32

static BYTE receiveBuffer[UART0_RECEIVE_BUFFER_SIZE]; // Buffer de reception
static BYTE receiveBufferIn; // Index pour le buffer tournant, octet recu
static BYTE receiveBufferOut; // Index pour le buffer tournant, octet lu

// Interruption de réception

#pragma interrupt uart0ReceiveInt;
void uart0ReceiveInt ( void )
{
receiveBuffer[receiveBufferIn] = u0rbl;
re_u1c1 = 1; //Réception terminée -> reception enabled
p1_3 = 1; //Led témoin
receiveBufferIn++;
}

// Initialisation de l'uart

void UART0_init(void)
{
pd1 = pd1 | 0x10; // TxD0 en output
pd1 = pd1 & 0xdf; // RxD0 en input

u0mr = 0x05; // UART0 en mode transfert 8 bits de longueur
u0c0 = 0x00; // UART0 en transmission et réception
u0rrm = 1; // réception continue activée
u0brg = 130-1; // 9600 baud avec l'horloge 20MHz
u0c1 = 0x05;
p1_0 = 1;
}

// Envoi d'un octet sans passer par le buffer

BYTE _uart0SendDirect ( BYTE value )
{
while (ti_u0c1 == 0); // Attend que le buffer de transmission soit vide
u0tb = value;
te_u0c1 = 1; // Transmission terminée
}

// Lecture des octets reçus

BYTE _uart0Receive( BYTE* value )
{
if ( receiveBufferIn != receiveBufferOut ) //Il y a qqch qui est arrivé dans le buffer
{
*value = receiveBuffer[receiveBufferOut];
receiveBufferOut++;
p1_1 = 1; //Led témoin
return( TRUE );
}
return( FALSE );
}

int main ( void )
{
//Change on-chip oscillator clock to Main clock
prc0 = 1;
cm13 = 1;
cm15 = 1;
cm05 = 0;
cm16 = 0;
cm17 = 0;
cm06 = 0;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
ocd2 = 0;
prc0 = 0;
s0ric = 0x07; //UART0 interrupt reception priority level = 7
pd1 = 0x0f; //Output mode for pin P1_0 to P1_3
p1 = 0x00;
UART0_init();
receiveBufferIn = receiveBufferOut = 0;
while ( 1 )
{
BYTE c;
if ( _uart0Receive( &c ) == TRUE )
{
p1_2=1;
_uart0SendDirect( c );
}
}
}
scorpion
 
Posts: 9
Joined: Fri Jan 17, 2014 4:37 pm

Postby nlc » Wed May 30, 2007 12:00 am

Salut Scorpion

Dans le code que tu donnes, les interruptions générales ne semblent pas etre activées.
Il faut faire un asm( "fset I" ); pour les activer

C'est peut etre simplement ca le probleme.

Ensuite, je mettrais u0rrm a 0, c'est comme ca chez moi et ca marche tres bien.

Et enfin, dans uart0ReceiveInt() et _uart0Receive(), au moment d'incrementer les index receiveBufferIn et receiveBufferOut, tu oublies de faire le masque avec (UART0_RECEIVE_BUFFER_SIZE-1) pour remettre a 0 l'index quand on arrive au bout du buffer. Si l'on omet ce masque, apres reception de 32 octets, il risque d'y avoir de serieux plantages

nlc
 
Posts: 109
Joined: Fri Jan 17, 2014 4:37 pm

Postby nlc » Wed May 30, 2007 12:00 am

Autre chose, je pense pas que ca genera, mais dans _uart0SendDirect() il ne faut pas faire de "te_u0c1 = 1"
nlc
 
Posts: 109
Joined: Fri Jan 17, 2014 4:37 pm

Postby nlc » Wed May 30, 2007 12:00 am

Encore une derniere chose : as tu correctement configuré les vecteurs d'interruptions ?

nlc
 
Posts: 109
Joined: Fri Jan 17, 2014 4:37 pm

Postby scorpion » Wed May 30, 2007 12:00 am

Mmmh voilà une question intéressante...
Comment fais-tu pour les configurer ?
Je pense qu'il y a une partie que je n'ai pas du bien saisir...
scorpion
 
Posts: 9
Joined: Fri Jan 17, 2014 4:37 pm

Postby nlc » Wed May 30, 2007 12:00 am

Ben en fait, le microcontroleur n'est pas devin. Il faut bien lui indiquer quelque part que quand une interruption reception arrive, il doit appeler la fonction uart0ReceiveInt()

Il y a donc une zone du programme qui contient les vecteurs d'interruptions, qui sont en fait les adresses des fonctions a appeler pour chaque interruption.

Dans ton cas, je ne sais pas ou tu vas pouvoir modifier ca, car je n'utilise pas le meme environnement de developpement que toi. Tu dois avoir dans la liste des fichiers de ton projet un ou deux fichier en assembleur. L'un de ces fichiers doit contenir la table des vecteurs d'interruption.

Il faut alors reperer le vecteur correspondant a l'interruption reception et remplacer le 0 par _uart0ReceiveInt
nlc
 
Posts: 109
Joined: Fri Jan 17, 2014 4:37 pm

Postby ymasquel » Wed May 30, 2007 12:00 am

Bonjour "scorpion",

Tu devrais d'abord relire le chapitre 10 du HARDWARE MANUAL.
Mais pour faire court tu dois définir en global un vecteur pour chaque interruption (les interruptions pour les accès série sont les numéros 17 à 20. Cela se fait dans le fichier include "sect30.inc" sans oublier de préciser l'adresse d'origine de cette table des vecteurs dans le ncrt0.a30 (cette adresse est variable selon les processeurs).
Si tu te débrouilles en allemand il y a un exemple pas mal à : http://www.b-kainka.de/r8c_2.htm (elektor_1.zip)

Amicalement, Yves.
Amicalement,
Yves.
ymasquel
Site Admin
 
Posts: 3392
Joined: Thu Jan 02, 2014 10:44 am
Location: Oise (60)

Postby scorpion » Wed May 30, 2007 12:00 am

Merci pour vos réponses.
Je suis enfin arrivé à activer les interruptions.

Comme l'a dit "YMasquel", il faut définir un vecteur pour chaque interruption dans le fichier "sect30.inc".
Pour faire profiter tout le monde, voici les lignes de code à taper pour activer les interruptions réception et transmission sur l'UART0 (les fonctions d'interruptions de réception et de transmission se noment respectivement uart0ReceiveInt et uart0TransmitInt) :
.glb _uart0TransmitInt
.lword _uart0TransmitInt ; vector 17
.glb _uart0ReceiveInt
.lword _uart0ReceiveInt ; vector 18

Ces 2 lignes de code sont à écrire à la place des lignes originales
.lword dummy_int ; vector 17
.lword dummy_int ; vector 18

dans la deuxième section relative à "Variable Vector Section" (pas celle avec le .if M60TYPE == 1).

Si on veut activer les interruptions de transmission et de réception sur l’UART1, il s’agit des vecteurs 19 et 20 respectivement.

Par ailleurs, nlc, pourrait-tu m’expliquer le principe de la gestion bufferisée de la transmission ?
Tu dis que ça marche exactement pareil pour l'émission, sauf que quand le buffer est vide, on doit envoyer le premier octet et valider l'interruption émission…
Je ne saisi pas tout à fait le principe.

Merci pour ton éclaircissement.
scorpion
 
Posts: 9
Joined: Fri Jan 17, 2014 4:37 pm

Postby nlc » Wed May 30, 2007 12:00 am

C'est vrai que le principe differe un peu.
En fait l'interruption emission se declenche quand l'octet que l'on a placé dans UOTB est parti.

Au demarrage, je n'active pas cette interruption, je ne l'active que quand c'est necessaire.

Du coup, je n'active l'interruption emission que lorsqu'on appelle la fonction _uart0Send si l'interruption n'est pas mise. Si elle n'est pas mise, c'est qu'aucun envoi n'est en cours, donc il faut activer l'interruption, et surtout il faut placer un octet dans U0TB sinon les octets vont s'empiler dans le buffer mais ne partiront jamais.

Il faut en quelque sorte envoyer manuellement le 1er octet, et les suivant seront automatiquement gérés par la fonction d'interuption dont le travail est le suivant :

S'il reste au moins un octet dans le buffer, je l'envoie. Et si le buffer est vide, je desactive l'interruption.

Désolé, je suis mauvais pedagogue
Le principe est assez simple a comprendre, mais difficile a expliquer
nlc
 
Posts: 109
Joined: Fri Jan 17, 2014 4:37 pm

Postby miralp » Wed May 30, 2007 12:00 am

il faut placer un octet dans U0TB sinon les octets vont s'empiler dans le buffer mais ne partiront jamais.

Oui, c'est vrai. Moi je fait autrement, je force l'interruption Tx lorsque je veux envoyer mon message:
ir_s1tic =1;
Ainsi il n'y a pas d'octet envoyé de trop.
miralp
 
Posts: 3
Joined: Fri Jan 17, 2014 4:37 pm

PreviousNext

Return to R8C/13 (01-2006)

Who is online

Users browsing this forum: No registered users and 1 guest