Помогоите найти ошибку [RS485 Modbus] IAR
Помогоите найти ошибку [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)) );
};
};
}
Помогите разобраться с общением устройств по 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)) );
};
};
}
Re: Помогоите найти ошибку [RS485 Modbus] IAR
Два вопроса.
Кто вас этому учит? Откуда такой пример?
Кто вас этому учит? Откуда такой пример?
Код: Выделить всё
__interrupt void RX_compl (void)
{
asm("cli");
rx_buffer[count++]=UDR;
asm("sei");
}Re: Помогоите найти ошибку [RS485 Modbus] IAR
1. volatile unsigned char count =0;
2.
3. После переключений RX / TX нужно обязательно давать задержку с отключением прерываний приёма/передачи. 2 ms для 38400 будет нормально.
дальше не смотрел
2.
Код: Выделить всё
__interrupt void RX_compl (void)
{
char b = UDR; //очень полезно. в ДШ про это хорошо сказано
if ( count < sizeof( rx_buffer ) ) { rx_buffer[ count++ ] = b; }
}
3. После переключений RX / TX нужно обязательно давать задержку с отключением прерываний приёма/передачи. 2 ms для 38400 будет нормально.
дальше не смотрел
Re: Помогоите найти ошибку [RS485 Modbus] IAR
Здравствуйте asteroid7 ! Спасибо что откликнулись.
Извеняюсь, я случайно не тот кусок кода всунул, просто уже глаза на лоб вылезли
Вот кусок, где я по приему 8-ми байт - выдаю в линию принятых 8-мь байт, т.е. типа эхо... В AVRStudio вродь как отладка идет верно - использую режим отладки AVRSim&Proteus, т.е. когда я через вирт. терминал шлю контроллеру 8 байт - он эхом шлет все назад. Вот в живую (rs485) передача начинается после 2-го принятого байта (см. на осцилографе).
CPU=mega8, Clk=8Mhz без предделителя, baundrate=38400
Заранее спасибо!!!!
Извеняюсь, я случайно не тот кусок кода всунул, просто уже глаза на лоб вылезли
Вот кусок, где я по приему 8-ми байт - выдаю в линию принятых 8-мь байт, т.е. типа эхо... В AVRStudio вродь как отладка идет верно - использую режим отладки AVRSim&Proteus, т.е. когда я через вирт. терминал шлю контроллеру 8 байт - он эхом шлет все назад. Вот в живую (rs485) передача начинается после 2-го принятого байта (см. на осцилографе).
Код: Выделить всё
#include "iom8.h"
#include "intrinsics.h"
#define Byte unsigned char
#define Word unsigned char
#define Long unsigned long
#define cMaxBufferSize 8
Byte aUartBuffer[cMaxBufferSize];
Word wIndexUart;
#define RE PORTD_Bit2
#define RXE RE=0
#define TXE RE=1
#define RX (UCSRB = (1<<RXEN)|(0<<TXEN)|(1<<RXCIE)|(0<<UDRIE)|(0<<TXCIE))
#define TX (UCSRB = (0<<RXEN)|(1<<TXEN)|(0<<RXCIE)|(1<<UDRIE)|(1<<TXCIE))
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)) );
}
#pragma vector = USART_RXC_vect
__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
Заранее спасибо!!!!
Re: Помогоите найти ошибку [RS485 Modbus] IAR
"есть некое устройство (мастер)"
Так про мастера ничего и не сказали. Это важно. Протеус идёт лесом.
РС? Win?
Если да, да, то задержку от/до реакции РС нужно закладывать минимум 16 ms. Лучше 20.
Задержка переключения приём/передача минимум 1,5 байта от скорости + переходные процессы в линии. Выше значение привёл.
Так про мастера ничего и не сказали. Это важно. Протеус идёт лесом.
РС? Win?
Если да, да, то задержку от/до реакции РС нужно закладывать минимум 16 ms. Лучше 20.
Задержка переключения приём/передача минимум 1,5 байта от скорости + переходные процессы в линии. Выше значение привёл.
Код: Выделить всё
#define QUARZ_FREQUENCY_HZ 8000000ul
//U32 == unsigned long
#define TIC_NS ((U32)(1000000000ul / QUARZ_FREQUENCY_HZ))
__intrinsic void __delay_cycles(U32);
#define DELAY_MS(ms) ( __delay_cycles( ( (U32)ms * 1000000ul) / TIC_NS ) ) /* MAX! 4294 */
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. Фьюзы проверил - все совпадает с даташитом.
Помогите мне по возможности, я сам не осилю задачу. Заранее Вам спасибо!!!!!!
Proteus для отладки не использую, в AVRStudio есть возможность вести отладку в паре с Proteus (подстегивает его dll) - из него только виртуальный терминал нужен, -ну, чтоб передать 8 байт, далее все по регистрам смотрю - вродь как выше указаный код работает как надо. Хотя, мне как начинающему мучителю МК -он помог здорово....
В живую, если не использую передачу - в программе закомтил передачу, поставил флаг по принятию 8-ми байт - на осцилограмме вродь как попадаю в конец 8-го байта от мастера, с передачей (с ответом) на осцилографе вижу, что после 1-го байта от мастера у меня врубается на передачу.... ...ля, уже упарился....
Свой дэвайс собрал на меге8, клок 8МГц, драйвер 485 - МАХ485, где RE-DE объединил - управляю 2-м пином порта D. Фьюзы проверил - все совпадает с даташитом.
Помогите мне по возможности, я сам не осилю задачу. Заранее Вам спасибо!!!!!!
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, режим -асинхроный...
Да, кстати, прием идет уверено от мастера, - сужу по анализу принятых данных: если адрес = адресу моего устр. начинаю передачу... - условие выполняется!!! менял адрес своего устр. - передача обрубалась!
И еше раз БОЛЬШОЕ СПАСИБО ЗА ПОМОЩЬ И УЧАСТИЕ!!!!!!!
Вродь как получилось!!!, - передача идет как надо, т.е. после приема 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, режим -асинхроный...
Да, кстати, прием идет уверено от мастера, - сужу по анализу принятых данных: если адрес = адресу моего устр. начинаю передачу... - условие выполняется!!! менял адрес своего устр. - передача обрубалась!
И еше раз БОЛЬШОЕ СПАСИБО ЗА ПОМОЩЬ И УЧАСТИЕ!!!!!!!
Re: Помогоите найти ошибку [RS485 Modbus] IAR
Visitor писал(а): Вопрос: - как программно корректировать скорость UART-а??!! Есть ли такая возможность?
Да очень просто - константой, записываемой в UBRR . В ДШ подробно расписано.
Re: Помогоите найти ошибку [RS485 Modbus] IAR
С огнём играете. Микросекунды не для RS485. Линия удлинится, другим проводом проложат... ох и нахватаетесь соплей... Приводите задержки к миллисекундам!Visitor писал(а):... т.е. разница в 16us!
Именно поэтому убрал из макросов две строки
Код: Выделить всё
#define DELAY_NS(ns) ( __delay_cycles( (U32)ns / TIC_NS ) )
#define DELAY_US(us) ( __delay_cycles( ( (U32)us * 1000ul) / TIC_NS ) ) //MAX! 4294967
Скорость рекомендуется менять при полной остановке UART-а. UCSRхB = 0; Потом перезапустить.
Rfast - удвоенная скорость. Для Вашей задачи не нужна. См. ДШ таблица 62, где бит U2X = 0.
Re: Помогоите найти ошибку [RS485 Modbus] IAR
Здравствуйте уважаемые!
Все работает - прием и передача идет как надо (по осцилографу), мастер шлет 8 байт - слэйв видя свой адрес отвечает, но облом теперь возник в другом месте - в протоколе обмена. Разработчик явно сунул что-то не то. Ну да ладно, разбирусь потихоньку, - есть идея заллогировать обмен в 24С16.
В мастере к стати, стоит кварц на 7.32МГц в слэйве -8МГц, думаю в этом причина разницы в 16мкс.
2 Jack_A: Ну это ясно, я имел ввиду, что еще кроме этого меняет скорость UART-а (ну, разве еще кроме смены квартца)?!!
2 asteroid7: Да вродь как работает, линию более чем на 10м удлинять не будем, пока,
В мертвом слэйве то же установлен квартц на 8МГц, да и мне с 8МГц-ми таймер удобнее настраивать, - далее еще RFID должен подстегнуть к слэйву для полноты счастья
И все же, разница в 16мкс немного напрягает, возможно у дохлого слэйва тоже длительность на 16мкс была больше, но вопрос все тот же: -Как программно подгонять скорость\длит. посылки UART-а??? Есть ли такая возможность?!
И еще просьба, поделитесь, плиз, библиотекой I2C (24C16) под 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 или примером?!!!
Всем спасибо за внимание!!!!!
Последний раз редактировалось Visitor Пн апр 18, 2011 11:50:18, всего редактировалось 1 раз.
Re: Помогоите найти ошибку [RS485 Modbus] IAR
Visitor писал(а):вопрос все тот же: -Как программно подгонять скорость\длит. посылки UART-а???
Блажь это. UART'ы, настроенные на одну скорость обмена с нормальной кварцевой стабилизацией ни в какой "подгонке" или любой другой "доработке напильником по месту" не нуждаются.
- urry
- Сверлит текстолит когтями
- Сообщения: 1262
- Зарегистрирован: Пн дек 08, 2008 10:58:48
- Откуда: Винница
- Контактная информация:
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
Считаем по формуле
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
Re: Помогоите найти ошибку [RS485 Modbus] IAR
Всем привет!
Вот настройка скорости по даташиту: UBRRH=0x00; UBRRL=0x0C (12); - Кварц -8МГц, прописал жестко, без вычислений.... Работает! При UBRRL=0x0В (11) - не работает! (по даташиту - это для кварца 7.32);
- Уважаемые, думаю вопрос по данному пункту можно снять, - всем спасибо!!!!
Сейчас мое внимание переключилось на протокол обмена между мастером и слэйвом (слэйв -у разработчиков выпросили на время, якобы начальству показать, мол в дальнейшем купим с его санкции). С данной фирмой у нас заложено много проектов в плане закупки ихнего оборудования, гады, могли бы хоть протокол обмена дать правильный!
По протоколу есть две мысли:
-1-я записать все из линии 485-го во внешнюю еепром (есть в наличии 24с16)
-2-я мысля - записать все на комп.
Больше склоняюсь к первому варианту, опыт с внеш. еепромкой может в дальнейшем пригодится!
Уважаемые, у меня к Вам вопрос: есть ли у кого готовая библиотека I2C(TWI) под IAR для 24Сххх - мною скачанные из нета, как-то незаработали с еепромкой, - ну здесь вероятнее всего я что-то не так делаю, либо лыжи не едут

Всем еще раз спасибо большое!!!
Вот настройка скорости по даташиту: UBRRH=0x00; UBRRL=0x0C (12); - Кварц -8МГц, прописал жестко, без вычислений.... Работает! При UBRRL=0x0В (11) - не работает! (по даташиту - это для кварца 7.32);
- Уважаемые, думаю вопрос по данному пункту можно снять, - всем спасибо!!!!
Сейчас мое внимание переключилось на протокол обмена между мастером и слэйвом (слэйв -у разработчиков выпросили на время, якобы начальству показать, мол в дальнейшем купим с его санкции). С данной фирмой у нас заложено много проектов в плане закупки ихнего оборудования, гады, могли бы хоть протокол обмена дать правильный!
По протоколу есть две мысли:
-1-я записать все из линии 485-го во внешнюю еепром (есть в наличии 24с16)
-2-я мысля - записать все на комп.
Больше склоняюсь к первому варианту, опыт с внеш. еепромкой может в дальнейшем пригодится!
Уважаемые, у меня к Вам вопрос: есть ли у кого готовая библиотека I2C(TWI) под IAR для 24Сххх - мною скачанные из нета, как-то незаработали с еепромкой, - ну здесь вероятнее всего я что-то не так делаю, либо лыжи не едут
Всем еще раз спасибо большое!!!