Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: USART mega128
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
_Артём_
Добрый день.
Проблема в следующем:
нужно определить момент завершения передачи пакета данных (RS485).
Передача байта:
Код
    if (UCSR0A&(1<<UDRE1)) {
        UCSR0A=(1<<TXC0);
        UDR0 = TxBuffer.ReadByte();
    }


Переключение линии:
Код
    if (TxBuffer.Size()==0) {
        if (UCSR0A&(1<<TXC0)) {
            if (OffTx485Count) {
                if (--OffTx485Count==0) {
                    DDRB|=(1<<5);
                    PORTB|=(1<<5);
                }
            }
        }
    }


В JTAG-е вижу странную ситуацию:
после записи в UDR0 (UDR0 = TxBuffer.ReadByte())
бит TXC сразу же устанавливается, чего быть не должно.
Как тогда определить конец пакета?
ILYAUL
Цитата(_Артём_ @ Nov 10 2011, 17:32) *
В JTAG-е вижу странную ситуацию:
после записи в UDR0 (UDR0 = TxBuffer.ReadByte())
бит TXC сразу же устанавливается, чего быть не должно.
Как тогда определить конец пакета?

Флаг Txc устанавливается, если отослан весь байт , а за это время в UDRE новый не поступил.
_Артём_
Цитата(ILYAUL @ Nov 10 2011, 16:07) *
Флаг Txc устанавливается, если отослан весь байт , а за это время в UDRE новый не поступил.


Разобрался.
Сделал так:
Код
    if (UCSR0A&(1<<UDRE1)) {
        UDR0 = TxBuffer.ReadByte();
        UCSR0A=(1<<TXC0); // сброс флага окончания передачи байта
    }
kolobok0
Цитата(_Артём_ @ Nov 10 2011, 18:26) *
..Сделал так:
Код
        UCSR0A=(1<<TXC0); // сброс флага окончания передачи байта



и ышо 5 коп...
если у вас над 485 крутиться модбас, то перед сбросом передатчика, после окончании передачи, надо анализировать таймер. и удерживать передачу некоторое время (согласно скорости)...

читать на эту тему - в википедии кажется было разжовано. тема типа: повышение устойчивости к помехам в протоколе 485 за счёт модбаса (не дословно)


удачи вам
(круглый)
demiurg_spb
Используйте все три прерывания уарта и будет вам счастье. Это как раз для RS485 и сделано.
RXC - приём
UDRE - отправка
TXC - переключение на приём.
_Артём_
Цитата(demiurg_spb @ Nov 14 2011, 21:34) *
Используйте все три прерывания уарта и будет вам счастье. Это как раз для RS485 и сделано.
RXC - приём
UDRE - отправка
TXC - переключение на приём.

Все три не хочу использовать: есть прерывание таймера 2 кГц - хватает отправлять/принимать, но убрать RTS нужно вовремя.

Вот так будет правильно?

Код
#pragma vector=TIMER1_COMPA_vect
__interrupt void timer_1_isr(void)
{
if (UCSR0A&(1<<UDRE1)) {
    if (BufferNotEmpty()) {
        UDR0 = ReadByteForUart();
        UCSR0A|=(1<<TXC0);
        if (LastByteInPacket())
            UCSR0B|=(1<<TXCIE0);
        }
    }
}

#pragma vector=USART0_TXC_vect
__interrupt void ClrRtsInterrupt()
{
    ClrRTS();
    UCSR0B&=~(1<<TXCIE0);
}
demiurg_spb
Цитата(_Артём_ @ Dec 20 2011, 14:53) *
Все три не хочу использовать: есть прерывание таймера 2 кГц - хватает отправлять/принимать, но убрать RTS нужно вовремя.

Именно для этого и созданы 3 отдельных прерывания. Таймер тут совершенно не нужен.
Зачем изобретать отправку на таймере = "чёрт-знает что"?
Цитата
Вот так будет правильно?
Возможно. Как будет правильно я уже посоветовал...
_Артём_
Цитата(demiurg_spb @ Dec 20 2011, 14:38) *
Именно для этого и созданы 3 отдельных прерывания. Таймер тут совершенно не нужен.

Таймер нужен, но не тум а мне в системе(не специально для RS485, а много для чего нужен) и так как он в системе уже есть те там же можно принимать/передавать данные - скорости хватает.

Цитата(demiurg_spb @ Dec 20 2011, 14:38) *
Как будет правильно я уже посоветовал.

Спасибо за совет.
Вводить два лишних прерывания я не буду, одно можно.

Вызывает сомнения последовательность:
Код
UDR0 = ReadByteForUart();
        UCSR0A|=(1<<TXC0);
        if (LastByteInPacket())
            UCSR0B|=(1<<TXCIE0);
        }


Правильна ли она?

Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.