Перейти к содержанию
    

Проблема с UART LPC2214

К 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);

    }

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Т.е. при передаче я отключаю прерывание приемника, включаю разрешение пердачи ADM485 и передаю данные. Далее контролирую опустошение передатчика UART и сдвигового регистра и при фиксации сего, чищу фифо и активирую прерывание приемника.

Читать все написанное не стал, ибо зачем такие дивные навороты, если можно просто принимать свое эхо и выкидывать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, как-то я не подумал про такое. Еще увидел интересное решение - пинсел переключается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...