Форум РадиоКот https://radiokot.ru/forum/ |
|
Помогоите найти ошибку [RS485 Modbus] IAR https://radiokot.ru/forum/viewtopic.php?f=20&t=46337 |
Страница 1 из 1 |
Автор: | Visitor [ Пн апр 11, 2011 16:39:30 ] |
Заголовок сообщения: | Помогоите найти ошибку [RS485 Modbus] IAR |
Всем добрый день Помогите разобраться с общением устройств по RS-485: - есть некое устройство (мастер), которое передает 8 байт (формат: №-устройства,команда,данные,контрол.сумма), следом ждет ответа от моего устройства (слэйв) в виде 8 байт. Написал код, где по циклу устройство(слэйв) ждет 8 байт, получив последний - передает принятые байты мастеру. Проблема в следующем: при передачи выясняется, что 1-й байт =0 (должен = 0х14) и да все последующие байты перекошены... Всем спасибо за внимание! Да, к стати, в Proteus-е логика отрабатывается как надо, а в живую не идет…. #include "iom8.h" #include "intrinsics.h" #define RE PORTD_Bit2 // MAX485 - вывод прием\передача #define RX (RE=(0<<RE), UCSRB = (1<<RXEN)|(0<<TXEN)|(1<<RXCIE)|(0<<UDRIE)|(0<<TXCIE)) #define TX (RE=(1<<RE), UCSRB = (0<<RXEN)|(1<<TXEN)|(0<<RXCIE)|(1<<UDRIE)|(1<<TXCIE)) define F_CPU 8000000// #define BAUD 38400 // скорость #define MYUBRR F_CPU/16/BAUD-1 // расчет static unsigned char rx_buffer[8]={0,0,0,0,0,0,0,0}; // буфер приема static unsigned char tx_buffer[8]={0,0,0,0,0,0,0,0}; // буфер передачи unsigned char count =0; // счетчик байтов //---------- UART на скор: 38400 формат: 8N1 ---------- void USART_Init( unsigned int ubrr) { UBRRH = (unsigned char)(ubrr>>8); UBRRL = (unsigned char)ubrr; UCSRB = (1<<RXEN)|(1<<TXEN);//|(1<<UDRIE); UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); } //---------- по приему----------------------------------------------- #pragma vector = USART_RXC_vect __interrupt void RX_compl (void) { asm("cli"); rx_buffer[count++]=UDR; asm("sei"); } int main() { USART_Init(MYUBRR); asm("sei") ; while(1) { count=0; RX; while(count<8); for(int i=0; i<8; i++) { tx_buffer[i]=rx_buffer[i];} count=0; TX; while(count<8) { while(!(UCSRA & (1<<UDRE))); UDR=tx_buffer[count++]; while ( !( UCSRA & (1<<TXCIE)) ); }; }; } |
Автор: | asteroid7 [ Пн апр 11, 2011 20:45:20 ] |
Заголовок сообщения: | Re: Помогоите найти ошибку [RS485 Modbus] IAR |
Два вопроса. Кто вас этому учит? Откуда такой пример? Код: __interrupt void RX_compl (void)
{ asm("cli"); rx_buffer[count++]=UDR; asm("sei"); } |
Автор: | asteroid7 [ Пн апр 11, 2011 20:54:45 ] |
Заголовок сообщения: | Re: Помогоите найти ошибку [RS485 Modbus] IAR |
1. volatile unsigned char count =0; 2. Код: __interrupt void RX_compl (void) { char b = UDR; //очень полезно. в ДШ про это хорошо сказано if ( count < sizeof( rx_buffer ) ) { rx_buffer[ count++ ] = b; } } 3. После переключений RX / TX нужно обязательно давать задержку с отключением прерываний приёма/передачи. 2 ms для 38400 будет нормально. дальше не смотрел |
Автор: | Visitor [ Ср апр 13, 2011 17:13:56 ] |
Заголовок сообщения: | Re: Помогоите найти ошибку [RS485 Modbus] IAR |
Здравствуйте asteroid7 ! Спасибо что откликнулись. Извеняюсь, я случайно не тот кусок кода всунул, просто уже глаза на лоб вылезли ![]() Вот кусок, где я по приему 8-ми байт - выдаю в линию принятых 8-мь байт, т.е. типа эхо... В AVRStudio вродь как отладка идет верно - использую режим отладки AVRSim&Proteus, т.е. когда я через вирт. терминал шлю контроллеру 8 байт - он эхом шлет все назад. Вот в живую (rs485) передача начинается после 2-го принятого байта (см. на осцилографе). Код: Byte aUartBuffer[cMaxBufferSize]; Word wIndexUart; volatile char RXcomplete=0; void InitUart(void) { wIndexUart = 0; PORTD = 0x07; DDRD = 0x06; UCSRB = 0x00; UCSRA = 0x00; /// выбр.ucsrc асинхр. 1-стоп формат 8-бит UCSRC=(1<<URSEL)|(0<<UMSEL)|(0<<USBS)|(0<<UCSZ2)|(1<<UCSZ1)|(1<<UCSZ0); UBRRH=0x00; UBRRL=0x0C; UCSRB = (1<<RXCIE) | (1<<TXCIE) | (0<<UDRIE) | (0<<RXEN) | (0<<TXEN); } void UartTxByte(Byte data) { while ( !(UCSRA & (1 << UDRE)) ); UCSRA |= (1 << TXC); UDR = data; while ( !(UCSRA & (1 << TXC)) ); } __interrupt void UartRxEnd(void) { Byte tempUDR = UDR; aUartBuffer[wIndexUart] = tempUDR; if (wIndexUart < cMaxBufferSize) wIndexUart++; if (wIndexUart == cMaxBufferSize) RXcomplete=1; } int main() { InitUart(); asm("sei"); while(1) { wIndexUart=0; RXcomplete=0; RXE; RX; __delay_cycles(? -сколько надо?!!); while(RXcomplete!=1); __delay_cycles(10); TXE; TX; __delay_cycles(?); for (char i=0; i<8;) { UartTxByte(aUartBuffer[i++]); } }; } CPU=mega8, Clk=8Mhz без предделителя, baundrate=38400 Заранее спасибо!!!! |
Автор: | asteroid7 [ Ср апр 13, 2011 20:38:34 ] |
Заголовок сообщения: | Re: Помогоите найти ошибку [RS485 Modbus] IAR |
"есть некое устройство (мастер)" Так про мастера ничего и не сказали. Это важно. Протеус идёт лесом. РС? Win? Если да, да, то задержку от/до реакции РС нужно закладывать минимум 16 ms. Лучше 20. Задержка переключения приём/передача минимум 1,5 байта от скорости + переходные процессы в линии. Выше значение привёл. Код: //U32 == unsigned long __intrinsic void __delay_cycles(U32); |
Автор: | Visitor [ Ср апр 13, 2011 23:54:16 ] |
Заголовок сообщения: | Re: Помогоите найти ошибку [RS485 Modbus] IAR |
Мастер выполнен на базе mega128, передает 8 байт (RS-485/MODBUS), далее ждет ответ (тоже 8 байт) от слэйва, если в течении 10мс ответа небыло - идет на повтор. Ранее это была СКД установленная для разгранечения доступа в помещение, к мастеру еще РС подстегивался (т.к. у меги128 два уарта), слэйв со временем сдох, и сдох капитально - контроллер там весь погорел. Со временем появилась надобность в СКД, вот мне и поручили это воскресить... Разработчики те еще гады - молчат, как партизаны на допросе ![]() ![]() Proteus для отладки не использую, в AVRStudio есть возможность вести отладку в паре с Proteus (подстегивает его dll) - из него только виртуальный терминал нужен, -ну, чтоб передать 8 байт, далее все по регистрам смотрю - вродь как выше указаный код работает как надо. Хотя, мне как начинающему мучителю МК -он помог здорово.... В живую, если не использую передачу - в программе закомтил передачу, поставил флаг по принятию 8-ми байт - на осцилограмме вродь как попадаю в конец 8-го байта от мастера, с передачей (с ответом) на осцилографе вижу, что после 1-го байта от мастера у меня врубается на передачу.... ...ля, уже упарился.... Свой дэвайс собрал на меге8, клок 8МГц, драйвер 485 - МАХ485, где RE-DE объединил - управляю 2-м пином порта D. Фьюзы проверил - все совпадает с даташитом. Помогите мне по возможности, я сам не осилю задачу. Заранее Вам спасибо!!!!!! |
Автор: | Visitor [ Чт апр 14, 2011 13:46:40 ] |
Заголовок сообщения: | Re: Помогоите найти ошибку [RS485 Modbus] IAR |
Добрый день! Вродь как получилось!!!, - передача идет как надо, т.е. после приема 8-го байта выдерживаю 300 us (кстати, спасиб за delay - я его переделал немного - из ms в us). НО, устройство [МАСТЕР] не воспринимает команды моего [СЛЭЙВ], заметил одну разницу, - по длительности 1 кадр от мастера = 264us, от слэйва - 280us, т.е. разница в 16us! Может в этом все дело??!! Вопрос: - как программно корректировать скорость UART-а??!! Есть ли такая возможность? В дата шите про расчет Rslow и Rfast - я так и не понял куда этот результат прикрутить, к чему он???!!! Настройка UCSRC: (1<<URSEL)|(0<<UMSEL)|(0<<UPM1)|(0<<UPM0)|(0<<USBS)|(0<<UCSZ2)|(1<<UCSZ1)|(1<<UCSZ0)|(0<<UCPOL) - если я не ошибаюсь - 8-N-1, режим -асинхроный... Да, кстати, прием идет уверено от мастера, - сужу по анализу принятых данных: если адрес = адресу моего устр. начинаю передачу... - условие выполняется!!! менял адрес своего устр. - передача обрубалась! И еше раз БОЛЬШОЕ СПАСИБО ЗА ПОМОЩЬ И УЧАСТИЕ!!!!!!! |
Автор: | Jack_A [ Чт апр 14, 2011 21:13:02 ] |
Заголовок сообщения: | Re: Помогоите найти ошибку [RS485 Modbus] IAR |
Visitor писал(а): Вопрос: - как программно корректировать скорость UART-а??!! Есть ли такая возможность? Да очень просто - константой, записываемой в UBRR . В ДШ подробно расписано. |
Автор: | asteroid7 [ Чт апр 14, 2011 22:12:12 ] |
Заголовок сообщения: | Re: Помогоите найти ошибку [RS485 Modbus] IAR |
Visitor писал(а): ... т.е. разница в 16us! С огнём играете. Микросекунды не для RS485. Линия удлинится, другим проводом проложат... ох и нахватаетесь соплей... Приводите задержки к миллисекундам!Именно поэтому убрал из макросов две строки ![]() Код: Скорость рекомендуется менять при полной остановке UART-а. UCSRхB = 0; Потом перезапустить. Rfast - удвоенная скорость. Для Вашей задачи не нужна. См. ДШ таблица 62, где бит U2X = 0. |
Автор: | Visitor [ Пн апр 18, 2011 06:46:54 ] |
Заголовок сообщения: | Re: Помогоите найти ошибку [RS485 Modbus] IAR |
Здравствуйте уважаемые! Все работает - прием и передача идет как надо (по осцилографу), мастер шлет 8 байт - слэйв видя свой адрес отвечает, но облом теперь возник в другом месте - в протоколе обмена. Разработчик явно сунул что-то не то. Ну да ладно, разбирусь потихоньку, - есть идея заллогировать обмен в 24С16. В мастере к стати, стоит кварц на 7.32МГц в слэйве -8МГц, думаю в этом причина разницы в 16мкс. Цитата: Да очень просто - константой, записываемой в UBRR . В ДШ подробно расписано. 2 Jack_A: Ну это ясно, я имел ввиду, что еще кроме этого меняет скорость UART-а (ну, разве еще кроме смены квартца)?!! 2 asteroid7: Да вродь как работает, линию более чем на 10м удлинять не будем, пока, ![]() В мертвом слэйве то же установлен квартц на 8МГц, да и мне с 8МГц-ми таймер удобнее настраивать, - далее еще RFID должен подстегнуть к слэйву для полноты счастья ![]() И все же, разница в 16мкс немного напрягает, возможно у дохлого слэйва тоже длительность на 16мкс была больше, но вопрос все тот же: -Как программно подгонять скорость\длит. посылки UART-а??? Есть ли такая возможность?! И еще просьба, поделитесь, плиз, библиотекой I2C (24C16) под IAR или примером?!!! Всем спасибо за внимание!!!!! |
Автор: | Jack_A [ Пн апр 18, 2011 10:47:19 ] |
Заголовок сообщения: | Re: Помогоите найти ошибку [RS485 Modbus] IAR |
Visitor писал(а): вопрос все тот же: -Как программно подгонять скорость\длит. посылки UART-а??? Блажь это. UART'ы, настроенные на одну скорость обмена с нормальной кварцевой стабилизацией ни в какой "подгонке" или любой другой "доработке напильником по месту" не нуждаются. |
Автор: | urry [ Пн апр 18, 2011 11:31:36 ] |
Заголовок сообщения: | Re: Помогоите найти ошибку [RS485 Modbus] IAR |
ну как бы вставлю свои 5 копеек - по поводу целочисленного округления и кварца на 7.32 мегагерца Считаем по формуле define F_CPU 7320000// #define BAUD 38400 // скорость #define BAUD_05 38400/2 // для коррекции ошибки целочисленного деления ---------- старая формула #define MYUBRR F_CPU/16/BAUD -1 11.91 -1 - целочисленное округление забирает .91 и получается 11,хотя точнее было бы 12. Изменяем формулу #define MYUBRR (F_CPU/16+BAUD_05)/BAUD -1 добавляем половину делителя получаем 12.41, отбрасываем дробь, получаем 12 - 1 |
Автор: | Visitor [ Пн апр 18, 2011 14:02:12 ] |
Заголовок сообщения: | Re: Помогоите найти ошибку [RS485 Modbus] IAR |
Всем привет! Вот настройка скорости по даташиту: UBRRH=0x00; UBRRL=0x0C (12); - Кварц -8МГц, прописал жестко, без вычислений.... Работает! При UBRRL=0x0В (11) - не работает! (по даташиту - это для кварца 7.32); - Уважаемые, думаю вопрос по данному пункту можно снять, - всем спасибо!!!! Сейчас мое внимание переключилось на протокол обмена между мастером и слэйвом (слэйв -у разработчиков выпросили на время, якобы начальству показать, мол в дальнейшем купим с его санкции). С данной фирмой у нас заложено много проектов в плане закупки ихнего оборудования, гады, могли бы хоть протокол обмена дать правильный! По протоколу есть две мысли: -1-я записать все из линии 485-го во внешнюю еепром (есть в наличии 24с16) -2-я мысля - записать все на комп. Больше склоняюсь к первому варианту, опыт с внеш. еепромкой может в дальнейшем пригодится! Уважаемые, у меня к Вам вопрос: есть ли у кого готовая библиотека I2C(TWI) под IAR для 24Сххх - мною скачанные из нета, как-то незаработали с еепромкой, - ну здесь вероятнее всего я что-то не так делаю, либо лыжи не едут ![]() ![]() ![]() Всем еще раз спасибо большое!!! |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |