SDCC: Driver para Usart PIC16*
3 participantes
Página 1 de 1.
SDCC: Driver para Usart PIC16*
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...
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...
- 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;
}
arcachofo- Participante Activo
- Mensajes : 91
Fecha de inscripción : 26/11/2008
Problema con librería USART
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:
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
Desde ya, mil gracias! Esperamos poder compartir el código una vez finalizado.
- 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
Desde ya, mil gracias! Esperamos poder compartir el código una vez finalizado.
fclad- Nuevo Usuario
- Mensajes : 6
Fecha de inscripción : 11/10/2010
Re: SDCC: Driver para Usart PIC16*
Hola...
Puedes probar con esto..
modifica la libreria serial16f en donde se declara el registro para el registro SPBRG
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.
Esto lo probé y efectivamente transmite la letra K. voy a ver porque el codigo
Saludos RiSanti
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ó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
Saludos RiSanti
Hasta que lo tocó la mano de Risanti...
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
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!
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
- 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
- Mensajes : 6
Fecha de inscripción : 11/10/2010
Re: SDCC: Driver para Usart PIC16*
Holaa.
Me Alegro que te haya servido la información.. Cualquier novedad que tengas no dudes
en publicar algún mensaje..
Saludos
RiSanti
Me Alegro que te haya servido la información.. Cualquier novedad que tengas no dudes
en publicar algún mensaje..
Saludos
RiSanti
Ya va quedando...
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:
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!
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;
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
- Mensajes : 6
Fecha de inscripción : 11/10/2010
Re: SDCC: Driver para Usart PIC16*
Holaaaa..
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
# 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
Temas similares
» SDCC: Driver para LCD. PIC16F*
» SDCC: Driver para ADC PIC16f87x.
» Comenzar a trabajar con SDCC y pic 14 bits (PIC12, PIC16).
» ADC para PIC16F*, driver y ejemplo.
» LCD 44780 4-bits para PIC16F, driver y ejemplo.
» SDCC: Driver para ADC PIC16f87x.
» Comenzar a trabajar con SDCC y pic 14 bits (PIC12, PIC16).
» ADC para PIC16F*, driver y ejemplo.
» LCD 44780 4-bits para PIC16F, driver y ejemplo.
Página 1 de 1.
Permisos de este foro:
No puedes responder a temas en este foro.