Fórum

arrow_back

logica do programa slave modbus

TALLES NEWTON DE CARVALHO

03/09/2022 11:04:47

bom dia, 


Estava analisando o programa mbslave_f01 do curso de modbus, e do que vi do programa, apesar de ter sido fixado atraves do switch case o startaddress em 1, percebi que quando coloca para iniciar o endereço em 2, o programa le novamente o byte do inicio. O que quero dizer é que se fixarmos um byte com o numero inicial 1 em decimal. e colocar no mpoll para ler a partir do endereço 1, vc vai ler o numero 1 no endereço 1, se modificarmos para o endereço 2, vc vai ler o numero 1 no endereço 2, isto não esta errado, não deveríamos estar fixo no endereço 2 como o numero 0 neste caso? o que o programa esta fazendo é um deslocamento do byte para iniciar a partir do endereço solicitado, mas o correto não era aquele endereço ser sempre fixo o valor do byte como se sempre iniciasse em 0?


para ser mais claro, se o master mandasse a seguinte msg


TX 0A 01 00 01 00 07 (CRC16)

RX 0A 01 01 01 (CRC16)


dai se mandassemos o proximo endereço 


TX 0A 01 00 02 00 06 (CRC16) //diminuindo a qtde de bits lidos para ser 06 pois nao teriamos mais bits, pois no exemplo temos apenas um byte de leitura


nao deveríamos receber 


RX 0A 01 01 00 (CRC16)? e caso quisesse ler 7 bits aumentando o endereço inicial, não deveria dar algum erro de estouro?


mas no caso do programa acabamos tendo a seguinte resposta


RX 0A 01 01 01 (CRC16)


o que demonstra que o byte apenas deslocou iniciando no novo endereço, o que nao deveria, pois se pensarmos esta variavel precisa ser fixa, caso seja a leitura de alguma porta, etc.


teria como passar uma modificação do programa para ler desta maneira?


FERNANDO SIMPLICIO DE SOUSA

03/09/2022 21:29:40

Olá Talles

Não há erros na biblioteca modbus, entretanto é necessário implementar a logica dos endereçamentos na função de callback no folha main(); Faz um teste para mim. Eu implementei duas funções da biblioteca FreeModbus que é utilizado no ESP32 e acredito que possa ser utilizada também no PIC. 

#include "lib/defs.h"
#include "lib/lcd.h"
#include "lib/mb_config.h"
#include "lib/mb_timer.h"
#include "lib/mb_serial.h"
#include 

void INTERRUPCAO() iv 0x0008 ics ICS_AUTO {
      uart_irq();
      timer_irq();
}

#define BITS_UCHAR      8U

UCHAR
xMBUtilGetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits )
{
    USHORT          usWordBuf;
    USHORT          usMask;
    USHORT          usByteOffset;
    USHORT          usNPreBits;

    /* Calculate byte offset for first byte containing the bit values starting
     * at usBitOffset. */
    usByteOffset = ( USHORT )( ( usBitOffset ) / BITS_UCHAR );

    /* How many bits precede our bits to set. */
    usNPreBits = ( USHORT )( usBitOffset - usByteOffset * BITS_UCHAR );

    /* Prepare a mask for setting the new bits. */
    usMask = ( USHORT )( ( 1 << ( USHORT ) ucNBits ) - 1 );

    /* copy bits into temporary storage. */
    usWordBuf = ucByteBuf[usByteOffset];
    usWordBuf |= ucByteBuf[usByteOffset + 1] << BITS_UCHAR;

    /* throw away unneeded bits. */
    usWordBuf >>= usNPreBits;

    /* mask away bits above the requested bitfield. */
    usWordBuf &= usMask;

    return ( UCHAR ) usWordBuf;
}

void
xMBUtilSetBits( UCHAR * ucByteBuf, USHORT usBitOffset, UCHAR ucNBits,
                UCHAR ucValue )
{
    USHORT          usWordBuf;
    USHORT          usMask;
    USHORT          usByteOffset;
    USHORT          usNPreBits;
    USHORT          usValue = ucValue;

   // assert( ucNBits <= 8 );
   // assert( ( size_t )BITS_UCHAR == sizeof( UCHAR ) * 8 );

    /* Calculate byte offset for first byte containing the bit values starting
     * at usBitOffset. */
    usByteOffset = ( USHORT )( ( usBitOffset ) / BITS_UCHAR );

    /* How many bits precede our bits to set. */
    usNPreBits = ( USHORT )( usBitOffset - usByteOffset * BITS_UCHAR );

    /* Move bit field into position over bits to set */
    usValue <<= usNPreBits;

    /* Prepare a mask for setting the new bits. */
    usMask = ( USHORT )( ( 1 << ( USHORT ) ucNBits ) - 1 );
    usMask <<= usBitOffset - usByteOffset * BITS_UCHAR;

    /* copy bits into temporary storage. */
    usWordBuf = ucByteBuf[usByteOffset];
    usWordBuf |= ucByteBuf[usByteOffset + 1] << BITS_UCHAR;

    /* Zero out bit field bits and then or value bits into them. */
    usWordBuf = ( USHORT )( ( usWordBuf & ( ~usMask ) ) | usValue );

    /* move bits back into storage */
    ucByteBuf[usByteOffset] = ( UCHAR )( usWordBuf & 0xFF );
    ucByteBuf[usByteOffset + 1] = ( UCHAR )( usWordBuf >> BITS_UCHAR );
}


BOOL
MBSlaveFunc01CallBack(UCHAR * wRegHoldingbuffer, USHORT startAddress, USHORT  numberOfCoils )
{
	//VALORES DO MAPA BINÁRIO DE SEU DISPOSITIVO SLAVE CONTENDO APENAS 2 BYTES. IMPLEMENTE MAIS OU MENOS BYTES DE ACORDO
//COM A NECESSIDADE; 
	UCHAR ucByteBuf[] = {0B00000011, 0B00000000};
	UCHAR ret = xMBUtilGetBits(ucByteBuf, startAddress, numberOfCoils);
	memset(ucByteBuf,0,sizeof(ucByteBuf));
	xMBUtilSetBits(ucByteBuf, startAddress, numberOfCoils, numberOfCoils);
	memcpy(wRegHoldingbuffer, ucByteBuf, sizeof(ucByteBuf));
	
   return TRUE;
}
/**
*  Modbus RTU Function Code 01 - Modo Slave
*/
void main( void )
{
#ifdef P18F45K22
    ANSELA = 0;
    ANSELB = 0;
    ANSELC = 0;
    ANSELD = 0;
    ANSELE = 0;
#else
    ADCON1 |= 0X0F;
#endif
    uart_init();
    timer_init();
    /**
     * Função LCD do compilador mikroC
     */
    Lcd_Init();
    Lcd_Cmd(_LCD_CLEAR);
    Lcd_Cmd(_LCD_CURSOR_OFF);
    Lcd_Out(1,1, "ADD:      ");
    Lcd_Out(2,1, "COIL:     ");

   for(;;)
   {
       MB();
   }
}

Substitua a folha main.c do projeto mbslave_f01, compile e faça o teste. Não tenho como testar neste momento no hardware, porém testei no Devc++ as funções básica do exemplo

abraços, 

fernando Simplicio

Este site usa cookies para melhorar sua experiência. Política de Privacidade