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

Доброго времени суток уважаемые!

 

Значит перейдём сразу к сабжу:

 

Имеются два устройства, назовём их условно мастером и слейвом. Мастер и слейв должны общаЦЦа меж собой через USART. Но они не общаются, вернее не всегда. Мастер и слейв оснащены интерфейсными микросхемами ADM483.

 

Была готовая рабочая программа, у мастера она выглядела так:

 

out UDR,temp
sei
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
rcall DEL64MS
cli
sbi PORTD,2    ;установка усарта в режим передатчика (используется
                     ;интерфейсная микросхема ADM485)

 

Изначально мастер был в режиме передатчика. Ну код не очень сложный, думаю понятно что к чему. Так вот мне была поставлена задача уменьшить время с 640 милисекунд до минимально возмаожного. (DEL64MS - п/п задержки на 64 мс).

 

Вот что у меня получилось:

zapr: UCSRA,UDRE          ;проверяю на готовность УДРа принимать инфу
        rjmp zapr
        out UDR,temp         ;засылаю передаваемые данные
        rcall DEL1MS           ;без особого смысла
        rcall TxComp          ;не знаю почему, но после передачи программа не 
                                     ;уходит в обработчик прерывания сразу. если 
                                     ;слейвов несколько (мастер их поочерёдно 
                                     ;опрашивает), то прерывание срабатывает только 
                                     ;после последнего слейв
       
        rcall DEL1MS          ;это я вычитал, что переключение в режим 
        rcall DEL1MS          ;передатчика происходит от 300 до 3000 
        rcall DEL1MS          ;микросекун
        
        ldi r17,0xFF            ;почти пустой цикл, который длится около 40
lp1:   ldi r18,0xFF            ;милисекунд. Выход из цикла происходит
lp2:   sbic UCSRA,RXC     ;тогда, когда приходят данные.
        rjmp otv                ;По логике в принципе 40 мс должно хватить
        dec r18                  ;что бы слейв отреагировал и выдол ответ
        breq lp2                 ;
        dec r17                  ;
        breq lp1                 ;

       sbi PORTD,2           ;усарт -> ражим передатчика

если интересно, то вот программа слейва:

         in temp,UDR
        sbis temp,7
        rjmp enrx
        ....
        ....
        ....
        ....
enrx: cp temp,temp1
        brne end
        rcall del1ms
        rcall del1ms
        rcall del1ms
        rcall del1ms
        lds Z,DataToTransmit
        mov temp,Z
        out UDR,temp
end:

 

Теперь поподробнее. Представленная программа у слейва преставляет собой обработчик прерывания "приём завершён". У мастера и у слейва обработка прерывания по завершению передачи одиноков - усарт переводится в режим приёмника.

 

Сижу над этим уже неделю - так к слейву претензий нет - он всё прекрасно принимает и передаёт. За неделю я придумал мириады способов это проверить... А вот слейв меня расстраивает - предавать он в принципе передаёт, но вот обратно принимает не всегода. Причём закономерность мне выявить ну никак не удаётся. Из ста пакетов он может принять 64, 78, 55, 23, 70 и т.д. Причём ни разу 100 пакетов он не принял... Подскажите, в чём дело, может я чего не так делаю...

 

 

ЗЫ:. к слову:

 

бодрейт 38,4к, 1 стоп бит, 8 бит, бит четности, микроконтроллер рабоет на частоте 8Mz.

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


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

Что-то похожее на лечение гланд.

Зачем нужны все эти задержки?

получил флаг TXC после последнего байта пакета -значит можно переключится на прием и просто ждать RXC.

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


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

Согласен.... Но (повторюсь) я вычитал, что переключение режимов происхожит от 70 до 3000 мкс, поэтому я их и поставил. Сперва у меня так и было, но... После отправки пакета и приёмом ответных данных должно пройти какое то время. Так как все слейвы опрашиваются поочерёдно и ничего кроме опроса не происходит, то вероятнее всего в удр записываются данные ещёдо того как был установлен ТХС. Была сделана проверка флага, тогда программа на этом зацикливалась и отказывалась идти дальше. Потом была мысль, что происходит рассинхронизация мастера и слейва, т.е. слейв передаёт пакеты когда мастер ещё не переключился в режим приёма, тогда были поставлены задержки в программу слейва. Блин..... :cranky: Потом пытался поставить проверку флага RXC, но и из этого ничего путного не вышло, так как раз пакеты не доходят, то и собственно говоря флаг установлен не будет, поэтому программа опять зацикливалась. Потом был организован цикл, длительностью в 40 милисекунд, выход из которого происходил двумя способами - либо по истечению этого времени, либо по установке флага RXC. Из этого тоже ничего путного не вышло... И только увеличением этого цикла я добился (уже сегодня!) более-менее устойчивого приёма, но не всегда с первого раза... вернее с первого раза получалось довольно таки не всегда. (Но не верю я что при такой скорости предача происходит более 200 милисекунд).... :(

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


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

Согласен.... Но (повторюсь) я вычитал, что переключение режимов происхожит от 70 до 3000 мкс, поэтому я их и поставил.

....

выход из которого происходил двумя способами - либо по истечению этого времени, либо по установке флага RXC. Из этого тоже ничего путного не вышло... И

 

Фигня :). у меня адм485 переключается сразу. в том смысле, что передернул вывод, а следующей командой можно в UDR писать. на 38400 начало не глотает, проверено. Хотя по сути рс485 вначале и должна идти преамбула=активная пауза.

 

Флаги-то зачем? используй прерывание. Все равно UDR надо прочитать, даже если была ошибка фрейминга. А еще с АДМ бывает такая фишка: без растягивающих резисторов она иногда работает лучше.

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


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

Реальные гланды :)

 

Вот так работает в более десятка разных устройств и мастреров, и слэйвов:

#pragma vector=USART_TXC_vect
__interrupt void UTX()
{
 PORTC&=~(1<<PC5);
};

#pragma vector=USART_RXC_vect
__interrupt void URX()
{
 unsigned char RCV_data = UDR;
}

void SendUART(unsigned char data)
{
 while ( !(UCSRA&(1<<UDRE)) );
 PORTC|=(1<<PC5);
 UDR=data;
};

На PC5, как нетрудно догадаться, висит R/W

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


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

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

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

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

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

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

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

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

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

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