Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: LPC2129 прерывание UART
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Д_М
Здравствуйте!
Работает прерывание приёма и опустошения регистра передачи. Очень хочется, чтобы было прерывание и по окончании передачи.
Ниже обработчик прерывания

CODE
#define RBR_Interrupt_Enable (1<< 0)
#define THRE_Interrupt_Enable (1<< 1)
#define LS_Interrupt_Enable (1<< 2)
#define Receive_Line_Status 6
#define Receive_Data_Available 4
#define Character_TimeOut_Indicator 0x0C
#define THRE_Interrupt 2
#define msk_ULSR_Errors 0x9E

void UART0VectoredIRQ (void) __irq
{
char
Msg,
dummy;

if(((Msg = U0IIR) & 0x01) == 0) // Flag Status of RX Int
{
switch(Msg & 0x0E) // Filter Msg
{
case Receive_Line_Status:
if (IOPIN & LED_G)
LEDS_ON = LED_G;
else
LEDS_OFF = LED_G;

if (U0LSR & msk_ULSR_Errors)
break;
else
if ((RTS0) && (U0LSR & (1<< TEMP))) // Transmition Finish
{
// Run Tx handler
/* if (IOPIN & LED_G)
LEDS_ON = LED_G;
else
LEDS_OFF = LED_G; */
U0IER = RBR_Interrupt_Enable | LS_Interrupt_Enable;
RTS0 = 0;
break;
}

case Receive_Data_Available:
RTS0 = 1;
U0IER = THRE_Interrupt_Enable;
U0THR = U0RBR + 3;
/* if (IOPIN & LED_G)
LEDS_ON = LED_G;
else
LEDS_OFF = LED_G; */
break;
case THRE_Interrupt:
if (IOPIN & LED_G)
LEDS_ON = LED_G;
else
LEDS_OFF = LED_G;

U0IER = LS_Interrupt_Enable;
/*
if (RTS0) // Transmition
if (amount_SIO0--)
U0THR = *ptr_SIO0++;
else
dummy = U0LSR; */
break;
default:
break;
}
}
VICVectAddr = 1;// Dummy write to signal end of interrupt
}

Программа должна возвращать один байт на один байт запроса. Как я себе представляю, при обработке прерывания опустошения регистра передачи, включается прерывание "состояние линии" (LS_Interrupt_Enable). Когда произойдёт это прерывание, отследить в регистре состояния линии (LSR) бит TransmitterEmpty(TEMT). Однако, управление не переходит на Receive_Line_Status
Что не так?
Д_М
Здравствуйте!
Было замечено, что прерывание THRE возникает не при опустошении регистра хранения передатчика, а при опустошении сдвигового регистра передатчика. Перед начало передачи была сброшена очередь передачи и включен светодиод. В обработчике прерывания опустошения регистра хранения передатчика светодиод выключался. Как я себе представляю, когда очередь пустая, один записанный байт тут же помещается в сдвиговый регистр и начинается его передача. Очередь становится опять пустой и должно сгенерироваться прерывание опустошения регистра хранения. Если так, то мигания светодиода не наблюдалось бы, так как время между двумя событиями слишком мало. Но светодиод вспыхивает очень хорошо. Это доказывает что прерывание THRE после завершения передачи.

CODE
void UART0VectoredIRQ (void) __irq
{
char
Msg,
dummy;

if(((Msg = U0IIR) & 0x01) == 0) // Flag Status of RX Int
{
switch(Msg & 0x0E) // Filter Msg
{
case Receive_Line_Status:
// if (RTS0)
if (IOPIN & LED_G)
LEDS_ON = LED_G;
else
LEDS_OFF = LED_G;

if (U0LSR & msk_ULSR_Errors)
/* if ((IOPIN & LED_G) && RTS0)
LEDS_ON = LED_G;
else
LEDS_OFF = LED_G; */

break;
else
/* if (RTS0)
{
if (IOPIN & LED_G)
LEDS_ON = LED_G;
else
LEDS_OFF = LED_G; */

if (U0LSR & (1<< TEMP)) // Transmition Finish
{
// Run Tx handler
/* if (IOPIN & LED_G)
LEDS_ON = LED_G;
else
LEDS_OFF = LED_G; */
U0IER = RBR_Interrupt_Enable | LS_Interrupt_Enable;
RTS0 = 0;
break;
}
// }

case Receive_Data_Available:
while(U0LSR & 1) // U0RBR contains valid data.
dummy = U0RBR;
// LEDS_ON = LED_G;
/* RTS0 = 1;
U0IER = 0;
U0FCR = SD_FIFO_ENABLE | SD_FIFO_RX_RESET | SD_FIFO_TX_RESET | RX_Trigger_Level1;
U0IER = THRE_Interrupt_Enable;
U0THR = U0RBR + 3;
LEDS_ON = LED_G;
if (IOPIN & LED_G)
LEDS_ON = LED_G;
else
LEDS_OFF = LED_G; */
break;
case Character_TimeOut_Indicator:
while(U0LSR & 1) // U0RBR contains valid data.
dummy = U0RBR;
// LEDS_OFF = LED_G;
LEDS_ON = LED_G;
RTS0 = 1;
U0IER = 0;
U0FCR = SD_FIFO_ENABLE | SD_FIFO_RX_RESET | SD_FIFO_TX_RESET | RX_Trigger_Level1;
break;
case THRE_Interrupt:
Msg = U0LSR;

if (Msg & (1<< THRE))
{
if (amount_SIO0--)
{
U0THR = 8;
LEDS_OFF = LED_G;
}
/* if (IOPIN & LED_G)
LEDS_ON = LED_G;
else
LEDS_OFF = LED_G; */
}

if (Msg & (1<< TEMP))
{
RTS0 = 0;
U0IER = RBR_Interrupt_Enable | LS_Interrupt_Enable;
/* if (IOPIN & LED_G)
LEDS_ON = LED_G;
else
LEDS_OFF = LED_G; */
}

break;
default:
break;
}
}
VICVectAddr = 1;// Dummy write to signal end of interrupt
}
Д_М
Кажется нашёл способ. Когда остаётся передать один байт, надо отключить очередь передачи. Тогда прерывание генерируется после завершения передачи последнего байта.
jcxz
Цитата(Д_М @ Mar 13 2015, 15:28) *
Было замечено, что прерывание THRE возникает не при опустошении регистра хранения передатчика, а при опустошении сдвигового регистра передатчика.

Сомнительное утверждение.
Я конечно конкретно это не проверял, но у нас много устройств на разных LPC с RS-485, где после приёма THREI мониторится состояние TEMT и, после его возникновения, отключается передатчик. И все работают ок.

Цитата(Д_М @ Mar 13 2015, 15:28) *
Перед начало передачи была сброшена очередь передачи и включен светодиод. В обработчике прерывания опустошения регистра хранения передатчика светодиод выключался. Как я себе представляю, когда очередь пустая, один записанный байт тут же помещается в сдвиговый регистр и начинается его передача. Очередь становится опять пустой и должно сгенерироваться прерывание опустошения регистра хранения. Если так, то мигания светодиода не наблюдалось бы, так как время между двумя событиями слишком мало. Но светодиод вспыхивает очень хорошо. Это доказывает что прерывание THRE после завершения передачи.

Не знаю про какой Вы исходник говорите, но в Вашем светодиод вроде включается после наступления события таймаута приёма. При этом все прерывания запрещаются и когда и где Вы потом опять их разрешаете не видно из исходника.
Так что мигать может как угодно и гореть как угодно долго.
И вообще - у Вас там такая каша, что трудно разобраться.
Научитесь пользоваться функциями или макросами для вкл/выкл светодиода.
И странно сначала запрещать все прерывания, а после этого считывать IIR.

PS: Ещё раз повторю - в 99.9% случаев ищите ошибку у себя, а не в чипе. А с таким кодом и во всех 100% у себя....
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.