Actualmente estoy tratando de escribir código para un atenuador controlado por DMX de 48 canales usando un PIC24FJ32GA002. Usando un alcance, confirmé que hay una señal DMX que llega al pin Rx del UART que se configuró correctamente usando la función PPS de la imagen. También se deshabilitan las interrupciones anidadas.
A continuación se muestra el contenido de mi ISR para la interrupción UART Rx. Lo que sucede cuando lo depuro con un punto de interrupción establecido dentro del ISR es que el ISR se activa una o dos veces con datos nulos que llegan U1RXREG
, luego no se activa nuevamente y el programa se ejecuta sin más interrupciones.
El bucle principal del programa tiene un bucle que procesa los paquetes DMX entrantes y los envía al controlador PWM. dmxRecieveByte()
toma el contenido rxbyte
y lo coloca en un búfer que tiene el tamaño adecuado para almacenar un paquete DMX (512 bytes) para luego copiarlo en un búfer separado cuando se recibe el paquete.
ACTUALIZACIÓN: Cambié los ISR para que haya controladores separados para errores y bytes entrantes, la uartRecieve()
función ahora maneja la clasificación de los bytes entrantes y los ISR se encargan de borrar banderas y demás. El Tx ISR está allí como marcador de posición hasta que la funcionalidad DMX funcione correctamente.
ACTUALIZACIÓN 2: Se agregó el código de inicio de UART y el código Rx ISR actualizado, y aún se activa el ISR una vez en los programas que se ejecutan por primera vez y luego no vuelve a suceder. Ahora tengo el hardware de producción, por lo que se han eliminado todas las variables que estaban allí. Hurgué con una sonda de alcance y todo parece estar en orden en cuanto a la señal.
Función de inicio de UART
void dmxInit(void)
{
DMX_UART_MODE = 0b0000000000001001;
DMX_UART_BAUD = (FCY/(4*250000))-1;
DMX_INT_PRIORITY = 0x07;
PORTBbits.DMX_RX_MUX = 0;
spareBufValid = 0;
DMX_UART_ENABLE_BIT = 1;
DMX_INT_ENABLE_BIT = 1;
}
UART Rx ISR
void __attribute__ ((interrupt,no_auto_psv)) DMX_INTERRUPT_FUNC(void)
{
uint8_t dmxData;
if(DMX_OVERRUN_BIT)
{ // Overrun error
DMX_OVERRUN_BIT = 0;
dmxReset();
}
else
{ // empty any data in the UART fifo
while(DMX_DATA_AVAIL_BIT)
{
if(DMX_FRAME_ERR_BIT)
{ // frame error
if(DMX_DATA_REG)
{ // data is not 0 - not a break
dmxReset();
}
else
{ // its a break!
breakDetected = 1;
startDetected = 0;
if(writeCount)
{
dmxWriteBufSwap();
}
}
}
else
{ // data in the fifo
dmxData = DMX_DATA_REG;
if(breakDetected)
{
if(startDetected)
{ // some DMX data
if(rxCount == fixture.DMXStartAddress)
{
pByteWrite = pWriteBuf;
}
if(pByteWrite)
{
*pByteWrite++ = dmxData;
writeBufSize++;
if( (writeBufSize >= NumberOfChannels) || (rxCount >= NUM_DMX_CHANNELS-1) )
{ // finished receiving this packet
dmxWriteBufSwap();
}
}
rxCount++;
}
else
{ // This is the start code
if(dmxData == DMX_DATA_START_CODE)
{
startDetected = 1;
writeBufSize = 0;
rxCount = 0;
}
else
{ // some other start code
dmxReset();
}
}
}
}
}
}
DMX_INT_FLAG_BIT = 0; // Clear interrupt flag
}
Entonces resulta que esa familia de PIC tiene un módulo ADC que automáticamente tiene prioridad sobre cualquier otro componente y evita que los pines causen interrupciones hasta que se deshabilita. Se agregó un código de desactivación a la función de inicialización del hardware principal para desactivar el ADC en todos los pines y ahora funciona de maravilla.
Ese PIC tiene un vector de interrupción separado para errores UART.
Creo que encontrará que su UART está atascado en una condición de error no controlada y se niega a recibir más datos.
Le sugiero que mueva su código de verificación y manejo de errores de encuadre y desbordamiento a un nuevo controlador _U1ErrInterrupt.
Oleg Mazúrov
Justin Trzeciak