Hola, me llamo Javier. Antetodo quería presentarme a ustedes puesto que soy nuevo en el foro y creo que es la mejor forma de empezar. Necesito de su consejo.
Estoy intentando realizar una recepción de datos utilizando el módulo de comunicaciones UART, con un dsPIC30F4011. Para ello envio los datos a través de una aplicación similar al hyperterminal de windos llamada Terminal. Estoy desarrollando el código en C, utilizando el compliador C30 de Microchip, y mi versión de MPLAB es la 8.20, el dsp se encuentra en la placa de prueba dsPICDEM 2 del fabricante Microchip.
He estado leyendo varios post en este foro sobre el módulo UART y también en otra fuentes, me han ayudado bastante a entender algunos fallos que tenía pero sigo encontrado algún que otro problema y también tengo alguna duda. Así que les agredecería mucho si me pudieran ayudar, les voy a explicar lo mejor posible lo que sucede para no robarles mucho de su valioso tiempo.
Bueno voy a empezar por lo que hace el programa. Como dije antes es una recepción de datos utilizando el módulo de comunicaciones UART, para ello he utilizado la librería UART.h de Microchip, lo que quiero hacer es ir recibiendo los datos e ir almacenandolos en un buffer de cuatro elementos
(más tarde con esos cuatro elementos construiré un único dato, pero eso no está incluido en el programa), una vez se ha completado el buffer se vuelve a puntar al primer elemento de este para volver a utilizarlo. He configurado para que se produzca la interrupción cada vez que se recive un caracter.
Problemas con los que me encuentro:
Cuando estoy haciendo el debug e inicializo el programa el primer caracter que mando no se almacena en el buffer, entra en la interrupción y automáticamente el registro U1RXREG se borra y me almacena un dato vacio en el buffer. Y así sucesivamente hasta que llego al cuarto caracter, el cual si se me almacena en el buffer. La explicación a todo esto que sucede, en mi opinión, es que al irse almacenando los datos en la pila FIFO de recepción (pila de 4 niveles), hasta que un dato no llega al nivel más alto de la pida no es apto para su manipulación.
También he probado configurando la interrupción para que se produzca cuando se completa el buffer, para eso tengo que mandandar los datos de cuatro en cuatro pero sólo me coge el primer elemento de la pila, pues esta al no estar direccionada no puede ser recorrida y por lo tanto no puedo acceder a los otros datos a no ser que lleguen más que hagan que los ya almacenados se desplacen.
Por lo tanto no tengo muy claro el funcionamiento de la pila y la interrupciones, puesto según entiendo yo si configuro para que se me produzca la interrupción cada vez que se recive un dato no tendría porque completar el resto de la pila, esta quedaría como una de un solo nivel, digamoslo así. Y si configuro la interrupción para que sea cuando se me complete el buffer una vez que leo el primer dato debería actualizarse la pila porque sigue teniendo datos en ella y el primer nivel se ha quedado libre.
Otro problema que tengo, es que la comunicación la estoy haciendo utilizando los pines U1ALTRX Y U1ALTTX, y se comunica con los anteriores problemas citados, pero si cambio la comunicacíon para realizarla con los pines normales de la UART, habiendo cambiado la configuración el los registros, es decir, puesto a 0 el bit ALTIO del registro U1MODE, la cominicación se me vuelve loca, no recive nada y de hecho me envia datos extraños, lo cual es raro porque solo estoy haciendo la recepción, aquí estoy más perdido y no he podido llegar a ninguna conclusión, he leído el manual de la placa y la he configurado para cambiar a los pines normales, era sólo cambiar un jumper por otro, así que eso no tiene misterio.
Decir que el programa me compila correctamente, no me genera ni errores ni warnings, que he incluido las librerias del dsPIC libc-coff.a libp30F4011-coff.a, libpic30-coff.a, el correspondiente Linker Script p30f4011.gld, y los header Files p30f4011.h, uart.h, stdlib.h
También he probado a hacerlo mismo sin utilizar la libreria uart.h y el comportamiento es el mismo.
Espero que me puedan hechar un cable porque llevo ya muchos días con esto y ya he agotado todas las ideas.........

pero no la fe

Les dejo el código para que le heche un vistazo, he puesto bastantes comentarios pero si necesitan alguna aclaración no duden en preguntar.
Muchas gracias por su ayuda y valioso tiempo.
//***********************************************************************************
//
// PROGRAMA:
// Obtener datos enviados por computador a traves de comunicacion RS232,
// los datos se estan enviando atraves de una aplicacion software llamada terminal
// similar al hyperterminal de windows, pero con mejores caracteristicas
//
// Entorno de programacion: MPLAB v8.20
// Compilador: C30
// Dispositivo: dsPIC30F4011
// Placa desarrollo: dsPICDEM2
//
//***********************************************************************************
#include <p30f4011.h>
#include <uart.h>
#include <stdlib.h>
//Macros for Configuration Fuse Registers:
//Invoke macros to set up device configuration fuse registers.
//The fuses will select the oscillator source, power-up timers, watch-dog
//timers, BOR characteristics etc. The macros are defined within the device
//header files. The configuration fuse registers reside in Flash memory.
_FOSC(CSW_FSCM_OFF & XT_PLL8); //Run this project using an external crystal
//routed via the PLL in 8x multiplier mode
//For the 7.3728 MHz crystal we will derive a
//throughput of 7.3728e+6*8/4 = 14.74 MIPS(Fcy)
//,~67nanoseconds instruction cycle time(Tcy).
_FWDT(WDT_OFF); //Turn off the Watch-Dog Timer.
_FBORPOR(MCLR_EN & PWRT_OFF); //Enable MCLR reset pin and turn off the
//power-up timers.
_FGS(CODE_PROT_OFF); //Disable Code Protection
//Defines for System Clock Timing -
//For oscillator configuration XT x PLL8 mode,
//Device Throughput in MIPS = Fcy = 7372800*8/4 = ~14.74 MIPS
//Instruction Cycle time = Tcy = 1/(Fcy) = ~68 nanoseconds
#define XTFREQ 7372800 //On-board Crystal frequency
#define PLLMODE 8 //On-chip PLL setting
#define FCY XTFREQ*PLLMODE/4 //Instruction Cycle Frequency
#define BAUDRATE 9600 //Designamos rango de baudios
#define BRGVAL (((FCY/BAUDRATE)/16)-1) //Formula para registro U1BRG, obtenida del manual
//dsPIC30F Family Reference Manual
/*****************
** PROTOTIPOS **
*****************/
void UART_Init (void);
void __attribute__((__interrupt__)) _U1RXInterrupt(void);
int main (void);
/****************
** GLOBALES **
****************/
unsigned char bufferRX[4]; //buffer donde voy almacenar los elementos de la pila
unsigned char *Ptro_bufferRX=NULL; //inicializacion del buffer
unsigned char index=0; //contador que me indica las veces que se ha leido un dato
/*****************
** FUNCIONES **
*****************/
void UART_Init (void)
{
unsigned int U1MODEvalue;
unsigned int U1STAvalue;
CloseUART1(); //Turn off UART1module
//Configuramos interrupciones de UART1, recepcion
ConfigIntUART1(UART_TX_INT_DIS & UART_RX_INT_EN & UART_RX_INT_PR7);
//configuramos los registros UMODE y USTA
U1MODEvalue= UART_EN & UART_IDLE_CON & UART_DIS_WAKE & UART_DIS_ABAUD & UART_ALTRX_ALTTX &
UART_DIS_LOOPBACK & UART_ODD_PAR_8BIT & UART_1STOPBIT;
U1STAvalue= UART_INT_TX & UART_INT_TX_BUF_EMPTY & UART_TX_PIN_NORMAL & UART_TX_DISABLE &
UART_INT_RX_CHAR & UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR;
OpenUART1(U1MODEvalue, U1STAvalue, BRGVAL); //activamnos el uart con la configuracion seleccionada
Ptro_bufferRX= &bufferRX[0]; //el puntero apunta al primer elemento del buffer
}
/*********************
** Interrupciones **
*********************/
// This is UART1 receive ISR
void __attribute__((__interrupt__,no_auto_psv)) _U1RXInterrupt(void)
{
IFS0bits.U1RXIF = 0; //borramos flag de interrupcion
if((U1STAbits.PERR==0) && (U1STAbits.FERR==0)) //compruebo errores
{
(*(Ptro_bufferRX)++)=U1RXREG;
}
if(U1STAbits.OERR) U1STAbits.OERR=0; //si hay error de overflow es borrado
}
/***********
** main **
***********/
int main (void)
{
UART_Init(); //iniciamos las configuracion de UART
while(1) //bucle infinito, loop main
{
if(index==4) //se acede cuando se han leido cuatro bytes
{
Ptro_bufferRX= &bufferRX[0]; //vuelvo apuntar al primer elemento del buffer
index=0; //inicializo contador
}
}
CloseUART1(); //si por alguan circunstacia se abandona loop main se cierra el dispostivo UART
return 0;
}
//main