Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
09.02.2010, 22:40
|
|
Частый гость
Регистрация: 22.07.2007
Сообщений: 21
Сказал спасибо: 1
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Modbus RTU
Здравствуйте! Кто может помочь с примером рабочей программой с использованием Modbus RTU для AVR на языке С желательно адаптированной для AVR Studio . Заранее благодарен.
|
|
|
|
10.02.2010, 19:19
|
|
Гражданин KAZUS.RU
Регистрация: 13.06.2005
Адрес: РК г.Павлодар
Сообщений: 866
Сказал спасибо: 99
Сказали Спасибо 216 раз(а) в 140 сообщении(ях)
|
Re: Modbus RTU
UART поможет плюс расчет CRC(а сети куча примеров CRC)
__________________
Не ошибается лишь тот, кто ни чего не делает!
|
|
|
|
10.02.2010, 20:38
|
|
Частый гость
Регистрация: 22.07.2007
Сообщений: 21
Сказал спасибо: 1
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Modbus RTU
Да с CRC проблем нет, а как отследить в UART 3,5 бита
|
|
|
|
10.02.2010, 20:40
|
|
Почётный гражданин KAZUS.RU
Регистрация: 10.12.2007
Адрес: Екатеринбург
Сообщений: 2,729
Сказал спасибо: 2,435
Сказали Спасибо 893 раз(а) в 580 сообщении(ях)
|
Re: Modbus RTU
Таймером.Запускать по каждому импульсу.
|
|
|
|
11.02.2010, 00:36
|
|
Прохожий
Регистрация: 19.11.2006
Сообщений: 7
Сказал спасибо: 0
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Modbus RTU
// Расчет контрольной суммы для MODBUS протокола
//---------------------------------------------------------------------------
unsigned int CRC16Total(volatile unsigned char *pBuffer, unsigned int usBufferSize)
{
unsigned int usResult = 0xFFFF;
unsigned int j;
unsigned char i;
for(j = 0; j ‹ usBufferSize; j++)
{
usResult = usResult ^ pBuffer[j];
for(i = 0; i ‹ 8; i++)
{
if((usResult & 0x01) == 0x01)
{
usResult = usResult ›› 1;
usResult = usResult ^ 0xA001;
}
else
usResult = usResult ›› 1;
}
}
return usResult;
}
|
|
|
|
11.02.2010, 00:39
|
|
Прохожий
Регистрация: 19.11.2006
Сообщений: 7
Сказал спасибо: 0
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Modbus RTU
Кусок из реального живого проекта под PIC18
// Проверка диапазона и формирование выходного пакета данных
//--------------------------------------------------------------------------------------
unsigned char move_read (unsigned char *ptr, unsigned short size, unsigned short addr)
{
unsigned char i,j;
addr = (addr-1)*2;
if(offset ›= addr) //
if((offset+nbyte)‹= (addr + size)) // запрос настроек ПИН
{
out_buf[2]=nbyte;
offset = offset-addr;
for(i=0;i‹nbyte;i++)
{
if(i&1) // в MODBUS старший байт идет первым в пакете
j=i-1;
else
j=i+1;
out_buf[j+3]=*(ptr+offset+i);
}
tx_len = nbyte + 5;
return (1);
}
return(0);
}
// Проверка диапазона, сохранение принятых данных и формирование выходного пакета отчета
//------------------------------------------------------------------------------------------
unsigned char move_write (unsigned char *ptr, unsigned short size, unsigned short addr)
{
unsigned char i,j;
addr = (addr-1)*2;
if(offset ›= addr)
if((offset+nbyte)‹= (addr+ size)) // запись
{
offset = offset-addr;
for(i=0;i‹nbyte;i++)
{
if(i&1) // в MODBUS старший байт идет первым в пакете
j=i-1;
else
j=i+1;
*(ptr+offset+i)=in_buf[j+7];
}
for(i=2;i‹6;i++)
out_buf[i]=in_buf[i]; // формируем ответное сообщение
tx_len=8;
return (1);
}
return(0);
}
//------------------------------- Основной цикл ------------------------------------
void main(void)
{
unsigned int tmp,tmp2,n;
unsigned char i;
Init();
while (1)
{
CLRWDT();
led_control();
in_main_cycle (); // операции которые должны повторяться
if (tmr_check_rs232==0)
{
tmr_check_rs232 = 5; // 5 мс
if (flg.rx_pack)
{
flg.rx_pack=0;
rx_len= nrx;
nrx=0;
}
if (rx_len ›=5) // если длина достаточна
{
in.crc = CRC16Total(in_buf,(rx_len-2));
if ((in.crcbyte[0]==in_buf[rx_len-2])&&(in.crcbyte[1]==in_buf[rx_len-1])) // если CRC совпала
if (in_buf[0]==1) // если адрес совпал
{
out_buf[0]=1;
out_buf[1]=in_buf[1];
if (in_buf[1]==4)
in_buf[1]=3;
switch (in_buf[1]) // проверка типа функции
{
case 3: // чтение данных
offset=(in_buf[2]*256+in_buf[3])*2;
nbyte=in_buf[5]*2;
if ((in_buf[4]==0)&&(in_buf[5] ‹= DATA_MAX_LEN)) // читать не более 240 байт за 1 раз
{
if (move_read ((unsigned char *)&VarData, sizeof(VarData), ADDR_VarData))
break;
if (move_read ((unsigned char *)&State, sizeof(State), ADDR_State))
break;
/*
if (move_read ((unsigned char *)&Set, sizeof(Set), ADDR_Set))
break;
*/
if (move_read ((unsigned char *)&pu_const[0][0], sizeof(pu_const), ADDR_PuConst))
break;
if (move_read ((unsigned char *)PuComm, sizeof(PuComm), ADDR_PuComm))
break;
if (move_read ((unsigned char *)&Control[0], sizeof(Control), ADDR_Contr))
break;
if (move_read ((unsigned char *)&Rxbuf_eedata[0], sizeof(Rxbuf_eedata), ADDR_ReadSet))
{
Rxbuf_eedata[0] = Rxbuf_eedata[0]&0xf0; // Rxbuf_eedata.code = 0; // сбросить флаг получения ответа
break;
}
if (move_read ((unsigned char *)&Txbuf_eedata[0], sizeof(Txbuf_eedata), ADDR_WriteSet))
break;
}
out_buf[1]=in_buf[1]|0x80;
out_buf[2]=2; // код ошибки - адрес или количество не поддерживается
tx_len=5;
break;
case 16: // запись данных
offset=(in_buf[2]*256+in_buf[3])*2;
nbyte=in_buf[5]*2;
if ((in_buf[4]==0)&&(in_buf[5] ‹= DATA_MAX_LEN)) // писать не более 240 байт за 1 раз
{
/*
if(move_write ((unsigned char *)&Set, sizeof(Set), ADDR_Set))
{
n=sizeof(Set); // число байт настроек
for(i=0; i‹ n ;i++)
{
tmp=*((unsigned char *) &Set+i); // полученные настройки
tmp2 = eeprom_read(SETUP_EEADR + i); // сохраненная в EEPROM версия настроек
if(tmp!=tmp2) // если отличаются, обновить
write_eeprom (SETUP_EEADR +i,tmp);
}
break;
}
*/
if (move_write ((unsigned char *)&Txbuf_eedata[0], sizeof(Txbuf_eedata), ADDR_WriteSet))
{
Rxbuf_eedata[0] = Rxbuf_eedata[0]&0xf0; // Rxbuf_eedata.code = 0; // сбросить флаг получения ответа
break;
}
if(move_write ((unsigned char *)&Set.password, sizeof(Set.password), ADDR_Write_Password))
{
n=sizeof(Set.password); // число байт
for(i=0; i‹ n ;i++)
{
tmp=*((unsigned char *) &Set.password+i); // полученные настройки
tmp2 = eeprom_read(PASSW_EEADR + i); // сохраненная в EEPROM версия настроек
if(tmp!=tmp2) // если отличаются, обновить
write_eeprom (PASSW_EEADR +i,tmp);
}
break;
}
if (move_write ((unsigned char *)&WritePassw, sizeof(WritePassw), ADDR_CheckPassw))
{
if(cnt_err_psw ‹3) // если прием пароля не заблокирован 3 неверными попытками
{
if(WritePassw == Set.password) // если принятый пароль совпал с заданным в ПИН
{
cnt_wrt = 1; // разрешить однократную запись в ПИН
cnt_err_psw = 0; // сбросить счетчик неудачных попыток передачи пароля
}
else
cnt_err_psw ++; // инкремент счетчика ошибок пароля
}
break;
}
if(cnt_wrt) // если разрешена запись в переменные ПИН
{
if (move_write ((unsigned char *)PuComm, sizeof(PuComm), ADDR_PuComm))
{
cnt_wrt--;
break;
}
if (move_write ((unsigned char *)&Control[0], sizeof(Control), ADDR_Contr))
{
cnt_wrt--;
break;
}
}
}
out_buf[1]=in_buf[1]|0x80;
out_buf[2]=2; // код ошибки - адрес или количество не поддерживается
tx_len=5;
break;
default: // функция не поддерживается
out_buf[1]=in_buf[1]|0x80;
out_buf[2]=1; // код ошибки
tx_len=5;
break;
}
out.crc=CRC16Total(out_buf,(tx_len-2));
out_buf[tx_len-2]=out.crcbyte[0];
out_buf[tx_len-1]=out.crcbyte[1];
ntx = tx_len; // число передаваемых байт
T0CS=0; // Переход на тактирование от ядра - старт передачи данных
tmr_err_modbus = 0; // Сброс ошибки модбас (нет обмена более 1 мин)
State.Pin.err_modbus =0;
flg.rs232_red =0;
}
}
rx_len=0;
}
}
}
|
|
|
|
11.02.2010, 00:41
|
|
Прохожий
Регистрация: 19.11.2006
Сообщений: 7
Сказал спасибо: 0
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Modbus RTU
Ну и переменные имеющие к нему отношение
//--------------------------- программный UART для MODBUS -----------------------------------
volatile unsigned char nrx,ntx; // счетчик принятых, еще непереданных байт
volatile unsigned char rx_pack_timer; // счетчик межбайтн. интервала
volatile unsigned char rx_len,tx_len;
volatile unsigned short offset; // смещение первого читаемого байта
volatile unsigned char nbyte; // запрошенное количество байт
volatile unsigned char * ptr;
volatile unsigned char in_buf[RX_MAX_LEN]; // Входной буфер MODBUS
volatile unsigned char out_buf[TX_MAX_LEN]; // Выходной буфер MODBUS
volatile union
{
unsigned int crc; // контрольная сумма. Союз описан для удобного доступа к младшему и старшему байтам.
unsigned char crcbyte[2]; // crcbyte[0] - мл. байт, crcbyte[1] - ст. байт
} in,out;
|
|
|
|
11.02.2010, 13:09
|
|
Прохожий
Регистрация: 29.01.2010
Сообщений: 2
Сказал спасибо: 1
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Modbus RTU
есть бесплатные библиотеки, например http://freemodbus.berlios.de
|
|
|
|
12.02.2010, 11:37
|
|
Гражданин KAZUS.RU
Регистрация: 04.08.2006
Сообщений: 911
Сказал спасибо: 28
Сказали Спасибо 180 раз(а) в 139 сообщении(ях)
|
Re: Modbus RTU
Сообщение от CMP_SYS
|
Да с CRC проблем нет, а как отследить в UART 3,5 бита
|
Да не делает никто 3.5 бита. В AVR, придётся заводить прерывание на RxD. Иначе этого вообще никак не увидишь. Ну и под Виндой эта хрень не будет работать. Там менее 20мс сделать устойчивые задержки весьма затруднительно, если не сказать - невозможно.
Обычно делают 1.5 байта.
|
|
|
|
12.02.2010, 16:45
|
|
Прописка
Регистрация: 21.09.2009
Сообщений: 218
Сказал спасибо: 1
Сказали Спасибо 29 раз(а) в 27 сообщении(ях)
|
Re: Modbus RTU
Подправлю малёк, не 3.5 бита, а 3.5 байта, в смысле интервал
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Тема |
Автор |
Раздел |
Ответов |
Последнее сообщение |
управление по modbus
|
antibiotic0000 |
Микроконтроллеры, АЦП, память и т.д |
1 |
17.11.2009 13:23 |
Часовой пояс GMT +4, время: 13:53.
|
|