реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> USART mega128
_Артём_
сообщение Nov 10 2011, 13:32
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Добрый день.
Проблема в следующем:
нужно определить момент завершения передачи пакета данных (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 сразу же устанавливается, чего быть не должно.
Как тогда определить конец пакета?
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Nov 10 2011, 14:07
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



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

Флаг Txc устанавливается, если отослан весь байт , а за это время в UDRE новый не поступил.


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Nov 10 2011, 14:26
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



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


Разобрался.
Сделал так:
Код
    if (UCSR0A&(1<<UDRE1)) {
        UDR0 = TxBuffer.ReadByte();
        UCSR0A=(1<<TXC0); // сброс флага окончания передачи байта
    }
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Nov 11 2011, 18:25
Сообщение #4


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



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



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

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


удачи вам
(круглый)
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Nov 14 2011, 19:34
Сообщение #5


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Используйте все три прерывания уарта и будет вам счастье. Это как раз для RS485 и сделано.
RXC - приём
UDRE - отправка
TXC - переключение на приём.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Dec 20 2011, 11:53
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(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);
}
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Dec 20 2011, 12:38
Сообщение #7


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(_Артём_ @ Dec 20 2011, 14:53) *
Все три не хочу использовать: есть прерывание таймера 2 кГц - хватает отправлять/принимать, но убрать RTS нужно вовремя.

Именно для этого и созданы 3 отдельных прерывания. Таймер тут совершенно не нужен.
Зачем изобретать отправку на таймере = "чёрт-знает что"?
Цитата
Вот так будет правильно?
Возможно. Как будет правильно я уже посоветовал...


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Dec 20 2011, 12:47
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(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);
        }


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

Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 6th July 2025 - 13:18
Рейтинг@Mail.ru


Страница сгенерированна за 0.01444 секунд с 7
ELECTRONIX ©2004-2016