Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: MSP430F149, прерывания USART.
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
AHTOXA
RS485. Хочу управлять направлением передачи без таймера.
План был такой: не отключать приёмник у драйвера 485, ловить эхо переданных символов, и по приёму последнего символа отключать передатчик.

Пишу:
Код
    // прерывание по приёму.
    void rx_interrupt(void)
    {
        if (is_tx_on())   // передатчик включен?
        {
            if (!tx_on_)   // передача окончена?
                tx_off();   // отключаем передатчик.
        }
        else // обычный приём.
        {
            RxBuf.put(RXBUF0);
        }
    }

    // прерывание по передаче
     void tx_interrupt(void)
    {
        if (TxBuf.is_empty())
        {
            tx_on_ = false;
        }
        else
            TXBUF0 = TxBuf.get();
    }
};


Вроде бы всё логично. Сначала опустошается TXBUF0, возникает прерывание tx_interrupt, я сбрасываю флажок tx_on_. Затем этот последний символ принимается, возникает прерывание по приёму, я отключаю передатчик.

Но. Почему-то сначала возникает прерывание по приёму, а лишь затем - по опустошению передатчика! Как такое может быть?
Dog Pawlowa
Цитата(AHTOXA @ Jul 17 2009, 09:05) *
Но. Почему-то сначала возникает прерывание по приёму, а лишь затем - по опустошению передатчика! Как такое может быть?

Вполне логично, поскольку для приема достаточно информационных бит, а для передатчика наверняка еще стоповый бит включен.
MrYuran
Цитата(Dog Pawlowa @ Jul 17 2009, 10:35) *
Вполне логично, поскольку для приема достаточно информационных бит, а для передатчика наверняка еще стоповый бит включен.

Вряд ли, приёмник должен проконтролировать целостность фрейма, для этого стоповые тоже нужны.
Хотел было предположить, что прерывания формируются одновременно, но у приёма более высокий приоритет, ан нет.
#define USART1TX_VECTOR 4 /* 0xFFE4 USART 1 Transmit */
#define USART1RX_VECTOR 6 /* 0xFFE6 USART 1 Receive */
Трансмит выше. Да это и логично.
Загадка, однако!

Стоп...
Я чё-то не понял...
Прерывание по передаче формируется по окончании передачи?
Нажмите для просмотра прикрепленного файла
Тогда зачем вся эта свистопляска с эхом/приёмом?

Ещё вчера заметил забавную вещь.
Подряд закидывал 2 байта в U0TXBUF (в тестовых целях), а на осциле видел только последний.
Тоже удивился.
Dog Pawlowa
Цитата(MrYuran @ Jul 17 2009, 10:10) *
Вряд ли, приёмник должен проконтролировать целостность фрейма, для этого стоповые тоже нужны.

Это разные процессы.
Сформировать готовность(и прерывание) - это одно.
Продолжение накопления ошибок (например, переполнение будет сформировано если придет следующий старт - бит) - это другая функция аппаратуры.
AHTOXA
Цитата(MrYuran @ Jul 17 2009, 13:10) *
Стоп...
Я чё-то не понял...
Прерывание по передаче формируется по окончании передачи?


Вроде как прерывание передатчика происходит при задвигании U0TXBUF в сдвиговый регистр:
Нажмите для просмотра прикрепленного файла

То есть, сам символ ещё передаётся. Но по факту это не так.
MrYuran
Цитата(AHTOXA @ Jul 17 2009, 11:49) *
То есть, сам символ ещё передаётся. Но по факту это не так.

Возможно, IFG формируется как на картинке, а вот на прерывание наложено ещё одно условие (сдаётся мне, что TXEPT)
Провёл эксперимент на живой МСП-хе (правда, у меня сейчас 169, но не суть)
Код
interrupt(UART0TX_VECTOR) uart0_write_interrupt_handler(void)
{
    P6OUT |= 1;
    IFG1 &= ~UTXIFG0;                   // clear flag TXD0
    if(UART0.BytesToTransmit)           // Есть что передавать
    {


        // формируем CS в последнем байте пакета
        *(UART0.cTxBufPtr + UART0.BytesToTransmit) += ~(*(UART0.cTxBufPtr++) );
        UART0.BytesToTransmit --;
        U0TXBUF = *UART0.cTxBufPtr; // Выдаём очередной байт
        P6OUT &= ~1;
    }
    else        // передали весь пакет
    {

        UART0.events->DataSent = 1; // выставили флаг
        UART0.events->SendingData = 0;
        for(;UART0.uart->utctl.txept == 0;);
        P6OUT &= ~1;
#if LINE_MASTER_MODE == 1
        GetRealTime(&Timers.SendTimer);
        Timers.SendTimer += DIR_SWITCH_DELAY_MS;
#endif
        //UARTevents.SendingData = 0;
    }
}

В прерывании от последнего байта пакета дёргаю ногой вверх, а потом жду установки TXEPT и опускаю ногу.
Результат: импульс длительностью ~10 мкс - никак не длительность передачи (бодрэйт стоит 1200)
AHTOXA
Цитата(MrYuran @ Jul 17 2009, 14:37) *
Возможно, IFG формируется как на картинке, а вот на прерывание наложено ещё одно условие (сдаётся мне, что TXEPT)


Ну это вряд ли. Уж диаграммы в доках TI обычно всегда соответствуют. К тому же, при таком условии становится практически нереальной передача символов подряд.

Цитата
В прерывании от последнего байта пакета дёргаю ногой вверх, а потом жду установки TXEPT и опускаю ногу.
Результат: импульс длительностью ~10 мкс - никак не длительность передачи (бодрэйт стоит 1200)


Ну пусть даже 10 мкс. В любом случае прерывание по RX должно быть позже на эти самые 10 мкс!

А я в свою очередь попробовал выключать передатчик в прерывании по TX. Тоже плохо. Сейчас найду второй щуп, и исследую получше, что там в каком порядке происходитsmile.gif
MrYuran
Ещё один эксперимент.
Код
void test_UART()
{
    U0TXBUF = 0x5a;
    P6OUT |= 1;
    for(; IFG1 & UTXIFG0 == 0;);
    P6OUT |= 4;
    for(;UART0.uart->utctl.txept == 0;);
    P6OUT &= ~5;
}

Итого:
На обеих ногах импульс длительностью 8,5 мс
То есть: TXIFG формируется сразу же, как только кинули байт в буфер.

10 мкс в прошлом разе - это время выполнения обработчика прерывания.
То есть, по всей вероятности, в момент прерывания TXEPT уже торчит.

smile3046.gif

Попутно ткнулся в выходной сигнал и обнаружил, что начало стартового бита запаздывает относительно момента записи в сдвиговый регистр на 400 мкс, то есть половину битового интервала.
Щас гляну ещё конец.

Что и требовалось доказать. laughing.gif
TXEPT (по которому предположительно вызывается прерывание), тоже отодвинут на пол-интервала от конца стопового бита
AHTOXA
Цитата(MrYuran @ Jul 17 2009, 15:23) *
Итого:
На обеих ногах импульс длительностью 8,5 мс

На каких на обеих? А, понялsmile.gif
Цитата
То есть: TXIFG формируется сразу же, как только кинули байт в буфер.

Для первого символа - да. Ибо U0TXBUF сразу же перезаписывается в сдвиговый регистр и опустошается.
Цитата
10 мкс в прошлом разе - это время выполнения обработчика прерывания.
То есть, по всей вероятности, в момент прерывания TXEPT уже торчит.

Да там вроде команд не так многоsmile.gif
Цитата
Попутно ткнулся в выходной сигнал и обнаружил, что начало стартового бита запаздывает относительно момента записи в сдвиговый регистр на 400 мкс, то есть половину битового интервала.

Только всё же не в сдвиговый регистр, а в буфер передачи. Сдвиговый регистр - он унутре, и не доступен программистуsmile.gif

Цитата
TXEPT (по которому предположительно вызывается прерывание), тоже отодвинут на пол-интервала от конца стопового бита


Я всё же сильно сомневаюсь, что TXEPT влияет на возникновение прерывания. Попробуйте писать пару символов сразу, картина изменится. (я, к сожалению не нашёл второго лучаsad.gif )
MrYuran
Цитата(AHTOXA @ Jul 17 2009, 13:49) *
Попробуйте писать пару символов сразу, картина изменится. (я, к сожалению не нашёл второго лучаsad.gif )

Глянул.
Забавная картина.
Передаю 7 байтов подряд, в начале и конце обработчика TX_ISR машу ногой вверх/вниз.
И что же?
ровно в середине каждого стартового бита вижу тоненькую палку.
Ничего не понимаю! (с)
AHTOXA
Цитата(MrYuran @ Jul 17 2009, 16:51) *
ровно в середине каждого стартового бита вижу тоненькую палку.
Ничего не понимаю! (с)


Дык, это как раз нормальноsmile.gif Стартовый бит пошёл - буфер передатчика освободился (отправлен в сдвиговый регистр) - прерывание.

У меня возникли подозрения, что я банально пропускаю прерывание. Проц очень сильно нагружен, там scmRTOS, дисплей, то, сё... На сегодня плюнул, в понедельник буду ставить более чистый экспериментsmile.gif
=DS=
Цитата(AHTOXA @ Jul 17 2009, 10:05) *
Но. Почему-то сначала возникает прерывание по приёму, а лишь затем - по опустошению передатчика! Как такое может быть?


У UART MSP430 есть режим, когда прерывание возникает по приему стартового бита. Сделано это, чтобы можно было усыпить контроллер, и в то же время успеть включить DCO для приема символа.

slau049f.pdf USART Peripheral Interface, UART Mode page 13-19
Receive-Start Edge Detect Operation
The URXSE bit enables the receive start-edge detection feature. The recommended usage of the receive-start edge аeature is when BRCLK is sourced by the DCO and when the DCO is off because of low-power mode operation. The гltra-fast turn-on of the DCO allows character reception after the start edge detection.
When URXSE, URXIEx and GIE are set and a start edge occurs on URXDx, the internal signal URXS will be set. When URXS is set, a receive interrupt request is generated but URXIFGx is not set. User software in the receive interrupt service routine can test URXIFGx to determine the source of the interrupt. When URXIFGx = 0 a start edge was detected and when URXIFGx = 1 a valid character (or break) was received......


Проверьте состояние URXSE.
Может быть, получается так, что у Вас в течение одного такта срабатывают и прерывания по передаче и по приему, а первым обслуживается прием (приоритет я навскидку не помню)?
AHTOXA
Цитата(=DS= @ Jul 17 2009, 22:40) *
У UART MSP430 есть режим, когда прерывание возникает по приему стартового бита.


Не, не оно. Я проверял ужеsmile.gif

Цитата
Может быть, получается так, что у Вас в течение одного такта срабатывают и прерывания по передаче и по приему, а первым обслуживается прием (приоритет я навскидку не помню)?


Да нет. Во-первых, приоритет передатчика выше. А во-вторых (и в главных), прерывание передатчика должно возникать по опустошению буфера передатчика, задолго до физического окончания передачи (передача ведётся из сдвигового регистра).
Собственно из-за чего и приходится городить весь этот огород - нужно узнать момент окончания передачи, а не момент опустошения буфера передатчика.
=DS=
Цитата(AHTOXA @ Jul 17 2009, 20:49) *
Да нет. Во-первых, приоритет передатчика выше. А во-вторых (и в главных), прерывание передатчика должно возникать по опустошению буфера передатчика, задолго до физического окончания передачи (передача ведётся из сдвигового регистра).
Собственно из-за чего и приходится городить весь этот огород - нужно узнать момент окончания передачи, а не момент опустошения буфера передатчика.

Не поленился, проверил rolleyes.gif Приоритет приемника выше, да оно и логично.
А по поводу цепочки событий:
1.запихивание байта в сдвиговый регистр
2.начало передачи и генерация TX переывания
3. Получение эха стартового бита и генерация RX прерывания
4 Передача остального символа
Так что если события 2 и 3 попадут на один такт процессора, первым обслужится прием.

Но если URXSE не установлен... laughing.gif
И еще вариант, правда маловероятный - если очень велика разница между частотой MCU и UART, те символ успевает передаться в течение такта.
MrYuran
Цитата(=DS= @ Jul 17 2009, 21:20) *
Не поленился, проверил rolleyes.gif Приоритет приемника выше, да оно и логично.

Номер вектора приёма больше, соответственно приоритет ниже.
=DS=
Цитата(MrYuran @ Jul 17 2009, 22:20) *
Номер вектора приёма больше, соответственно приоритет ниже.

Я же написал, что ПРОВЕРИЛ crying.gif .
Не знаю, как сюда вклеить кусок даташита, но можете посмотреть сами.
AHTOXA
И правдаsmile.gif

Нажмите для просмотра прикрепленного файла

Но у меня дело точно не в этом. В понедельник буду разбираться...
AHTOXA
Докладываю, всё в порядке, нашёл в чём проблемаsmile.gif
Я перепутал процедуры выключения и включения прерывания передатчика в putch().

То есть, получалось, что прерывания передатчика были включены только внутри putch(), а остальное время - выключены. Вот от этого и были все странностиsmile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.