Прерывание PIC24F UART Rx не срабатывает

В настоящее время я пытаюсь написать код для 48-канального диммера, управляемого DMX, с использованием PIC24FJ32GA002. С помощью осциллографа я подтвердил наличие сигнала DMX, достигающего вывода Rx UART, который был правильно настроен с помощью функции PPS на рис. Также отключены вложенные прерывания.

Ниже приведено содержимое моего ISR для прерывания UART Rx. Что происходит, когда я отлаживаю его с помощью точки останова, установленной внутри ISR, так это то, что ISR запускается один или два раза с достижением нулевых данных U1RXREG, затем он снова не запускается, и программа работает без дальнейших прерываний.

Основной цикл программы имеет цикл, который обрабатывает входящие DMX-пакеты и выводит их на ШИМ-контроллер. dmxRecieveByte()берет содержимое rxbyteи помещает его в буфер подходящего размера для хранения DMX-пакета (512 байт), который затем копируется в отдельный буфер при получении пакета.

ОБНОВЛЕНИЕ: я изменил ISR, чтобы были отдельные обработчики для ошибок и входящих байтов, uartRecieve()теперь функция обрабатывает сортировку входящих байтов, а ISR заботятся об очистке флагов и тому подобном. Tx ISR используется в качестве заполнителя до тех пор, пока я не получу правильную работу DMX.

ОБНОВЛЕНИЕ 2: добавлен код инициализации UART и обновленный код Rx ISR, при этом ISR по-прежнему срабатывает один раз при первом запуске программ, а затем больше не повторяется. Теперь у меня есть производственное оборудование, поэтому все переменные, которые были в нем, были удалены. Поковырялся с прицелом, с сигналом вроде все в порядке.

Функция инициализации 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
}
ISR выглядит правильно для меня. Опубликуйте свою инициализацию.
Глобальные прерывания включены?

Ответы (2)

Итак, оказывается, что в этом семействе PIC есть модуль АЦП, который автоматически имеет приоритет над любыми другими компонентами и предотвращает прерывание контактов, пока он не будет отключен. В основную функцию инициализации оборудования добавлен некоторый код отключения, чтобы отключить АЦП на всех выводах, и теперь это работает.

Этот PIC имеет отдельный вектор прерывания для ошибок UART.
Я думаю, вы обнаружите, что ваш UART застрял в состоянии необработанной ошибки и отказывается получать какие-либо данные.
Я предлагаю вам переместить код проверки и обработки переполнения и ошибок кадрирования в новый обработчик _U1ErrInterrupt.

Для ошибок есть отдельный обработчик прерываний, посмотрю, поможет ли реструктуризация моего кода.
Покажите нам также свой код инициализации UART. Может там что-то есть...