TODOPIC
Microcontroladores PIC => Pic32 => Mensaje iniciado por: IngRandall 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:
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:
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:
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 :( :( :( :( :( :( :( :(
-
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.
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 LED_ON_OFF = 1; Y funciono perfectamente.
-
Esa variable que cambias en la interrupción la estableces como volatile?
-
No, esa variable es global y esta declarada como "unsigned char"... si fuera "volatile" creo que allí estaría el problema... gracias.
-
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!
-
Bueno, al parecer tengo mal el concepto de "volatile"... voy a buscarlo, gracias.
Aqui lo encontre link (http://kcomputing.com/volatile.html)... tenia errado el concepto.
-
Hola.
en este link: http://pablohoffman.com/cgi-bin/twiki/bin/view/Oscusb/DocCap05Firmware#Uso_del_calificador_volatile (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.
-
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.
-
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:
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.
-
Me parece que fuera un error en la configuración del baudrate, podrá ser?
Saludos!
-
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:
#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.
-
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:
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;
}
-
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.
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;
}