Autor Tema: Regresar valor en interrupción del uart  (Leído 4881 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado IngRandall

  • PIC18
  • ****
  • Mensajes: 383
Regresar valor en interrupción del uart
« en: 08 de Septiembre de 2012, 11:05:17 »
Hola, vengo de nuevo a ustedes con otro problema mas  :( :( :( :(

Esta vez es con el uart del pic 32... cuando ocurre una interrupción cambio el valor de una variable que es global pero cuando regresa al main principal no ve el cambio, parece que no lo cambiara o que no saliera de la interrupción...

Este es mi main:
Código: [Seleccionar]
    init_port();

    LED_ON_OFF = 1;

    secuencia   =       1;
    p           =       10;

    while(1){
        if(secuencia==1){
            PutCharacter_U2(secuencia);
            WriteString_U2("*** Hola!!! ***\r\n");
            secuencia   =       0;
        }
    }

Sencillo... este es la inicializacion del puerto:
Código: [Seleccionar]
void configuracion_uart2()
{
    UARTConfigure(UART2, UART_ENABLE_PINS_TX_RX_ONLY);
    UARTSetFifoMode(UART2, UART_INTERRUPT_ON_TX_NOT_FULL | UART_INTERRUPT_ON_RX_NOT_EMPTY);
    UARTSetLineControl(UART2, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
    UARTSetDataRate(UART2, GetPeripheralClock(), DESIRED_BAUDRATE);
    UARTEnable(UART2, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));

// Configure UART2 RX Interrupt
    INTEnable(INT_SOURCE_UART_RX(UART2), INT_ENABLED);
    INTSetVectorPriority(INT_VECTOR_UART(UART2), INT_PRIORITY_LEVEL_7);
    INTSetVectorSubPriority(INT_VECTOR_UART(UART2), INT_SUB_PRIORITY_LEVEL_0);
}

Y esta es la interrupción:
Código: [Seleccionar]
void __ISR(_UART2_VECTOR, ipl7) IntUart2Handler(void)
{
LED_Rx_U2 = 1;

// Is this an RX interrupt?
if(INTGetFlag(INT_SOURCE_UART_RX(UART2)))
{
            // Clear the RX interrupt Flag
    INTClearFlag(INT_SOURCE_UART_RX(UART2));

            buffer[x]=UARTGetDataByte(UART2);


            if(buffer[x]=='1'){
               
                p           =       10;

                while(p){
                    LED_Tx_U1 = 1;
                    LED_Rx_U1 = 0;
                    LED_Tx_U2 = 0;
                    LED_Rx_U2 = 0;
                    DelayMs(50);
                    LED_Tx_U1 = 0;
                    LED_Rx_U1 = 1;
                    LED_Tx_U2 = 0;
                    LED_Rx_U2 = 0;
                    DelayMs(50);
                    LED_Tx_U1 = 0;
                    LED_Rx_U1 = 0;
                    LED_Tx_U2 = 1;
                    LED_Rx_U2 = 0;
                    DelayMs(50);
                    LED_Tx_U1 = 0;
                    LED_Rx_U1 = 0;
                    LED_Tx_U2 = 0;
                    LED_Rx_U2 = 1;
                    DelayMs(50);

                    p--;
                }

                LED_Tx_U1 = 0;
                LED_Rx_U1 = 0;
                LED_Tx_U2 = 0;
                LED_Rx_U2 = 0;

            }


//            if(buffer[x]=='1'){secuencia=1;}

            // Echo what we just received.
//            PutCharacter_U2(buffer[x]);

            x++;
}

// We don't care about TX interrupt
if ( INTGetFlag(INT_SOURCE_UART_TX(UART2)) )
{
INTClearFlag(INT_SOURCE_UART_TX(UART2));
}

LED_Rx_U2 = 0;

        secuencia=1;
}

Todo esta sencillo... pero yo cambio el valor de la variable secuencia pero esta cuando regresa al main principal parece que no cambiara o que no regresara por que no entra en el if :( :( :( :( :( :( :( :(

Desconectado IngRandall

  • PIC18
  • ****
  • Mensajes: 383
Re: Regresar valor en interrupción del uart
« Respuesta #1 en: 08 de Septiembre de 2012, 12:38:28 »
Bueno, si alguien tiene el por que, seria de gran ayuda, pero la solución fue bien sencilla, solo agregue una linea de código al main, después del if, cualquier linea me funciono.
Código: [Seleccionar]

int main(void)
{   
    init_usb();

    LED_ON_OFF = 1;

    secuencia   =       1;
    p           =       10;

    while(1){
        if(secuencia==1){
            PutCharacter_U2(secuencia);
            WriteString_U2("*** Hola!!! ***\r\n");
            secuencia   =       0;
        }
        LED_ON_OFF = 1;
}

Solamente agregue
Código: [Seleccionar]
LED_ON_OFF = 1; Y funciono perfectamente.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Regresar valor en interrupción del uart
« Respuesta #2 en: 08 de Septiembre de 2012, 13:54:07 »
Esa variable que cambias en la interrupción la estableces como volatile?
No contesto mensajes privados, las consultas en el foro

Desconectado IngRandall

  • PIC18
  • ****
  • Mensajes: 383
Re: Regresar valor en interrupción del uart
« Respuesta #3 en: 10 de Septiembre de 2012, 09:38:39 »
No, esa variable es global y esta declarada como "unsigned char"... si fuera "volatile" creo que allí estaría el problema... gracias.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Regresar valor en interrupción del uart
« Respuesta #4 en: 10 de Septiembre de 2012, 10:45:36 »
Ese puede ser el problema, cuando una variable es modificada en una interrupción y es consultada constantemente en algún lugar del código debe colocarse como volatile.


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado IngRandall

  • PIC18
  • ****
  • Mensajes: 383
Re: Regresar valor en interrupción del uart
« Respuesta #5 en: 10 de Septiembre de 2012, 10:47:01 »
Bueno, al parecer tengo mal el concepto de "volatile"... voy a buscarlo, gracias.


Aqui lo encontre link... tenia errado el concepto.
« Última modificación: 10 de Septiembre de 2012, 10:53:52 por IngRandall »

Desconectado jukinch

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 608
Re: Regresar valor en interrupción del uart
« Respuesta #6 en: 10 de Septiembre de 2012, 10:51:40 »
Hola.
en este link: http://pablohoffman.com/cgi-bin/twiki/bin/view/Oscusb/DocCap05Firmware#Uso_del_calificador_volatile
podés ver un ejemplo muy claro de uso y del problema de no usar el calificador volatile para una variable que cambie dentro de una interrupción.
            Saludos a todos.
                     Jukinch.
"Divide las dificultades que examinas en tantas partes como sea posible para su mejor solución." -René Descartes

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Regresar valor en interrupción del uart
« Respuesta #7 en: 10 de Septiembre de 2012, 19:43:25 »
Es uno de los peores errores, porque muchas veces son dificiles de encontrar, debido a que un sutil cambio de codigo puede hacer que la optimizacion o cacheo de la variable en cuestión desaparezca o aparezca.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado IngRandall

  • PIC18
  • ****
  • Mensajes: 383
Re: Regresar valor en interrupción del uart
« Respuesta #8 en: 11 de Octubre de 2012, 17:55:11 »
Bueno, ya solucionado esto, ahora lo que que estoy haciendo es simplemente lo que entre por el uart 1 salga por el uart 2 y viceversa, pero no me esta funcionando bien, me salen mas letras que no he escrito o la letra que escribo me sale doble o escribo otra letra y me sale la letra anterior varias veces antes de que se cambie a la letra que quiero enviar, les voy a dejar el método de interrupción que estoy trabajando:

Código: [Seleccionar]
void __ISR(_UART2_VECTOR, ipl3) IntUart2Handler(void)
{
// Is this an RX interrupt?
if(INTGetFlag(INT_SOURCE_UART_RX(UART2)))
{
// Clear the RX interrupt Flag
       INTClearFlag(INT_SOURCE_UART_RX(UART2));

// Echo what we just received.
                data[0]=UARTGetDataByte(UART2);
                data[0]=data[0]&0x00ff;
                UARTSendDataByte(UART1, data[0]);
}

// We don't care about TX interrupt
if ( INTGetFlag(INT_SOURCE_UART_TX(UART2)) )
{
INTClearFlag(INT_SOURCE_UART_TX(UART2));
}
}

Adjunto también envió una foto, del lado derecho estoy enviando el dato y del lado izquierdo lo que sale del otro uart, y como podrán ver no se parece en nada.
« Última modificación: 11 de Octubre de 2012, 18:03:50 por IngRandall »

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Regresar valor en interrupción del uart
« Respuesta #9 en: 11 de Octubre de 2012, 20:19:50 »
Me parece que fuera un error en la configuración del baudrate, podrá ser?


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado IngRandall

  • PIC18
  • ****
  • Mensajes: 383
Re: Regresar valor en interrupción del uart
« Respuesta #10 en: 12 de Octubre de 2012, 09:28:47 »
Bueno tal vez, estuve mirando lo que sucedía y como las primeras 5 letras si las escribo de forma lenta funcionan bien luego de eso es que empieza a duplicarse lo que mando pero con una letra al azar, aquí esta el código de configuración del baudrate:

Código: [Seleccionar]
#define GetSystemClock() (80000000ul) // Hz
#define GetInstructionClock() (GetSystemClock()/1) // Normally GetSystemClock()/4 for PIC18, GetSystemClock()/2 for PIC24/dsPIC, and GetSystemClock()/1 for PIC32.  Might need changing if using Doze modes.
#define GetPeripheralClock() (GetSystemClock()/1) // Normally GetSystemClock()/4 for PIC18, GetSystemClock()/2 for PIC24/dsPIC, and GetSystemClock()/1 for PIC32.  Divisor may be different if using a PIC32 since it's configurable.

#define DESIRED_BAUDRATE     (115200)      //The desired BaudRate

    // Configure the device for maximum performance but do not change the PBDIV
    // Given the options, this function will change the flash wait states, RAM
    // wait state and enable prefetch cache but will not change the PBDIV.
    // The PBDIV value is already set via the pragma FPBDIV option above..
    SYSTEMConfig(GetSystemClock(), SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);

void configuracion_uart2()
{
    UARTConfigure(UART2, UART_ENABLE_PINS_TX_RX_ONLY);
    UARTSetFifoMode(UART2, UART_INTERRUPT_ON_TX_NOT_FULL | UART_INTERRUPT_ON_RX_NOT_EMPTY);
    UARTSetLineControl(UART2, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
    UARTSetDataRate(UART2, GetPeripheralClock(), DESIRED_BAUDRATE);
    UARTEnable(UART2, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));

// Configure UART2 RX Interrupt
    INTEnable(INT_SOURCE_UART_RX(UART2), INT_ENABLED);
    INTSetVectorPriority(INT_VECTOR_UART(UART2), INT_PRIORITY_LEVEL_3);
    INTSetVectorSubPriority(INT_VECTOR_UART(UART2), INT_SUB_PRIORITY_LEVEL_0);
}

Adjunto otra foto, donde al principio del programa mando por cada uno de los uart una frase para saber si la transmisión del uart funciona correctamente.
« Última modificación: 12 de Octubre de 2012, 11:33:22 por IngRandall »

Desconectado IngRandall

  • PIC18
  • ****
  • Mensajes: 383
Re: Regresar valor en interrupción del uart
« Respuesta #11 en: 16 de Octubre de 2012, 10:38:54 »
Hola amigos, pues seguía con mi problema y por este motivo me dirigí al libro Programming 32-bit Microcontrollers in C Exploring the PIC32 de Lucio di Jasio, y allí me encuentro con que el no trabaja con las librerías si no con los registros directos y para mi sorpresa los probé y funcionaron perfectamente... aquí el código:

Código: [Seleccionar]
void __ISR(_UART1_VECTOR, ipl3)IntUart1Handler(void)
{
    unsigned char Temp;
    LED_Rx_U1 = 1;

    while ( !U1STAbits.URXDA); // wait for a new char to arrive

    Temp=U1RXREG;

    UARTSendDataByte(UART1, Temp);
    UARTSendDataByte(UART2, Temp);

    LED_Rx_U1 = 0;
}

Desconectado IngRandall

  • PIC18
  • ****
  • Mensajes: 383
Re: Regresar valor en interrupción del uart
« Respuesta #12 en: 17 de Octubre de 2012, 13:25:23 »
Todo iba muy bien, pero otra vez algo se aparece en el camino... Esta vez es que cuando envió un dato por uno de los dos uart, lo envía al otro perfecto y si vuelvo a enviar las veces que yo quiera sigue perfecto, hasta aquí todo bien, pero si envió por el otro uart, no me funciona la interrupción  :shock: :shock: :shock:

La verdad no se si me hice explicar, pero aquí les dejo la interrupción de los dos uart, a ver si pueden detectar algo.

Código: [Seleccionar]
void __ISR(_UART1_VECTOR, ipl3)IntUart1Handler(void)
{
    LED_Rx_U1 = 0;
   
    IFS0bits.U1RXIF = 0;
    unsigned char Temp;
   
    while ( !U1STAbits.URXDA); // wait for a new char to arrive

    Temp=U1RXREG;

    UARTSendDataByte(UART2, Temp);

    LED_Rx_U1 = 1;
}
// UART 2 interrupt handler
// it is set at priority level 2
void __ISR(_UART2_VECTOR, ipl3) IntUart2Handler(void)//_UART2_VECTOR
{
    LED_Rx_U2 = 0;
   
    IFS1bits.U2RXIF = 0;
    unsigned char Temp;
   
    while ( !U2STAbits.URXDA); // wait for a new char to arrive

    Temp=U2RXREG;

    UARTSendDataByte(UART1, Temp);

    LED_Rx_U2 = 1;
}