SDCC: Driver para Usart PIC16*

Ver el tema anterior Ver el tema siguiente Ir abajo

SDCC: Driver para Usart PIC16*

Mensaje por arcachofo el Mar 2 Dic 2008 - 7:59

Partiendo del material de P.Launay: http://per.launay.free.fr/dokuwiki-2008-05-05/doku.php
he comenzado ha mejorar en la medida de lo posible el driver Usart que se encuentra en su página, basicamente el código es el mismo, lo he "limpiado" un poco, dejando los comentarios que me parecieron oportunos en español y le he añadido algunas lineas para que funcione a cualquier velocidad de oscilador y pines Rx y Tx de distintos PICs.

Cualquier idea, mejora, error que veais, etc exponedlo aquí para ir mejorando esto hasta tener un driver funcional.

este es el archivo para descargar: serie16F.h

y aquí se puede ver el código... aunque la verdad es que verse se ve poco... Smile


Código:


/*****************************************************************************
******************************************************************************
****                                                                      ****
****            --- DRIVER USART asincrono  para PIC16* ---              ****
****                                                                      ****
******************************************************************************
*****************************************************************************/

// This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


/*********************************************************************************
**********************************************************************************


        EN EL PROGRAMA PRINCIPAL DONDE VAYA A USAR LAS FUNCIONES USART
INSERTAR LAS SIGUIENTES LINEAS CON LAS DEFINICIONES DE PUERTO Y RELOJ USADOS:

//---------------------------- PUERTO SERIE ------------------------------
//------------------------------------------------------------------------

#define Br 9600                //Baudrate, ajustar a velocidad deseada
#define Rx TRISC7            //Pin RX
#define Tx TRISC6            //Pin TX

#include "serie_16F.h"

#define FREQ 8000            // 8000 KHz = 8 Mhz, LA FRECUENCIA EN KHz.


**********************************************************************************
*********************************************************************************/



#define x (FREQ * 1000 / Br - 16) / 16    // calculo para SPBRG
#define Te 1000                // Tiempo de espera al recibir en


//----------------------------- FUNCIONES --------------------------------
//------------------------------------------------------------------------

void init_serie(void);
void putchar(char);
void puthex(char);
void puth(char);
void putint(int);
void print(char*);
char getchar(void);
char espera_car(void);
char lee_car(void);

//--------------------------- INICIALIZACION -----------------------------
//------------------------------------------------------------------------

void init_serie(void)            // Configurado para: 8 bits asincrono
{   
    SPBRG = x;            // SPBRG - Registro Baud Rate Generator (BRGH = 1)
    BRGH = 1;            // (1 = high speed)
    SYNC = 0;            // Asincrono
    Rx = 1;                // Pin RX como entrada
    Tx = 0;                // Pin Tx como salida
    SPEN = 1;            // Puerto serie habilitado
    TXIE = 0;            // Interruption transmision USART deshabilitada
    RCIE = 0;            // Interruption recepcion USART deshabilitada
    TX9 = 0;            // 0 = modo transmisión 8-bit
    RX9 = 0;            // 0 = modo recepción 8-bit
    CREN = 1;            // Recepcion continua habilitada
    TXEN = 1;            // transmision habilitada
}

//---------------------------- TRANSMISION -------------------------------
//------------------------------------------------------------------------

void putchar(char c)            // Enviar un caracter
{
    while(!TXIF);            // espera mientras TXIF=0
    TXREG = c;            // Poner char en TXREG
}
 
void print(char *t)            // Enviar una cadena (terminar texto en /0)
{
    while (*t)
    {
            putchar(*t);       
        t++;
    }
}

void puth(char a)            // Transformar nibble en caracter ASCII           
{
    if (a > 9)
        a += 55;
    else
        a += 48;
    putchar(a);
}

void puthex(char nb)            // Transformar un octeto en 2 nibbles
{
    char n;
    n=(nb >> 4) & 0x0f;
    puth( n );
    n = nb & 0x0f;
    puth(n);
}

void putint(int num)            // Transformar int (16 bits) en dos octetos
{
    puthex(num >> 8);
    puthex(num & 0xff);   
}

//----------------------------- RECEPCION --------------------------------
//------------------------------------------------------------------------


char lee_car(void)            // lee un caracter de RCREG
{               
    if (OERR)            // Si error
    {           
        CREN = 0;        // Reactiva CREN
        CREN = 1;   
    }
    if (RCIF)            // Si flag RCIF activado = hay un caracter
        return RCREG;        // la funcion Devuelve RCREG
    else   
        return 0;
}

char getchar(void)
{
    char a = 0;
    while (a == 0)            // hasta que exista a =  reciba un caracter
        a = lee_car();   
    return a;
}

char espera_car(void)            // variante de getchar espera "Te" ciclos
{               
    int compt = 0;
    char a = 0;
    while ( (!a) && (compt != Te) )    // Si se sobrepasa "Te" devuelve 0
    {           
        compt++;
        a = lee_car();
    }
    return a;
}

char geth(void)               
{   
    char hex;
    hex = getchar();
    if ( (hex > 0x29) && (hex < 0x3a) ) 
        hex = hex & 0x0f;
    else
    {
        if (( (hex > 0x40) && (hex < 0x47) ) || ( (hex > 0x60) && (hex < 0x67) ))
            hex = (hex + 0x09) & 0x0f;
        else
            hex = 0xff;
    }
    return hex;
}

char gethex(void)           
{
    char hex;
    hex = geth() << 4;
    hex |= geth();
    return hex;

 
char getd(void)
{   
    char dec;
    dec = getchar();
    if ( (dec > 0x29) && (dec < 0x3a) ) 
        dec &= 0x0f;
    else 
        dec = 0xff;
    return dec;
}



avatar
arcachofo
Participante Activo
Participante Activo

Mensajes : 91
Fecha de inscripción : 26/11/2008

Volver arriba Ir abajo

Problema con librería USART

Mensaje por fclad el Lun 11 Oct 2010 - 21:50

Buenas! La verdad es que esta página es un lujo. Somos estudiantes, y estamos haciendo un control de un motor paso a paso mediante el pic 16F628. Ahora bien, necesitamos comunicación serie mediante el usart, y no conseguimos hacerla funcionar. He aquí el código de prueba, sólo debería transmitir "K" por el serie:


Código:

#include <pic16f628a.h>
#define FREQ 4000            // 4000 KHz = 4 Mhz, LA FRECUENCIA EN KHz.
#define Br 9600                //Baudrate, ajustar a velocidad deseada
#define Tx RB2
#define Rx RB1

#include "delay.h"
#include "serie16F.h"


typedef unsigned int word;
word at 0x2007 CONFIG = _WDT_OFF & _PWRTE_OFF & _INTOSC_OSC_NOCLKOUT & _MCLRE_OFF & _BODEN_OFF & _LVP_OFF & _DATA_CP_OFF & _CP_OFF;




void main(){
while(1){

putchar(0x4B);
delay_ms(500);

}

Hemos probado el código en Proteus Isis, y en nuestro pic (conectándolo mediante un integrado 40106), y no funciona. Es válida esta librería para el 16F628?
En la compilación, observamos el siguiente error
serie16F.h:71: warning 165: integer overflow in expression ?

que corresponde a la línea
Código:

#define x (FREQ * 1000 / Br - 16) / 16    // calculo para SPBRG
de la librería. Hay problema con esto?

Desde ya, mil gracias! Esperamos poder compartir el código una vez finalizado.

fclad
Nuevo Usuario
Nuevo Usuario

Mensajes : 6
Fecha de inscripción : 11/10/2010

Volver arriba Ir abajo

Re: SDCC: Driver para Usart PIC16*

Mensaje por Risanti el Mar 12 Oct 2010 - 20:45

Hola...

Puedes probar con esto..

modifica la libreria serial16f en donde se declara el registro para el registro SPBRG
Código:


#define x (FREQ * 1000 / Br - 16) / 16    // calculo para SPBRG
cámbialo por
Código:


#define x  25

Ademas en tu codigo hay algunos errores :

Debes declarar los pines a usar, usando el resgistro TRIS en tu caso TRISB1 yTRISB2, ya que la libreria te lo pide asi. ademas debes iniciar el USART usando la funcion init_serie(), y por ultimo te falta un { para el bluce while.. ademas te aconsejo que revises los fuse de configuracion para el pic16f628A, yo seleccione usar cristal Xt.


Código:


#include <pic16f628a.h>
#define FREQ 4000            // 4000 KHz = 4 Mhz, LA FRECUENCIA EN KHz.
#define Br 9600                //Baudrate, ajustar a velocidad deseada
#define Tx TRISB2
#define Rx TRISB1

#include <delay.h>
#include <serie16F.h>


typedef unsigned int word;
word at 0x2007 CONFIG = _WDT_OFF & _PWRTE_OFF & _XT_OSC & _MCLRE_ON & _BODEN_ON & _LVP_ON & _DATA_CP_OFF & _CP_OFF;




void main(){

init_serie();
while(1){
putchar(0x4B);    // Puede ser escrito asi, es mas facil    putchar('K');
delay_ms(500);
}

}

Esto lo probé y efectivamente transmite la letra K. voy a ver porque el codigo
Código:


#define x (FREQ * 1000 / Br - 16) / 16    // calculo para SPBRG
no funciona bien...

Saludos RiSanti
avatar
Risanti
Asiduo del Foro
Asiduo del Foro

Mensajes : 172
Fecha de inscripción : 07/12/2008
Edad : 32
Localización : La Serena Chile

http://www.facebook.com/risanti.electronica

Volver arriba Ir abajo

Hasta que lo tocó la mano de Risanti...

Mensaje por fclad el Miér 13 Oct 2010 - 2:36

La verdad amigo, te has pasado! El código funciona de maravillas.
Esos pequeños errores se debieron a que estuve probando tu código de comunicación serie por software, y ahí utilizaba
Código:

#define Tx_pin RB2                             
#define Rx_pin RB3
además el } me olvidé de copiarlo! El código, en principio, compilaba bien pero no funcionaba. Los dos errores fueron:

  • No haber iniciado el usart
  • No Utilizar #define x 25 en la librería.

Corrigiendo esto, ha funcionado sin más vueltas. Esperamos tener el proyecto pronto por aquí. Somos estudiantes de Ingeniería en Mecatrónica, y notamos difícil utilizar herramientas libres cuando siempre se utiliza software privativo sobre windows. Tu ayuda ha sido un gran impulso para que sigamos trabajando con estas herramientas! Muchas gracias!

fclad
Nuevo Usuario
Nuevo Usuario

Mensajes : 6
Fecha de inscripción : 11/10/2010

Volver arriba Ir abajo

Re: SDCC: Driver para Usart PIC16*

Mensaje por Risanti el Dom 17 Oct 2010 - 3:10

Holaa.
Me Alegro que te haya servido la información.. Cualquier novedad que tengas no dudes
en publicar algún mensaje..

Saludos
RiSanti
avatar
Risanti
Asiduo del Foro
Asiduo del Foro

Mensajes : 172
Fecha de inscripción : 07/12/2008
Edad : 32
Localización : La Serena Chile

http://www.facebook.com/risanti.electronica

Volver arriba Ir abajo

Ya va quedando...

Mensaje por fclad el Sáb 23 Oct 2010 - 2:36

Va quedando ya nuestro proyecto! Falta limar algunas cositas...
La pregunta ahora tiene que ver con la función putint. En nuestro PaP, se recibe con getd el número de paso deseado, que se almacena en una variable int (puede ir de 1 a 999). Ahora bien, cuando deseamos imprimirla con putint, nos imprime el hexadecimal...
Es decir, si paso = 500, por la terminal, haciendo putint(paso) nos devuelve 1F4.

He pensado dos posibles soluciones:

  • Utilizar este itoa.c que encontré por ahí para pasar el int del número de paso a un char*. No funciona, en proteus me devuelve un stack overflow. Adjunto el código de ejemplo (pasa a a texto), que compila pero no funciona...
    Código:
    /* ----------------------------------------------------------------------- */
    /* Plantilla generada por Piklab */

    #include <pic16f628.h>
    #define FREQ 4000            // 4000 KHz = 4 Mhz, LA FRECUENCIA EN KHz.
    #define Br 9600                //Baudrate, ajustar a velocidad deseada
    #define Tx TRISB2
    #define Rx TRISB1

    #include <delay.h>
    #include <serie16F.h>

    /* ----------------------------------------------------------------------- */
    /* Bits de configuración: adapte los parámetros a su necesidad */
    typedef unsigned int word;
    word at 0x2007 CONFIG = _WDT_OFF & _PWRTE_ON & _XT_OSC & _MCLRE_ON & _BODEN_ON & _LVP_OFF & _DATA_CP_OFF & _CP_OFF;



    /*-------------------------------------------------------------------------
     integer to string conversion

     Written by:  Bela Torok, 1999
                  bela.torok@kssg.ch
     usage:

     uitoa(unsigned int value, char* string, int radix)
     itoa(int value, char* string, int radix)

     value  ->  Number to be converted
     string ->  Result
     radix  ->  Base of value (e.g.: 2 for binary, 10 for decimal, 16 for hex)
    ---------------------------------------------------------------------------*/

    #define NUMBER_OF_DIGITS 16  /* space for NUMBER_OF_DIGITS + '\0' */

    void uitoa(unsigned int value, char* string, int radix)
    {
    unsigned char index, i;

      index = NUMBER_OF_DIGITS;
      i = 0;

      do {
        string[--index] = '0' + (value % radix);
        if ( string[index] > '9') string[index] += 'A' - ':';  /* continue with A, B,.. */
        value /= radix;
      } while (value != 0);

      do {
        string[i++] = string[index++];
      } while ( index < NUMBER_OF_DIGITS );

      string[i] = 0; /* string terminator */
    }

    void itoa(int value, char* string, int radix)
    {
      if (value < 0 && radix == 10) {
        *string++ = '-';
        uitoa(-value, string, radix);
      }
      else {
        uitoa(value, string, radix);
      }
    }



    /*main*/

    unsigned int retardo;
    signed int a=237;
    char * texto;
    void main(){

       retardo = 500;
       texto = "nada";
       TRISB = 0x7F;
       init_serie();
       delay_ms(500);
       print("Test!");
       putchar(0x0D);
       itoa(a,texto,10);
       //Bucle infinito
       while(1){
          putchar('K');
          putchar(0x0D);
          delay_ms(retardo);
          
          print(texto);
          putchar(0x0D);
          delay_ms(retardo);
          }
       
    }
  • La otra opción que había pensado era hacer una suerte de conversión del número de paso. Por ejemplo, supongamos que
    Código:

    int a = 230;
    int b;
    a en hexadecimal es E6. La idea es operar sobre b para que devuelva 560 = 0x230. Es decir, buscar el "equivalente" de a en hexadecimal tal que en valor numérico sea igual a a. Luego imprimiría con putint.


La verdad, no se cuál de las dos ideas es menos complicada. ¿Alguien ha hecho funcionar el itoa en el 16f628? ¿Alguna otra idea para el problema?
Muchas gracias!

fclad
Nuevo Usuario
Nuevo Usuario

Mensajes : 6
Fecha de inscripción : 11/10/2010

Volver arriba Ir abajo

Re: SDCC: Driver para Usart PIC16*

Mensaje por Risanti el Lun 25 Oct 2010 - 5:20

Holaaaa..

# Utilizar este itoa.c que encontré por ahí para pasar el int del número de paso a un char*. No funciona, en proteus me devuelve un stack overflow. Adjunto el código de ejemplo (pasa a a texto), que compila pero no funciona...

Este error es cuando desbordas la pila del PIC, el cual tiene solo 8 niveles, puede ser cuando se abusa realizado llamados de funciones, lo malo que sdcc no te avisa que has realizo mas de 8 llamados de funciones.

Deja hacer algunas pruebas con tu codigo, para ver como te puedo ayudar...
Espero responder pronto..
Saludos
RiSanti
avatar
Risanti
Asiduo del Foro
Asiduo del Foro

Mensajes : 172
Fecha de inscripción : 07/12/2008
Edad : 32
Localización : La Serena Chile

http://www.facebook.com/risanti.electronica

Volver arriba Ir abajo

Re: SDCC: Driver para Usart PIC16*

Mensaje por Contenido patrocinado


Contenido patrocinado


Volver arriba Ir abajo

Ver el tema anterior Ver el tema siguiente Volver arriba

- Temas similares

 
Permisos de este foro:
No puedes responder a temas en este foro.