Как это по нашемуПо freemodbus есть справка, правда я не могу в ней разобраться
FreeModbus + AVR
- Реклама
- Сообщения: 10
- Зарегистрирован: Пн июл 02, 2012 18:05:02
Спасибо, я разобрался только что )))
Есть массив usRegHoldingBuf[], там всё и хранится. Ответ был на поверхности
Есть массив usRegHoldingBuf[], там всё и хранится. Ответ был на поверхности
Вообще, Modbus - очень древний протокол и далеко не лучший. Другое дело, что он является стандартом для многого промышленного оборудования. Но его принцип - отображение адресного пространства регистров - очень неудобен. Поэтому применяю его только тогда, когда требует заказчик. В других случаях использую Wake, который сделал как замену Modbus-у. В протоколе Wake вместо регистров используются команды, т.е. некие функции с набором параметров. Это намного проще в использовании. Что касается Modbus, то я просто эмулировал массиы Coils и Registers:
Код: Выделить всё
//----------------------------------------------------------------------------
//------- Эта секция программы эмулирует массив регистров для Modbus: --------
//----------------------------------------------------------------------------
//------------------ Эмуляция массива COILS на запись: -----------------------
bool ForceCoil(unsigned int addr, unsigned int word)
{
if(word == 0xFF00)
return(Regs_SetCoil(addr, 1));
if(word == 0x0000)
return(Regs_SetCoil(addr, 0));
return(0);
}
//------------------ Эмуляция массива COILS на чтение: -----------------------
bool ReadCoil(unsigned int addr, bool *bit)
{
return(Regs_GetCoil(addr, bit)); //чтение реле
}
//------------------ Эмуляция массива INPUTS на чтение: ----------------------
bool ReadInput(unsigned int addr, bool *bit)
{
return(Regs_GetInput(addr, bit)); //нет INPUTS
}
//------------- Эмуляция массива INPUT REGISTERS на чтение: ------------------
bool ReadIReg(unsigned int addr, unsigned int *word)
{
if(addr < 4)
{
*word = Adc_Get(addr); //чтение ADC1..ADC4
return(1);
}
switch(addr)
{
case 5: *word = Regs_Get(); break; //чтение SW
case 6: *word = Step_GetIc(); break; //Ic
case 7: *word = Step_GetAc(); break; //Ac
case 8: *word = Step_GetVc(); break; //Vc
case 9: *word = Control_GetLims(); break; //чтение LIM
case 10: *word = Control_GetCtrs(); break; //чтение CONTROLS
case 11: *word = Control_GetStat(); break; //состояние
default: return(0);
}
return(1);
}
//------------ Эмуляция массива HOLDING REGISTERS на чтение: -----------------
bool ReadHReg(unsigned int addr, unsigned int *word)
{
switch(addr)
{
case 1: *word = Step_GetFM(); break; //FM
case 2: *word = Step_GetIh(); break; //Ih
case 3: *word = Step_GetIa(); break; //Ia
case 4: *word = Step_GetIw(); break; //Iw
case 5: *word = Step_GetAw(); break; //Aw
case 6: *word = Step_GetVm(); break; //Vm
case 7: *word = Step_GetVw(); break; //Vw
default: return(0);
}
return(1);
}
//------------ Эмуляция массива HOLDING REGISTERS на запись: -----------------
bool PresetHReg(unsigned int addr, unsigned int word)
{
switch(addr)
{
case 1: Step_SetFM(word); break; //FM
case 2: Step_SetIh(word); break; //Ih
case 3: Step_SetIa(word); break; //Ia
case 4: Step_SetIw(word); break; //Iw
case 5: Step_SetAw(word); break; //Aw
case 6: Step_SetVm(word); break; //Vm
case 7: Step_SetVw(word); break; //Vw
default: return(0);
}
return(1);
}
//----------------------------------------------------------------------------
- Сообщения: 214
- Зарегистрирован: Чт май 23, 2013 18:31:58
Доброго времени суток! Не получается запустить freemodbus на мк atmega16. Два дня уже просидел. Вроде бы все проверил. Все компилируется через makefile в корневой папке. Редактирую код в VS Code на виндоусе. В makefile изменил пути до avr-gcc, avrdude, avr-objcopy. Частоту df-cpu=8000000ul выставил. Фьюзы прошил на внешний кварц 8Мгц, на плате отладочное реле, щелкает раз в сек, как положено. В файле port.h выставил конфиги портов для управления приема/передачей max485. Не знаю что еще настроить нужно. Для тестирования использую софт Termite. Отправляю на 10 адрес, 1, 3, 7 функции. Везде в ответе таймаут. Через лог анализатор проверил, данные только отправляются из компа и все. Может быть я опрос не так делаю с компа.

main.c
main.c
Спойлер
Код: Выделить всё
/* ----------------------- AVR includes -------------------------------------*/
#include "avr/io.h"
#include "avr/interrupt.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"
/* ----------------------- Defines ------------------------------------------*/
#define REG_INPUT_START 1000
#define REG_INPUT_NREGS 4
/* ----------------------- Static variables ---------------------------------*/
static USHORT usRegInputStart = REG_INPUT_START;
static USHORT usRegInputBuf[REG_INPUT_NREGS];
#define REG_HOLDING_START 1200
#define REG_HOLDING_NREGS 99
static USHORT usRegHoldingStart = REG_HOLDING_START;
static USHORT usRegHoldingBuf[REG_HOLDING_NREGS];
#define REG_COILS_START 1100
#define REG_COILS_SIZE 16
static unsigned char ucRegCoilsBuf[REG_COILS_SIZE / 8];
/* ----------------------- Start implementation -----------------------------*/
int
main( void )
{
const UCHAR ucSlaveID[] = { 0xAA, 0xBB, 0xCC };
eMBErrorCode eStatus;
eStatus = eMBInit( MB_RTU, 0x0A, 0, 38400, MB_PAR_EVEN );
eStatus = eMBSetSlaveID( 0x34, TRUE, ucSlaveID, 3 );
sei( );
/* Enable the Modbus Protocol Stack. */
eStatus = eMBEnable( );
for( ;; )
{
( void )eMBPoll( );
/* Here we simply count the number of poll cycles. */
usRegInputBuf[0]++;
}
}
eMBErrorCode
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
eMBErrorCode eStatus = MB_ENOERR;
int iRegIndex;
if( ( usAddress >= REG_INPUT_START )
&& ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
{
iRegIndex = ( int )( usAddress - usRegInputStart );
while( usNRegs > 0 )
{
*pucRegBuffer++ =
( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
*pucRegBuffer++ =
( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
iRegIndex++;
usNRegs--;
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
eMBErrorCode
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs,
eMBRegisterMode eMode )
{
eMBErrorCode eStatus = MB_ENOERR;
int iRegIndex;
if( ( usAddress >= REG_HOLDING_START ) &&
( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) )
{
iRegIndex = ( int )( usAddress - usRegHoldingStart );
switch ( eMode )
{
/* Pass current register values to the protocol stack. */
case MB_REG_READ:
while( usNRegs > 0 )
{
*pucRegBuffer++ = ( UCHAR ) ( usRegHoldingBuf[iRegIndex] >> 8 );
*pucRegBuffer++ = ( UCHAR ) ( usRegHoldingBuf[iRegIndex] & 0xFF );
iRegIndex++;
usNRegs--;
}
break;
/* Update current register values with new values from the
* protocol stack. */
case MB_REG_WRITE:
while( usNRegs > 0 )
{
usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
iRegIndex++;
usNRegs--;
}
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
eMBRegisterMode eMode )
{
return MB_ENOREG;
}
eMBErrorCode
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
{
return MB_ENOREG;
}
- Сообщения: 214
- Зарегистрирован: Чт май 23, 2013 18:31:58
Наконецто разобрался на третий день. Начал двигаться по коду библиотеки, устанавливая щелкание релюшкой в непонятных местах, и потом дошел до проверки аддресса и внутри условия не защелкало. Оказалось в ПО термит установил вместо 0А значение 10. Думал что Dec надо.
Два дня ушло изза одного значения. Ну зато по библиотеке полазил не плохо, тоже хороший опыт. Осталось теперь разобраться как применять команды. Ну и со стороны компа заюзать библиотеку modbus. 
- Реклама

