|
затруднение с RS485 |
|
|
|
Oct 24 2007, 04:09
|
Участник

Группа: Участник
Сообщений: 31
Регистрация: 18-04-06
Пользователь №: 16 238

|
По 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 раз первый запрошенный слейв. что я делаю неправильно подскажите плз поигрался интервалом отправки команд с мастера, начали отвечать несколько слейвов
|
|
|
|
3 страниц
1 2 3 >
|
 |
Ответов
(1 - 35)
|
Oct 24 2007, 04:28
|
Участник

Группа: Участник
Сообщений: 31
Регистрация: 18-04-06
Пользователь №: 16 238

|
код вкл-выключения 485 драйвера на передачу Код PORTE.7=1; ....//передача PORTE.7=0; Теперь у меня вопрос: как правильнее синхронизировать передачу команды и ссчитывание из буфера слейвом. Если ставлю интервал отправки мастером меньше чем интервал ссчитывания из буфера слейвом, то всё работает до переполнения буфера слейва. Сейчас попробую синхронизировать их таймером. А как выходили из положения вы? Сорри за сумбур
|
|
|
|
|
Oct 24 2007, 05:21
|
Участник

Группа: Участник
Сообщений: 31
Регистрация: 18-04-06
Пользователь №: 16 238

|
Цитата(Палыч @ Oct 24 2007, 10:51)  ИМХО, слэйв отвечает на команду мастера не дождавшись окончания передачи мастера: передача слэйва начинается. когда получен id слэйва, но мастер еще передаёт 3 байта (аргументы и постфикс) Вы правы. Поставил задержку перед ответом, все слейвы отвечают нормально Дальше экспериментирую.. Буду благодарен за фрагмент исходника для слейвов с RS485 или хотябы словесное объяснение алгоритма. Вечером отпишу что получилось у меня
Сообщение отредактировал Athlon128 - Oct 24 2007, 05:46
|
|
|
|
|
Oct 24 2007, 07:10
|
Участник

Группа: Участник
Сообщений: 43
Регистрация: 4-04-07
Пользователь №: 26 760

|
Работу слейва,как вариант, можно описать следующим образом. Будем считать пакет принятым, если после приема последнего байта пакета истекла пауза равная времени передачи трех байтов, в течение которой не было принято ни одного байта. Если же во время паузы принимаем байт, то считаем его последним и вновь отслеживаем истечение паузы. И так далее пока пауза не истечет и пакет не будет принят. Отслеживанием паузы занимается таймер, в прерывании которого просто устанавливаем какой-либо флаг. К примеру: //------------------------------------------------------------------------------------------- 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[i]=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);
|
|
|
|
|
Oct 24 2007, 07:54
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Athlon128 @ Oct 24 2007, 09:21)  Буду благодарен за фрагмент исходника для слейвов с RS485 или хотябы словесное объяснение алгоритма. В глаза бросаются недостатки примененного в Вашей работе протокола. Например, префикс и постфикс могут совпадать с другими полями команды (кодом, адресом, аргументами); если они применяются для целей нахождения начала и конца команды, то в этом случае - это будет сделать затруднительно. Да, и проверка "правильности" приема пакета (например, с помощью контрольной суммы) - дело не последнее. Рекомендую ознакомится с тем, как это делают другие. Например, тут http://www.caxapa.ru/lib/wake/ И исходники для AVR приведены...
|
|
|
|
|
Oct 24 2007, 08:08
|
Участник

Группа: Участник
Сообщений: 43
Регистрация: 4-04-07
Пользователь №: 26 760

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

Группа: Участник
Сообщений: 43
Регистрация: 4-04-07
Пользователь №: 26 760

|
Пользую ModBus RTU (вернее ModBus RTU-подобный протокол ). Обычно поступаю следующим образом. В качестве мастера выступает комп, он формирует запросы, анализирует ответы, осуществляет мониторинг, пишет БД и т.д. Обмен информацией организую так: 1. Очищаю приемный и передаваемый буферы драйвера COM - порта; 2. Отправляю запрос слейв устройствам; 3. Делаю маленькую паузу; 4. Жду поступления в приемный буфер данных (проверяю число байт в буфере) 5. Как только в буфере появились байты осуществляю считывание, если данные не идут в течении определенного времени - вываливаюсь по TIMEOUT-у 6. Анализирую принятую инфу
|
|
|
|
|
Oct 24 2007, 09:32
|
Гуру
     
Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493

|
Цитата если данные не идут в течении определенного времени в этот момент играющий на втором WinDVD запросил очередную порцию фильма с винта, винда этим занялась и тут Цитата - вываливаюсь по TIMEOUT-у А Modbus - да фик с ним, с Modbusom
|
|
|
|
|
Oct 24 2007, 10:41
|
Участник

Группа: Участник
Сообщений: 43
Регистрация: 4-04-07
Пользователь №: 26 760

|
Нет, перед приемом пакета устанавливаю время, в течение которого я жду данные, если это время истекает, а данных нет, генерируется исключение, т.е. данных никаких не пришло. Далее расцениваю это как "модуль не ответил" и реагирую в зависимости от ситуации. Ну и повторюсь, что пользую ModBus RTU-подобный протокол, заточенный под мои задачи. А то, что "винда не real time" - это точно
|
|
|
|
|
Oct 24 2007, 11:02
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(prm @ Oct 24 2007, 14:41)  Нет, перед приемом пакета устанавливаю время, в течение которого я жду данные, если это время истекает, а данных нет, генерируется исключение, т.е. данных никаких не пришло. Далее расцениваю это как "модуль не ответил" и реагирую в зависимости от ситуации. Ну и повторюсь, что пользую ModBus RTU-подобный протокол, заточенный под мои задачи. А то, что "винда не real time" - это точно  Так, уже интересно. Вариантов может быть 2 более-менее разных. 1. При приеме очередного символа, таймаут довзводится. При истечении таймаута анализируется пакет, указатель приемного буфера на начало. 2. При приеме очередного символа, подсчитывается CRC16. Если СКС16==0 обрабатывается пакет, указатель приемного буфера на начало. Таймер таймаута используется для еще одной установки указателя приемного буфера на начало. Что за вариант используется у Вас ?
|
|
|
|
|
Oct 24 2007, 12:53
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(DASM @ Oct 24 2007, 16:35)  RS485 вообще программный уровень не стандартизирует. А с чем доводилось работать - было либо ASCII либо и то и то вместе. А еще чаще просто текстовые строки - любят юзера, чтобы в обычной терминалке можно было бы с прибором поговорить. Стандартизация есть для PLC полная. Под SCADы много прибамбасов для ModBus. Если в терминалке с прибором поговорить, то текстовые сообщения (это понятно). А если программа пишется для PC, типа прибора, то ModBus RTU. Если контроллеры объединяются в сеть, то ModBus RTU.
|
|
|
|
|
Oct 24 2007, 16:22
|
Участник

Группа: Участник
Сообщений: 31
Регистрация: 18-04-06
Пользователь №: 16 238

|
Пытался днём на бумаге прикинуть программу. В основном коде программы: Код while (rx_counter0==0); // ждём когда будет принят байт в буфер delay_ms(25); TCCR1B=0x05; // запускаем таймер (период 50мс) В прерывании по таймеру: Код interrupt [TIM1_COMPA] void timer1_compa_isr(void) { if (rx_counter0>0) // если буфер не пуст { while (getchar()!=':'); // считываем по байту пока не попадётся префикс ':' command=getchar(); // номер команды number=getchar(); // номер слейва if ((command==1)&&(number==number_temp)) // если была послана команда №1 для текущего слейва { PORTE.7=1; // переключаем max487 на выход delay_ms(1); printf(":%d online;",number_temp); // ответ PORTE.7=0; // переключаем max487 на вход } }
TCNT1H=0x00; // обнуляем таймер TCNT1L=0x00; // } Мастер шлёт команды всем по очереди слейвам с периодом 100мс тоже по таймеру. Идея такая: в момент включения ждём хотябы 1 байт и через 25мс (чтобы обеспечить смещение во время которого смогут быть приняты следующие команды мастера) запускаем таймер (50мс). Далее каждые 50мс: ищем в буфере префикс ":", читаем № команды и id слейва в команде и отвечаем если команда адресована данному слейву. Вот такая задумка была. На деле отвечает только слейв, которому была адресована 1я команда Завтра попробую другой подход  Пошёл читать доки
Сообщение отредактировал Athlon128 - Oct 24 2007, 16:38
|
|
|
|
|
Oct 24 2007, 16:36
|
Cундук
    
Группа: Участник
Сообщений: 1 478
Регистрация: 13-11-06
Из: Ростов-на-Дону
Пользователь №: 22 269

|
Цитата(Athlon128 @ Oct 24 2007, 20:22)  Пытался днём на бумаге прикинуть программу. ... Завтра попробую другой подход  Я одного не пойму. Зачем изобретать велосипед там, где это давно уже сделано? Есть хороший стандарт MODBUS. Задача проста - ознакомиться с документами и сделать так, как там написано. Все преимущества такого подхода справедливо отметил alexander55. Если нужны бОльшие скорости - для этого существует MODBUS over TCP/IP, что тоже достаточно легко реализуемо в настоящее время. В качестве бонуса - полнейшая совместимость с туевой хучей девайсов. От себя могу добавить, что изобретать что либо в области RS485-строения в настоящее время уже просто неприлично.
|
|
|
|
|
Oct 24 2007, 18:18
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(Прохожий @ Oct 24 2007, 20:36)  От себя могу добавить, что изобретать что либо в области RS485-строения в настоящее время уже просто неприлично. Добавлю, что для хороших протоколов существуют картинки алгоритмов для мастера и для слэйва с указанием все возможных состояний и переходов. Без опыта лучше не изобретать. Или изобретать, только изучив подобные картинки. Цитата(DASM @ Oct 24 2007, 16:35)  RS485 вообще программный уровень не стандартизирует. А с чем доводилось работать - было либо ASCII либо и то и то вместе. А еще чаще просто текстовые строки - любят юзера, чтобы в обычной терминалке можно было бы с прибором поговорить. Хм, меня юзером назвали! Люблю в терминалке и поговорить, и послушать. А уж лог-файл вообще автоматом получается.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Oct 25 2007, 01:01
|
Участник

Группа: Участник
Сообщений: 31
Регистрация: 18-04-06
Пользователь №: 16 238

|
Ладно, всем спасибо, буду читать про modbus
Сообщение отредактировал Athlon128 - Oct 25 2007, 01:07
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|