Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проблема с RS 485. Третий день туплю...
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Axxel
Доброго времени суток!
Проблема с RS485, третий день туплю.

Собрал простой переходник с RS232 на RS485 по этой схемке:

схема.


Схема ИМХО работает, но с передачей данных появились проблемы
использовал Terminal. Для МК была написана простая тестовая программка:

_______________________________________________________________
//ICC-AVR application builder : 05.02.07 16:50:48
// Target : M16
// Crystal: 6.4Mhz

#include <iom16v.h>
#include <macros.h>
#define RXBUF_SIZE 4
#define TXBUF_SIZE 4
unsigned char RxBuffer[RXBUF_SIZE],TxBuffer[TXBUF_SIZE];
unsigned char TranRequest=0,flag=0,done=0;
unsigned char RxIndex=0,TxIndex=0;
void port_init(void)
{
PORTA = 0xFF;
DDRA = 0x00;
PORTB = 0xFF;
DDRB = 0x00;
PORTC = 0xFF; //m103 output only
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0xFF;
TCCR0 = 0x05;
}

//UART0 initialisation
// desired baud rate: 9600
// actual: baud rate:9524 (0,8%)
// char size: 8 bit
// parity: Disabled
void uart0_init(void)
{
UCSRB = 0x00; //disable while setting baud rate
UCSRA = 0x00;
UCSRC = 0x06;
UBRRL = (unsigned char)41; //set baud rate lo
UBRRH = (unsigned char)41>>8; //set baud rate hi
UCSRB = 0xD8;
}


void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
uart0_init();

MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x00; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialised
}

#pragma interrupt_handler uart0_rx_isr:12
void uart0_rx_isr(void)
{
unsigned char RXchar;
RXchar=UDR;
RxBuffer[RxIndex++]=RXchar;
if(RxIndex>=(RXBUF_SIZE)){flag=1;RxIndex=0;PORTD=0xFF;/*на передачу*/}
}

#pragma interrupt_handler uart0_tx_isr:14
void uart0_tx_isr(void)
{
if(done==1){done=0;PORTD=0x00;/*на прием*/}
if(TranRequest==1)
{
unsigned char TXchar;
TXchar=TxBuffer[++TxIndex];
if(TxIndex==(TXBUF_SIZE-1)){TranRequest=0;TxIndex=0;done=1;}
UDR=TXchar;
}
}

void main()
{
init_devices();
while(1)
{
if(flag==1)
{
unsigned char inc;
flag=0;
TranRequest=1;
for(inc=0;inc<=(TXBUF_SIZE-1);inc++){TxBuffer[inc]=RxBuffer[inc];}
UDR=TxBuffer[0];
}



}
}
_______________________________________________________________
Смысл: передаем с ПК 4 любых символа, МК возвращает их обратно
МК их конечно же возвращает, но 1 из 5-7 пакетов-"битый".
На этом форуме я натыкался на тему, где описывалась проблема
с RS 485 с "лишним" 0-вым битом в символе,примерно похоже на мою
проблему: в основном в неверных символах у меня "лишний" как раз или 0-й
или 7-й бит.

Причем проблема именно с передачей с ПК.
МК шлет обратно то, что ему прислали, это
я проверил это следующим способом:

Конструкция типа:

PORTD=0xFF;//всегда передача
.....................
.....................
.....................
while(1)
{
puts("a very long string");
delayms(1500);
}

работает без единой ошибки передачи.
______________________________________

А конструкция типа:

PORTD=0x00;//всегда прием.
..................
.................
.................
................
получаем 4 символа,
проверяем равны ли они
символу(предположим) 'x'
если равны, то зажигаем
св.диод на 1сек.

на 5-7 пакетов дает сбой.



По поводу переходника: линию CTS не получилось
использовать из-за отсутсвия необходимого пина
в разъеме от мыши :-)
Но это так, к слову, я на это даже и не думаю...

Кто-нибудь сталкивался с подобной проблемой?
Можете натолкнуть на свежую мысль?
А то уже 3-й день туплю :-)

Заранее спасибо!
Andy Mozzhevilov
Если у вас именно двухпроводный RS485, с переключением драйверов на прием/передачу,
то тут просто передачей символов обойтись не получается, нужно делать помехоустойчивый
протокол обмена. Иначе при переключении линии на прием пока нет активных передатчиков
из-за помех может появляться ложный стартовый бит на входе UART со всеми последствиями.
В настольных условиях растяните линию RS-485 двумя резисторами на +5 и GND так, чтобы
при отсутствии активных передатчиков в линии на выходах RO драйверов была лог.1

PS: Да, и для вставки исходных текстов используйте тэги code
SasaVitebsk
С такой схемой не сталкивался. На схеме видно сигналы СTS/RTS. С пом. сигнала CTS обычно переключается направление передачи (Приём/передача). Это осуществляется програмно с компа. Вместо этого сигнала используется иногда DSR.

Без этих сигналов используется спец. схема. У вас я этого не увидел. Непонятно в связи с этим как она вообще работает. Если используешь спец схему, то чаще не добавляет, а обрезает биты. Так как схема устойчиво работает на определённых скоростях (определяется длительностью одновибратора).
IgorKossak
Цитата(Andy Mozzhevilov @ Feb 7 2007, 15:45) *
PS: Да, и для вставки исходных текстов используйте тэги code

Дабы не нарушать соответствующее правило форума, исходники такого размера крайне рекомендую аттачить к сообщению в виде файла.
=GM=
Цитата(Axxel @ Feb 7 2007, 11:42) *
Проблема с RS485, третий день туплю.
Собрал простой переходник с RS232 на RS485 по этой схемке:

Схема ИМХО работает, но с передачей данных появились проблемы
использовал Terminal. Кто-нибудь сталкивался с подобной проблемой?
Можете натолкнуть на свежую мысль?
А то уже 3-й день туплю :-)

Заранее спасибо!


По-моему, ошибка у вас кроется в нижеследующем фрагменте
Код
{
UCSRB = 0x00; //disable while setting baud rate
UCSRA = 0x00;
UCSRC = 0x06;
UBRRL = (unsigned char)41; //set baud rate lo
UBRRH = (unsigned char)41>>8; //set baud rate hi
UCSRB = 0xD8;
}

а именно в строчке UCSRC = 0x06; насколько я понимаю, вы хотите установить 8-битные данные, но записываете не в UCSRC, а в UBRRH, т.к. бит URSEL=0. Строчку надо просто заменить на UCSRC = 0x86, тогда будет именно 8-бит данных и ошибки должны пропасть.

Ну и надо бы переставить местами следующие строчки, вот так

UBRRH = (unsigned char)41>>8; //set baud rate hi
UBRRL = (unsigned char)41; //set baud rate lo

хотя не полностью уверен, что это атомарная операция для М16.
IgorKossak
Цитата(=GM= @ Feb 7 2007, 16:16) *
Ну и надо бы переставить местами следующие строчки, вот так

UBRRH = (unsigned char)41>>8; //set baud rate hi
UBRRL = (unsigned char)41; //set baud rate lo

хотя не полностью уверен, что это атомарная операция для М16.

Дело здесь очевидно в соблюдении правил доступа к 16-битным регистрам (Accessing 16-bit
Registers), описанным в документации на любой МК AVR.
SpiritDance
На время передачи с МК попробуйте выключать его приемник (RXCx).
muravei
Только что сделал преобразователь RS-232>RS-485 "по мотивам":
http://electronix.ru/forum/index.php?showtopic=1352
с опторазвязкой.Там же прочитал. что CTS от компа заморачиваться не стоит.(Проблемы Виндов)
Основной принцип работы без CTS в том , что передатчик дает в линию только "0", а "1" делается подтягивающими резисторами и на время RC(фронт импульса) передатчиком.
На столе работает до 115.2 больше не пробовал.В боевых условиях испытаю на неделе.
=GM=
Цитата(IgorKossak @ Feb 7 2007, 14:25) *
Цитата(=GM= @ Feb 7 2007, 16:16) *

Ну и надо бы переставить местами следующие строчки, вот так

UBRRH = (unsigned char)41>>8; //set baud rate hi
UBRRL = (unsigned char)41; //set baud rate lo

хотя не полностью уверен, что это атомарная операция для М16.

Дело здесь очевидно в соблюдении правил доступа к 16-битным регистрам (Accessing 16-bit
Registers), описанным в документации на любой МК AVR.

К счастью для Axxel, я здесь ошибся, поэтому в предыдущем посте и писал, что не полностью уверен. Для МК М16 регистры UBRRH и UBRRL не образуют "атомарную единицу", как скажем, регистры данных 16-битного таймера1, где данные для старшего регистра пишутся во временный регистр и потом переписываются в регистр таймера одновременно с записью в младший регистр.

Так что, можно записывать данные в пару UBRRH-UBRRL в любом порядке. Хотя почему-то во всех примерах сначала пишут в старший байт, потом в младший. Может для будущих расширений?
SasaVitebsk
Цитата(muravei @ Feb 7 2007, 19:23) *
Только что сделал преобразователь RS-232>RS-485 "по мотивам":
http://electronix.ru/forum/index.php?showtopic=1352
с опторазвязкой.Там же прочитал. что CTS от компа заморачиваться не стоит.(Проблемы Виндов)
Основной принцип работы без CTS в том , что передатчик дает в линию только "0", а "1" делается подтягивающими резисторами и на время RC(фронт импульса) передатчиком.
На столе работает до 115.2 больше не пробовал.В боевых условиях испытаю на неделе.


На витой паре (брал бухту сетевого провода) проверял на скорости 38400 / 305 метров. Использовал подключение типа (D+ / GND) - одна витая пара, (D- / GND) - другая.

Больше не пробовал, так как мне больше не надо было.

(Простите у меня без опторазвязки)
rezident
Цитата(SasaVitebsk @ Feb 8 2007, 03:00) *
На витой паре (брал бухту сетевого провода) проверял на скорости 38400 / 305 метров. Использовал подключение типа (D+ / GND) - одна витая пара, (D- / GND) - другая.

Это неправильное использование витой пары! Попарно (по проводам одной и той же витой пары) нужно пускать именно дифференциальные сигналы A и B (D+ и D- в вашей терминологии). Сигнал GND не является обязательно необходимым и служит в основном для выравнивания потенциалов приемников RS-485, чтобы не выйти за диапазон допустимых для него синфазных напряжений (обычно -7В...+12В).
Axxel
Спасибо всем за ответы, буду проверять все варианты.
Axxel
Всем доброго времени суток!
___________________________
Дошел я-таки до сути проблемы.
Мне кажется что проблема вот в чем:
Когда в Terminal ставишь в опциях Handshaking
галочку RTS on TX, программа, должна
перед отправкой пакета (или байта) выставлять сигнал RTS,
после отправки, соответственно убирать.
Опыт состоял собственно вот в чем:
Поставил галочку Handshaking-none
И попробовал устанавливать линию RTS ручками перед
отправкой пакета.
В программе МК ввел небольшую задержечку на ответ,
чтобы успеть перевести RTS на прием.
Далее действовал так: взводим RTS-отправляем пакет-выключаем RTS-получаем пакет обратно.
Результат: из всех отправленных пакетов-ни одного "битого".

А как было наверное в первом случае (IMHO):
Стоит галочка Handshaking-RTS on TX.
Набираем на клаве символ на передачу,
перед отправкой автоматически взводится RTS,
и после отправки этого символа сразу же переходит в
"слушание" (это видно по миганию светодиода)
Т.е на каждый символ приходится по смене направления потока,
а мне кажется что это не есть гут. ohmy.gif

Выскажите пожалуйста ваше мнение.
Спасибо!
Axxel
А еще скорее всего перепутал hanshaking c flow control.
blush.gif
Axxel
Да, именно так и вышло, тему можно закрывать. blush.gif
muravei
Цитата(rezident @ Feb 8 2007, 01:08) *
Это неправильное использование витой пары! Попарно (по проводам одной и той же витой пары) нужно пускать именно дифференциальные сигналы A и B (D+ и D- в вашей терминологии)

Зато есть надежда, что при правильном использовании, будет еще лучше! smile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.