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

По RS485 объединены мастер и несколько слейвов (все на mega128) мастер с интервалом в 100мс шлёт команду вида: префикс ":", байт - номер команды, байт - id слейва, 2 байта - аргументы для команды, постфикс ";". 1 из слейвов должен ответить что он подключен. Вот фрагмент кода слейва (codevisionAVR):

 

while (1)
      {
delay_ms(50);

command=0;
number=0;

while (getchar() != ':');

command=getchar();
number=getchar();

if ((command==1)&&(number==id))
{ 
PORTE.7=1;
printf(":%d online;",id);
PORTE.7=0;
}
// delay_ms(50);

      };
}

на деле отвечает только 1 раз первый запрошенный слейв.

что я делаю неправильно подскажите плз

 

 

поигрался интервалом отправки команд с мастера, начали отвечать несколько слейвов :)

proteus_prj.rar

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


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

Не понял - это симулятор ? А где код вкл-выключения 485 драйвера на передачу ? И что-то не нравится мне идея готовность выдавать в виде : :%d online . В данном случае девайсы услышат этот отклик, но команда будет равна 32 (код пробела) но зачем их напрягать то... Какая скорость 485 ?

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


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

код вкл-выключения 485 драйвера на передачу

PORTE.7=1;
....//передача
PORTE.7=0;

Теперь у меня вопрос: как правильнее синхронизировать передачу команды и ссчитывание из буфера слейвом.

Если ставлю интервал отправки мастером меньше чем интервал ссчитывания из буфера слейвом, то всё работает до переполнения буфера слейва. Сейчас попробую синхронизировать их таймером.

А как выходили из положения вы?

Сорри за сумбур :)

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


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

Ничего не понял. Какого буфера переполнение ? Зачем кстати 50 мс задержка в цикле ? PS после включения драйвера на передачу задржку надо бы на устаканивание переходных процессов в линии

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


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

ИМХО, слэйв отвечает на команду мастера не дождавшись окончания передачи мастера: передача слэйва начинается. когда получен id слэйва, но мастер еще передаёт 3 байта (аргументы и постфикс)

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


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

ИМХО, слэйв отвечает на команду мастера не дождавшись окончания передачи мастера: передача слэйва начинается. когда получен id слэйва, но мастер еще передаёт 3 байта (аргументы и постфикс)

Это самая главная проблема при работе с RS485 для мастера. ЕЕ надо решать корректно.

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


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

ИМХО, слэйв отвечает на команду мастера не дождавшись окончания передачи мастера: передача слэйва начинается. когда получен id слэйва, но мастер еще передаёт 3 байта (аргументы и постфикс)

 

Вы правы.

Поставил задержку перед ответом, все слейвы отвечают нормально

Дальше экспериментирую..

Буду благодарен за фрагмент исходника для слейвов с RS485 или хотябы словесное объяснение алгоритма.

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

Изменено пользователем Athlon128

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


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

Работу слейва,как вариант, можно описать следующим образом. Будем считать пакет принятым, если после приема последнего байта пакета истекла пауза равная времени передачи трех байтов, в течение которой не было принято ни одного байта. Если же во время паузы принимаем байт, то считаем его последним и вновь отслеживаем истечение паузы. И так далее пока пауза не истечет и пакет не будет принят. Отслеживанием паузы занимается таймер, в прерывании которого просто устанавливаем какой-либо флаг. К примеру:

 

//-------------------------------------------------------------------------------------------

unsigned char Read_USART(unsigned char kol) // kol - число байт, которое хотим принять

{

unsigned char i;

 

for(i=0;i<kol;i++)

{

TimerFlag0=0; //очищаем флаг срабатывания таймера

 

TCNT0=0xC8; //значение, соответсвующее паузе ~1.75мс

TCCR0=0x04; //запускаем таймер

//ожидаем приема байта

while (!(UCSRA & (1<<RXC)))

{

if(TimerFlag0) //проверка, время ожидания истекло

{

//возвращаем число реально принятых байт

return i;

}

//сбрасываем сторожевой таймер

WDR();

}

//считываем байт

buf=UDR;

TCCR0=0x00;

}

return i;

}

 

//---------------------------------------------------------------------------------------

//Прерывание от таймера 0, свидетельствует о превышении интервала ожидания для приема байта

 

interrupt [TIM0_OVF] void timer0_ovf_isr(void)

{ TCCR0=0x00; //останавливаем таймер

TimerFlag0=1; //устанавливаем флаг срабатывания

}

 

В основной программе:

//принимаем пакет

k=Read_USART(IN_BUF_LEN);

//анализируем его

error = AnalizeBuf(k);

 

:)

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


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

Буду благодарен за фрагмент исходника для слейвов с RS485 или хотябы словесное объяснение алгоритма.

 

В глаза бросаются недостатки примененного в Вашей работе протокола. Например, префикс и постфикс могут совпадать с другими полями команды (кодом, адресом, аргументами); если они применяются для целей нахождения начала и конца команды, то в этом случае - это будет сделать затруднительно. Да, и проверка "правильности" приема пакета (например, с помощью контрольной суммы) - дело не последнее. Рекомендую ознакомится с тем, как это делают другие. Например, тут http://www.caxapa.ru/lib/wake/ И исходники для AVR приведены...

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


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

В данном случае думаю проще Modbus ASCII использовать, тем более похоже им и навеяно

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


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

Либо ModBus RTU, тоже вещь очень хорошая. Я бы даже сказал просто не заменимая в работе Master-Slave систем.

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


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

В глаза бросаются недостатки примененного в Вашей работе протокола.

Я рекомендую протокол ModBus. Дешево и сердито.

PS. Какой у нас народ шустрый.

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


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

Modbus RTU не люблю по причине определенных сложностей обработки потока на компе (винда не real time, и 3.5 символа паузы определить 100 % проблематично). Лучше действительно wake- подобное, ну или если траффика не жалко ASCII Modbus

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


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

Пользую ModBus RTU (вернее ModBus RTU-подобный протокол ). Обычно поступаю следующим образом. В качестве мастера выступает комп, он формирует запросы, анализирует ответы, осуществляет мониторинг, пишет БД и т.д. Обмен информацией организую так:

1. Очищаю приемный и передаваемый буферы драйвера COM - порта;

2. Отправляю запрос слейв устройствам;

3. Делаю маленькую паузу;

4. Жду поступления в приемный буфер данных (проверяю число байт в буфере)

5. Как только в буфере появились байты осуществляю считывание, если данные не идут в течении определенного времени - вываливаюсь по TIMEOUT-у

6. Анализирую принятую инфу

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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