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.

Problème avec l'UART

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

Bonjour.

J'essaye de programmer l’UART0 mais j’ai certainement un problème au niveau de l’initialisation.
J’aimerais simplement réceptionner une information (via une saisie clavier dans le terminal) et la renvoyer ensuite (affichage de cette information sur le terminal).
La connexion fonctionne et il me renvoie bien une information mais qui est différente que celle envoyée initialement.
En entrant : "abcdefghijklmnop" il me renvoie : "|rsfgfgnoz{nono~".
Je ne vois pas trop où pourrait se trouver le problème si ce n’est dans l’initialisation.
Cela ne fait que quelques jours que je joue avec le R8C/13. Je n’ai donc pas encore saisi toutes ses finesses.

Voici mon code :

void UART0_init(void)
{
pd1 = pd1 | 0x10; // TxD0 en output
pd1 = pd1 & 0xdf; // RxD0 en input
p1= p1 | 0x10; // sélection des E/S. Txd0 sur p1_4 et Rxd0 sur p1_5

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

void sendTxd0(unsigned char data)
{
while (ti_u0c1 == 0); // Attend que le buffer de transmission soit vide
u0tb = data; // Envoie la donnée
te_u0c1 = 1; // Transmission terminée
}

unsigned char receiveRxd0 (void)
{
unsigned char data;
unsigned char dummy;
while (ir_s0ric == 0); // Attend la réception d'une donnée
ir_s0ric = 0; // réception flag à 0
data = u0rbl; // Place la réception dans data
dummy = u0rbh; // si erreur
re_u0c1 = 1; // Réception terminée

return data;
}


void main(void){

unsigned char data;

/*-- Change on-chip oscillator clock to Main clock --*/

asm("FCLR I");
prc0 = 1; /* Protect off */
cm13 = 1; /* Xin Xout */
cm15 = 1; /* XCIN-XCOUT acity */
cm05 = 0; /* Xin on */
cm16 = 0; /* Main clock = No division mode */
cm17 = 0;
cm06 = 0; /* CM16 and CM17 enable */
asm("nop"); /* Waiting for stable of oscillation */
asm("nop");
asm("nop");
asm("nop");
ocd2 = 0; /* Main clock change */
prc0 = 0;

pd1 = 0xff; //Met tous les bits du port 1 à 1 (output)
UART0_init(); //Lance la fonction d'initialisation de l'UART1.


while (1){
data=receiveRxd0();
sendTxd0(data);
}
}

Quelqu’un pourrait m’éclairer ?

Merci d’avance pour votre aide
Attachments
fr_1727405362571.jpg
fr_1727405362571.jpg (92.23 KiB) Viewed 1214 times
scorpion
 
Posts: 9
Joined: Fri Jan 17, 2014 4:37 pm

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

Je n'ai pas regardé ton code, mais depuis le debut de la semaine je fais joujou avec une carte d'evaluation R8C/17, et aujourd'hui j'ai justement mis en route l'uart0.
Voici mes sources, attention, ca va paraitre compliqué car l'emission et la reception sont buffeurisés.

Fichier uart0.c :


#include "ior8c17.h"
#include "def.h"


// Definition de la frequence de l'horloge

#define FREQ 20000000

// Definition de la taille des buffers, attention, doivent etre multiple de ^2,
// soit 2 4 8 16 32 64 128 ou 256

#define UART0_RECEIVE_BUFFER_SIZE 32
#define UART0_SEND_BUFFER_SIZE 32

// Definition de la priorité des interruption emission et reception

#define TX_INTERRUPT_PRIORITY 1 // Interruption d'emission peu prioritaire
#define RX_INTERRUPT_PRIORITY 7 // Interruption de reception tres prioritaire

// Calcul de la base du baud rate

#define BAUD_BASE FREQ/16

// Definition des variables des buffers
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
static BYTE sendBuffer[UART0_SEND_BUFFER_SIZE]; // Buffer d'emission
static BYTE sendBufferIn; // Index pour le buffer tournant, octet envoyé
static BYTE sendBufferOut; // Index pour le buffer tournant, octet parti



// Interruption de reception

__attribute__((interrupt))
void uart0ReceiveInt ( void )
{
// On stocke l'octet dans le buffer
// A revoir pour tester d'eventuelles erreurs dans la transmission
receiveBuffer[receiveBufferIn] = (BYTE)U0RB.word;

// On avance dans le buffer
receiveBufferIn++;
receiveBufferIn &= UART0_RECEIVE_BUFFER_SIZE-1;
}



// Interruption d'emission

__attribute__((interrupt))
void uart0TransmitInt ( void )
{
// S'il n'y a plus rien a envoyer, on devalide les IRQ transmit-end interrupts
if ( sendBufferOut == sendBufferIn )
{ S0TIC.byte = 0;
}
else
{ // Sinon on envoie le prochain octet
U0TB.byte.U0TBL = sendBuffer[sendBufferOut++];
sendBufferOut &= (UART0_SEND_BUFFER_SIZE-1);
}
}






// Calcul du diviseur

static int getBRG ( long baudRate, long prescaler )
{
int brg = 0;
long baudBase = BAUD_BASE;

// Si on a un presacler de 8 ou 32, on divise le baud base par 8 ou 32
if ( prescaler == 8 ) baudBase >>= 3;
if ( prescaler == 32 ) baudBase >>= 5;

// On compte le nombre de fois ou le baudrate rentre dans le baud base (evite une division)
while ( (baudBase-=baudRate) >= 0 )
{ brg++;
}

// On regarde si on doit arrondir au dessus notre resultat
if ( baudBase+(baudRate>>1) >= 0 )
brg++;

// On retire 1, comme specifié dans la doc
brg--;

return( brg );
}







// Initialisation de l'uart

BYTE _uart0Init ( long speed, char parity, int data, int stopbits )
{
int temp;

// Config du registre U0MR

temp = 0;

switch( data )
{ case 7 : temp += BIT2; break; // Mode 7 bits
case 9 : temp += BIT2+BIT1; break; // Mode 9 bits
case 8 :
default: temp += BIT2+BIT0; break; // Mode 8 bits par defaut
}

if ( stopbits == 2 ) temp += BIT4;

switch( parity )
{ case 'E' : temp += BIT6+BIT5; break; // Parité impaire
case 'O' : temp += BIT6; break; // Parité paire
}

U0MR.byte = (BYTE)temp;

// Config du registre U0CO et du registre U0BRG

U0C0.byte = 0; // Sortie CMOS, pas de prescaler

if ( (temp=getBRG( speed, 0 )) > 255 )
{ U0C0.byte = BIT0; // Sortie CMOS, prescaler de 8
if ( (temp=getBRG( speed, 8 )) > 255 )
{ U0C0.byte = BIT1; // Sortie CMOS, prescaler de 32
temp=getBRG( speed, 32 );
}
}

U0BRG = (BYTE)temp;

// Config du registre U0C1

U0C1.byte = 0x05; // On active l'emission et la reception

// Config du registre UCON

UCON.byte = 0x00;

// Initialisation des index d'emission/reception

receiveBufferIn = receiveBufferOut = 0;
sendBufferIn = sendBufferOut = 0;

// On active les interruptions reception

S0RIC.byte = RX_INTERRUPT_PRIORITY;

// On passe la broche Tx en sortie

P1.bit.P1_4 = 1; // Tx a 1
PD1.bit.PD1_4 = 1; // Tx en sortie

return( TRUE );
}





// Envoi d'un octet, gestion bufferisée

BYTE _uart0Send( unsigned char value )
{
// Si le buffer est plein, pas la peine de continuer
if ( ((sendBufferIn+1) & (UART0_SEND_BUFFER_SIZE-1) ) == sendBufferOut )
return( FALSE );

// On place l'octet dans le buffer
sendBuffer[sendBufferIn] = value;
sendBufferIn++;
sendBufferIn &= (UART0_SEND_BUFFER_SIZE-1);

// Si l'interruption transmission n'est pas validée, on envoie un octet et on la valide
if ( (S0TIC.byte&0x07) == 0 )
{ U0TB.byte.U0TBL = sendBuffer[sendBufferOut++];
sendBufferOut &= (UART0_SEND_BUFFER_SIZE-1);
S0TIC.byte = TX_INTERRUPT_PRIORITY;
}

return( TRUE );
}




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

BYTE _uart0SendDirect ( BYTE value )
{ if ( U0C1.bit.TI )
{ U0TB.byte.U0TBL = value;
return( TRUE );
}
return( FALSE );
}









// Lecture des octets recu

BYTE _uart0Receive( BYTE* value )
{ if ( receiveBufferIn != receiveBufferOut )
{ *value = receiveBuffer[receiveBufferOut];
receiveBufferOut++;
receiveBufferOut &= (UART0_RECEIVE_BUFFER_SIZE-1);
return( TRUE );
}
return( FALSE );
}







// On vide les buffers d'emission et reception

void _uart0Emptying( void )
{ receiveBufferIn = receiveBufferOut = 0;
sendBufferIn = sendBufferOut = 0;
}



Fichier main.c d'exemple :

int main ( void )
{
_uart0Init ( 9600, 'N', 8, 1 );

while ( 1 )
{ BYTE c;
if ( _uart0Receive( &c ) == TRUE )
_uart0Send( c );
}

return 0;
}



Note :
Je travaille sous linux et j'utilise le compilateur GCC pour M16, c'est pour ca que les nom de registres vous paraitront aussi un peu bizarre. Il faut les modifier a votre sauce pour que ca compile. Il ne faut pas oublier aussi de configurer les vecteurs d'IT relatifs a l'uart 0 !!

Du fait que tout est bufferisé, lorsqu'on envoie une trame par exemple, ce n'est pas bloquant et on a la main de suite pour faire autre chose.
nlc
 
Posts: 109
Joined: Fri Jan 17, 2014 4:37 pm

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

Bonjour "scorpion",

Je n'ai pas non plus regardé ton code. Les symptômes que tu signales sont caractéristiques d'une mauvaise synchronisation (débits non adaptés) entre les systèmes en présence. J'ai jeté un oeil sur l'initialisation et j'y ai vu que tu avais paramétré le débit à 38400 bauds au niveau du R8C13. En faisant défiler ton post je suis arrivé à la fenêtre du terminal sous windows où le paramétrage est à 9600 bauds.
Cela confirme les soupçons si effectivement le paramétrage dans le R8C13 correspond bien à 38400 bauds ce que je te laisse vérifier.

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

Génial. Problème résolu.
Effectivement je n'avais fait attention au paramétrage de la vitesse du port série.
Merci pour ton aide.
scorpion
 
Posts: 9
Joined: Fri Jan 17, 2014 4:37 pm

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

Bonjour "scorpion",

Voilà l'exemple même d'une bonne utilisation du forum :
- tu as fourni TOUS les éléments qui permettent la découverte rapide d'une anomalie.
- grâce à ces informations il est facile à celui qui n'a pas la tête dans le guidon de son projet de voir ce qui pose problème.

Un problème bien posé est un problème presque résolu (il y avait longtemps que je n'avais pas philosophé).

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


Return to R8C/13 (01-2006)

Who is online

Users browsing this forum: No registered users and 1 guest