Обсуждаем контроллеры компании Atmel.
Ответить

Re: FreeModbus + AVR

Чт июл 05, 2012 21:34:50

По freemodbus есть справка, правда я не могу в ней разобраться

Как это по нашему :) Кавыряться в чём-то, не понимая в чём. Я бы может и помог, но я не понимаю в Си, ну и не нужно мне это. Если уж сильно припечёт, я напишу своё. Это очень часто быстрее, чем разбираться в чужом. Там в принципе не сложно. Так что дальше я пас.

Re: FreeModbus + AVR

Чт июл 05, 2012 21:44:53

Спасибо, я разобрался только что )))
Есть массив usRegHoldingBuf[], там всё и хранится. Ответ был на поверхности :)

Re: FreeModbus + AVR

Чт июл 05, 2012 23:09:59

Вообще, 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);
}

//----------

Re: FreeModbus + AVR

Пн сен 27, 2021 15:03:19

Доброго времени суток! Не получается запустить 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
Спойлер
Код:
/* ---------- 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;
}

Re: FreeModbus + AVR

Вт сен 28, 2021 10:29:51

Наконецто разобрался на третий день. Начал двигаться по коду библиотеки, устанавливая щелкание релюшкой в непонятных местах, и потом дошел до проверки аддресса и внутри условия не защелкало. Оказалось в ПО термит установил вместо 0А значение 10. Думал что Dec надо. :facepalm: Два дня ушло изза одного значения. Ну зато по библиотеке полазил не плохо, тоже хороший опыт. Осталось теперь разобраться как применять команды. Ну и со стороны компа заюзать библиотеку modbus. :tea:
Ответить