В настоящее время я пытаюсь написать код для 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
}
Итак, оказывается, что в этом семействе PIC есть модуль АЦП, который автоматически имеет приоритет над любыми другими компонентами и предотвращает прерывание контактов, пока он не будет отключен. В основную функцию инициализации оборудования добавлен некоторый код отключения, чтобы отключить АЦП на всех выводах, и теперь это работает.
Этот PIC имеет отдельный вектор прерывания для ошибок UART.
Я думаю, вы обнаружите, что ваш UART застрял в состоянии необработанной ошибки и отказывается получать какие-либо данные.
Я предлагаю вам переместить код проверки и обработки переполнения и ошибок кадрирования в новый обработчик _U1ErrInterrupt.
Олег Мазуров
Джастин Тречак