К LPC2214 подключена ADM485 у которой приемник постоянно включен. Т.е. при передаче я отключаю прерывание приемника, включаю разрешение пердачи ADM485 и передаю данные. Далее контролирую опустошение передатчика UART и сдвигового регистра и при фиксации сего, чищу фифо и активирую прерывание приемника. Проблема в том, что сразу после передчи и разрешения прерывания приемника, происходит прерывание и принимается переданный байт, не смотря на то, что я почистил фифо. Получается, фифо не всегда чистится или при каких-то условиях прерывание остается взведенным. Если под отладкой выполнять по шагам, такого не происходит. Помогите разобраться с данной ситуацией. Параметры уарта - скорость 38400, глубина фифо - 1 байт, остальное стандартно.
Вот такой у меня иср уарта:
Код
//********************************************************************************
**********
//Обработчик прерывания UART0
//******************************************************************** **********************
void UART0_Handler(void) __irq
{
u8_t data;
u8_t tmphead;
u8_t tmptail;
switch((data = U0IIR) & INTERRUPT_SOURCE_MASK)
{
//Прием
case SOURCE_RX:
data = U0RBR;
if((uart0.flags & (1<<UART0_FLAG_TX_IN_PROGRESS)) == 0)
{
tmphead = (uart0.rx_head + 1) & UART0_RX_BUFFER_MASK;
uart0.rx_head = tmphead;
if(tmphead == uart0.rx_tail)
{
//ERROR! Receive buffer overflow
uart0.flags |= (1<<UART0_FLAG_ERR);
}
uart0.rx_buf[tmphead] = data;
}
if(((data == 0x03) || (data == 0x06) || (data == 0x15)) && (avr.counter == 0))
{
data = 0x03;//Это для отлавливания ошибочной ситуации
}
break;
//Прередача
case SOURCE_THRE:
tmptail = uart0.tx_tail;
if(uart0.tx_head != tmptail)
{
tmptail = (uart0.tx_tail + 1) & UART0_TX_BUFFER_MASK;
uart0.tx_tail = tmptail;
U0THR = uart0.tx_buf[tmptail];
}
else
{
uart0.flags &= ~(1<<UART0_FLAG_TX_IN_PROGRESS);
uart0.flags |= (1<<UART0_FLAG_TX_COMPLETE);
}
break;
//Таймаут приема
case SOURCE_RX_TIMEOUT:
data = U0LSR;
data = U0RBR;
break;
//Ошибка
case SOURCE_ERROR:
data = U0LSR;
data = U0RBR;
break;
//Хрень какая-то
default:
data = U0LSR;
data = U0RBR;
}
VICVectAddr = 0;
}
Функции разрешения/запрещения передачи:
Код
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
// Запрет приема
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
void UART0_DisableReciveIRQ(void)
{
U0IER &= ~(1<<U0IER_RBR_Interrupt_Enable_BIT);
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
// Разрешение приема
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
void UART0_EnableReciveIRQ(void)
{
u8_t temp;
temp = U0LSR;
U0FCR = (1<<U0FCR_FIFO_Enable_BIT) | (1<<U0FCR_Tx_FIFO_Reset_BIT) | (1<<U0FCR_Rx_FIFO_Reset_BIT);
U0IER |= (1<<U0IER_RBR_Interrupt_Enable_BIT);
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
// Старт передачи
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
void UART0_Transmit_On(void)
{
UART0_DisableReciveIRQ();
IO0SET |= (1<<GL_BUS_DIR); //Включим передатчик RS485
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
// Стоп передачи
//::::::::::::::::::::::::::::::::::::::::::::::::::::::
void UART0_Transmit_Off(void)
{
IO0CLR |= (1<<GL_BUS_DIR); //Отключим передатчик RS485
UART0_EnableReciveIRQ(); //Разрешим прием
}
Проверка опустошения сдвигового регистра:
Код
u8_t UART0_Check_Shift_Reg_Emty(void)
{
if((uart0.flags & (1<<UART0_FLAG_TX_COMPLETE)) != 0)
{
if((U0LSR & (1<<U0LSR_TEMT_BIT) != 0) && (U0LSR & (1<<U0LSR_THRE_BIT) != 0))
{
uart0.flags &= ~(1<<UART0_FLAG_TX_COMPLETE);
return 1;
}
}
return 0;
}
Применеие в майне:
Код
system.state = SYSTEM_STATE_SCPU_BOOT;
while(1)
{
UART0_Transmit_On();
UART0_Transmit(0x15);
system.start_timer = TIME;
do
{
if(UART0_Check_Shift_Reg_Emty() != 0)
{
UART0_Buf_Clr();
UART0_Transmit_Off();
}
}while(system.start_timer != 0);
}