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