Пишу реализацию ПИД-регулятора. МК LPC1768
Период перерасчета должен быть соблюден крайне точно, поэтому использую прерывания по таймеру и устанавливаю этому прерыванию наивысший приоритет.
CODE
void init_tmr1()
{
T1TCR_bit.CR = 1; // Сбрасываем
T1TCR_bit.CR = 0;
/*
Fp = 25 МГц Частота периферии.
T = 20 мс Желаемый период таймера.
N = Fp/T Формула рачета кол-ва тактов за период.
N = 250000 Кол-во тактов за желаемый период таймера.
*/
T1MR0 = 250000; // Загружаем регистр сравнения
T1MCR_bit.MR0I = 1; // Разрешаем прерывание по совпадению MR0
T1MCR_bit.MR0R = 1; // Разрешаем сброс таймера по совпадению MR0
T1TCR_bit.CE = 1; // Разрешаем счет
IP0_bit.PRI_2 = 0; // Приоритет прерывания: наивысший (0)
SETENA0_bit.SETENA2 = 1; // Разрешаем прерывания в NVIC
}
{
T1TCR_bit.CR = 1; // Сбрасываем
T1TCR_bit.CR = 0;
/*
Fp = 25 МГц Частота периферии.
T = 20 мс Желаемый период таймера.
N = Fp/T Формула рачета кол-ва тактов за период.
N = 250000 Кол-во тактов за желаемый период таймера.
*/
T1MR0 = 250000; // Загружаем регистр сравнения
T1MCR_bit.MR0I = 1; // Разрешаем прерывание по совпадению MR0
T1MCR_bit.MR0R = 1; // Разрешаем сброс таймера по совпадению MR0
T1TCR_bit.CE = 1; // Разрешаем счет
IP0_bit.PRI_2 = 0; // Приоритет прерывания: наивысший (0)
SETENA0_bit.SETENA2 = 1; // Разрешаем прерывания в NVIC
}
Далее в обработчике прерываний от этого таймера есть получение данных с абсолютного датчика положения.
Опрос датчика производится из прерывания таймера 1 раз за прерывания,
поэтому на осциллографе я наблюдаю пакеты опроса датчика строго с частотой таймера.
Ок.
Теперь инициализирую UART для приема управляющего воздействия (DMX512)
CODE
PCONP_bit.PCUART3 = 1;
FIO3DIR_bit.P3_26 = 1;
FIO3CLR = 1 << 26;
PINSEL0_bit.P0_0 = 2;
PINSEL0_bit.P0_1 = 2;
// Скорость
/*
F = Fp/(16*(DLM*256+DLL)*(1+DIV/MUL))
F = 250 kBod
Fp = 100 MHz
DLM = 0
DLL = 25
DIV = 0
MUL = 1
*/
U3LCR_bit.DLAB = 1;
U3DLL = 25;
U3DLM = 0;
U3LCR_bit.DLAB = 0;
// FIFO
U3FCR_bit.FCRFE = 1; // Включаем FIFO
U3FCR_bit.RFR = 1; // Сбрасываем RxFIFO
U3FCR_bit.TFR = 1; // Сбрасываем TxFIFO
U3FCR_bit.RTLS = 2; // Порог срабатывания 8 символов
// Формат
U3LCR_bit.WLS = 3; // 8 бит
U3LCR_bit.SBS = 1; // 2 стоп-бита
// Преывания
U3IER_bit.RDAIE = 1; // Разрешаем прерывание по входящим данным
U3IER_bit.RXLSIE = 1; // Разрешаем прерывание по статусу линии
IP2_bit.PRI_8 = 2; // Приоритет прерывания: средний (2)
SETENA0_bit.SETENA8 = 1; // Разрешаем в NVIC
}
FIO3DIR_bit.P3_26 = 1;
FIO3CLR = 1 << 26;
PINSEL0_bit.P0_0 = 2;
PINSEL0_bit.P0_1 = 2;
// Скорость
/*
F = Fp/(16*(DLM*256+DLL)*(1+DIV/MUL))
F = 250 kBod
Fp = 100 MHz
DLM = 0
DLL = 25
DIV = 0
MUL = 1
*/
U3LCR_bit.DLAB = 1;
U3DLL = 25;
U3DLM = 0;
U3LCR_bit.DLAB = 0;
// FIFO
U3FCR_bit.FCRFE = 1; // Включаем FIFO
U3FCR_bit.RFR = 1; // Сбрасываем RxFIFO
U3FCR_bit.TFR = 1; // Сбрасываем TxFIFO
U3FCR_bit.RTLS = 2; // Порог срабатывания 8 символов
// Формат
U3LCR_bit.WLS = 3; // 8 бит
U3LCR_bit.SBS = 1; // 2 стоп-бита
// Преывания
U3IER_bit.RDAIE = 1; // Разрешаем прерывание по входящим данным
U3IER_bit.RXLSIE = 1; // Разрешаем прерывание по статусу линии
IP2_bit.PRI_8 = 2; // Приоритет прерывания: средний (2)
SETENA0_bit.SETENA8 = 1; // Разрешаем в NVIC
}
И в обработчике прерываний уже непосредственно получение данных из FIFO.
Итак: приоритет таймера - 0, приоритет UART - 2. Но когда по UART приходят данные период таймера нарушается и становится вообще не понятно каким.
То есть вложенные прерывания не выполняются? Как это исправить?
А если в процессе приема данных по UART отключить источник сигнала, то программа из прерывания UART вообще не выходит и прерывания таймера не выполняются вообще!
Вот обработчик UART
CODE
void UART3_IRQHandler()
{
char uiir, ulsr, urbr;
do
{
uiir = U3IIR;
ulsr = U3LSR;
if((uiir & INTID) == RLS)
{
if(ulsr & (OE | PE))
bDMX = 0;
if(ulsr & BI)
{
nDMX = 0;
bDMX = 1;
}
U3RBR;
}
if((uiir & INTID) == RDA)
{
urbr = U3RBR;
if(nDMX && bDMX && (nDMX < 513))
DMX[(nDMX++)-1] = urbr;
else
if(!(nDMX++) && urbr)
bDMX = 0;
}
}
while(!(uiir & INTPEND));
CLRPEND0_bit.CLRPEND8 = 1;
}
{
char uiir, ulsr, urbr;
do
{
uiir = U3IIR;
ulsr = U3LSR;
if((uiir & INTID) == RLS)
{
if(ulsr & (OE | PE))
bDMX = 0;
if(ulsr & BI)
{
nDMX = 0;
bDMX = 1;
}
U3RBR;
}
if((uiir & INTID) == RDA)
{
urbr = U3RBR;
if(nDMX && bDMX && (nDMX < 513))
DMX[(nDMX++)-1] = urbr;
else
if(!(nDMX++) && urbr)
bDMX = 0;
}
}
while(!(uiir & INTPEND));
CLRPEND0_bit.CLRPEND8 = 1;
}