Ir ao conteúdo
  • Cadastre-se

Ajuda com MODBUS no MikroC


victormantuaneli

Posts recomendados

Olá pessoal!

Estou com um projeto onde preciso criar uma comunicação entre CLPs e PIC utilizando MODBUS RTU.

Por exemplo, terei uma entrada analógica no pic e, via MODBUS lerei este valor e mostrarei CLP.

O problema é que não sei como interpretarei o prontocolo no mikroc.

Gostaria que me dessem exemplos de como posso interpretar os bytes de endereço, função e dados no mikroc para, assim retornar os dados para o CLP.

Link para o comentário
Compartilhar em outros sites

Estive tetando a um tempo atrás uma comunicação PIC<->PLC com o protocolo MODBUS-RTU, mas tive que interromper devido a tempo indisponível para desenvolvimento.

Uma parte do desenvolvimento abaixo.

obs.: O calculo de CRC é o CRC_16 e está funcionando 100% o código está incompleto e com algumas falhas. Pode te servir como base.


; TRANSMISSÂO DE DADOS COM O PC *
;*****************************************************************************************************
; CONFIGURAÇÔES
list p=16f877A
#INCLUDE <p16f877A.inc>

__CONFIG _CP_OFF & _WDT_ON & _BODEN_OFF & _PWRTE_ON & _XT_OSC & _LVP_OFF & _CPD_OFF & _DEBUG_OFF

;*****************************************************************************************************
; DEFINIÇÔES

BANK0 MACRO ; macro para selecionar banco 0
BCF STATUS,RP0 ; clear rp0
BCF STATUS,RP1 ; clear rp1
ENDM
BANK1 MACRO ; macro para selecionar banco 1
BSF STATUS,RP0 ; set rp0
BCF STATUS,RP1 ; clear rp1
ENDM
BANK2 MACRO ; macro para selecionar banco 2
BCF STATUS,RP0 ; clear rp0
BSF STATUS,RP1 ; set rp1
ENDM
BANK3 MACRO ; macro para selecionar banco 3
BSF STATUS,RP0 ; set rp0
BSF STATUS,RP1 ; set rp1
ENDM
#DEFINE E PORTC,0
#DEFINE RW PORTC,1
#DEFINE RS PORTC,2
#DEFINE LED_STATUS PORTC,3
#DEFINE DADOS_LCD PORTB
;*****************************************************************************************************
; VARIAVEIS

CBLOCK H'20'
UM_SEGUNDO ;20h
WATCHDOG ;21h
TEMP_W ;22h
TEMP_FSR ;23h
ENDERECO_INICIAL_H ;24h
ENDERECO_INICIAL_L ;25h
TAMANHO_BUFFER_H ;26h
TAMANHO_BUFFER_L ;27h
BUFFER ;28h
CONTADOR_BYTES ;29h
TESTE_MODBUS ;2Ah
VALOR ;2Bh
LOAD_REG ;2Ch
TEMP1 ;2Dh
TEMP2 ;2Eh
POLINOMIO_MSB ;2Fh
POLINOMIO_LSB ;30h
CRC16_MSB ;31h
CRC16_LSB ;32h
MENSSAGEM_MSB ;33h
MENSSAGEM_LSB ;34h
CONTADOR_BITS ;35h
UNIDADE ;36H
UNIDADE_ ;37H
DEZENA ;38H
DEZENA_ ;39H
CENTENA ;3AH
CENTENA_ ;3BH
TEMP_TESTE_MODBUS ;3CH
TAMANHO_BUFFER_L_2 ;3Dh
TAMANHO_BUFFER_L_3 ;3Eh
QUANTIDADE_BYTES ;3Fh
FUNCAO ;40h
ENDERECO ;41h
COUNT_1
ENDC
;*****************************************************************************************************
; CONSTANTES


;*****************************************************************************************************
; VETOR DE RESET

ORG 0x0000
GOTO START

;*****************************************************************************************************
; INTERRUPÇÂO

ORG 0x0004
MOVWF TEMP_W ; ARMAZENA "W" TEMPORARIAMENTE
MOVF FSR,W
MOVWF TEMP_FSR ; ARMAZENA FSR TEMPORARIAMENTE
BTFSS INTCON,T0IF ; VERIFICA SE A INTERRUPCAO FOI GERADA POR TMR0
GOTO RECEBER_DADOS ; SE NAO FOI TMR0, VERIFICA A USART
BCF INTCON,T0IF ; LIMPA FLAG TMR0
MOVLW .131
MOVWF TMR0 ; FAZ COM QUE TMR0 GERE UMA INTERRUPCAO A CADA 4mSEG COM CRISTAL DE 4MHZ
INCF WATCHDOG
MOVLW .4
XORWF WATCHDOG,W
BTFSS STATUS,Z ; VERIFICA SE WATCHDOG = 16mSEG
GOTO ROTINA_1SEG
CLRF WATCHDOG ; WATCHDOG = A 16mSEG
CLRWDT ; RESETA WATCHDOG PARA NAO ESTOURAR
ROTINA_1SEG
INCF UM_SEGUNDO
MOVLW .250
XORWF UM_SEGUNDO,W
BTFSS STATUS,Z ; VERIFICA SE PASSOU 1 SEGUNDO
GOTO SAIR ; SE NAO PASSOU, SAI DA INTERRUPCAO


CALL CONVERTER
CALL ESCREVE_LCD
BTFSS LED_STATUS ; VERIFICA SE O LED ESTA ACESO
GOTO ACENDE_LED ; SE NAO, ACENDE
GOTO APAGA_LED ; SE SIM, APAGA
APAGA_LED
BCF LED_STATUS ; APAGA LED
GOTO SAIR
ACENDE_LED
BSF LED_STATUS ; ACENDE LED

SAIR
MOVF TEMP_FSR,W
MOVWF FSR ; RECUPERA BYTE TEMPORARIO DO FSR
MOVF TEMP_W,W ; RECUPERA BYTE TEMPORARIO DO REGISTRADOR "W"
RETFIE

;*****************************************************************************************************

VALOR_
ADDWF PCL,F
RETLW '0'
RETLW '1'
RETLW '2'
RETLW '3'
RETLW '4'
RETLW '5'
RETLW '6'
RETLW '7'
RETLW '8'
RETLW '9'
START
BANK1
MOVLW b'00000001'
MOVWF TRISA ; SETA PRIMEIRO BIT COMO ENTRADA OS DEMAIS COMO SAIDAS
MOVLW b'00000000'
MOVWF TRISB ; SETA PORTB COMO SAIDA
MOVLW b'11000000'
MOVWF TRISC ; SETA PORTC,7 E 6 COMO USART E DEMAIS COMO SAIDA
MOVLW b'00000000'
MOVWF TRISD ; SETA PORTD COMO SAIDA
MOVLW b'00000000'
MOVWF TRISE ; SETA PORTE COMO SAIDA
MOVLW b'10000100'
MOVWF OPTION_REG ; PULL UP DESABILITADOS E TMR0 1:32
MOVLW b'11100000'
MOVWF INTCON ; INTERRUPCOES DE TMR0 E USART RECEIVE HABILITADOS
MOVLW b'00001110'
MOVWF ADCON1 ; AN0 COMO ENTRADA ANALOGICA E DEMAIS COMO DIGITAL
BANK0
MOVLW b'10000001'
MOVWF ADCON0 ; CLOCK DE CONVERSAO = OSC/32 SELECIONA CANAL 0 CONVERSAO, LIGA O MODULO BIT<0>

MOVLW .132
MOVWF TMR0 ; CONFIGURA TMR0 PARA GERAR INTERRUPCA A CADA 4mSEGUNDO
CLRF WATCHDOG ; RESETA CONTADOR DE CICLOS PARA RESETAR WATCHDOG
CLRF UM_SEGUNDO ; RESETA CONTADOR DE CICLOS PARA INDICAR 1 SEGUNDO
BCF LED_STATUS ; INICIA COM LED APAGADO
CLRF CONTADOR_BYTES
CLRF BUFFER
BANK1 ; INICIALIZA SERIAL
BSF TXSTA,BRGH ; SETA USART PARA ALTA VELOCIDADE
MOVLW .12
MOVWF SPBRG ; SETA BAUDRATE PARA 19200 COM CRISTAL DE 4MHZ
BCF TXSTA,SYNC ; SETA MODO DE TRANSMISSAO ASSINCRONA
BSF TXSTA,TXEN ; HABILITA TRANSMISSAO
BSF PIE1,RCIE ; HABILITA INTERRUPCAO DE RECEPCAO DA USART
BANK0
BSF RCSTA,SPEN ; HABILITA PORTA SERIAL, PINOS PORTC,7 E 6
BSF RCSTA,CREN ; HABILITA RECEPCAO CONTINUA

MOVLW H'01'
MOVWF ENDERECO ;define endereco do microcontrolador como 01 na rede
MOVLW B'10100000'
MOVWF POLINOMIO_MSB ;inicializa polinomio
MOVLW B'00000001'
MOVWF POLINOMIO_LSB ;inicializa polinomio
CLRF MENSSAGEM_MSB
CLRF MENSSAGEM_LSB
MOVLW H'FF'
MOVWF CRC16_MSB ;inicializa crc byte mais sgnificativo
MOVWF CRC16_LSB ;inicializa crc byte menos significativo

CALL INICIA_LCD
CALL CONVERSAO_AD
GOTO $-1
RECEBER_DADOS
BTFSS PIR1,RCIF ;Verifica se a interrupcao foi gerada por USART
GOTO SAIR ;Se nao foi, sai da interrupcao
CALL CHECA_ENDERECO ;Checa o endereco do destinatario
CALL VERIFICA_FUNCAO

TRANSMITIR_DADOS
MOVF ENDERECO,W
MOVWF MENSSAGEM_LSB
CALL TRANSMITE
CALL CALCULA_CRC
MOVF FUNCAO,W
MOVWF MENSSAGEM_LSB
CALL TRANSMITE
CALL CALCULA_CRC
MOVF QUANTIDADE_BYTES,W
MOVWF MENSSAGEM_LSB
CALL TRANSMITE
CALL CALCULA_CRC
CALL PREENCHE_MENSSAGEM
MOVF CRC16_LSB,W ;carrega CRC16 menos significativo para transmissao.
CALL TRANSMITE ;crc16 composto: id. rede, funcao, qtd bytes, x bytes
MOVF CRC16_MSB,W ;carrega CRC16 mais significativo para transmissao
CALL TRANSMITE

MOVLW H'FF'
MOVWF CRC16_MSB ;inicializa crc byte mais sgnificativo
MOVWF CRC16_LSB ;inicializa crc byte menos significativo

GOTO SAIR
NOVO_DADO
CLRWDT
BTFSS PIR1,RCIF
GOTO $-2
RETURN
OBTEM_INFORMACAO
MOVLW H'50'
MOVWF BUFFER
VOLTA_1
MOVF ENDERECO_INICIAL_L,W
MOVWF FSR
MOVF INDF,W
MOVWF VALOR
MOVF BUFFER,W
MOVWF FSR
MOVF VALOR,W
MOVWF INDF
INCF ENDERECO_INICIAL_L,F
INCF BUFFER
DECFSZ TAMANHO_BUFFER_L,F
GOTO VOLTA_1
RETURN

TRANSMITE
MOVWF TXREG
BANK1
BTFSS TXSTA,TRMT
GOTO $-1
BANK0
RETURN
CALCULA_CRC

MOVF MENSSAGEM_MSB,W
XORWF CRC16_MSB,F ;executa logica xor crc_lsb.menssagem_msb
MOVF MENSSAGEM_LSB,W
XORWF CRC16_LSB,F ;executa logica xor crc_msb.menssagem_lsb

MOVE
INCF CONTADOR_BITS,F
MOVLW .9
XORWF CONTADOR_BITS,W
BTFSC STATUS,Z
GOTO CRC_OK

BCF STATUS,C
RRF CRC16_MSB,F
BTFSS STATUS,C
GOTO CARRY_MSB_0
GOTO CARRY_MSB_1
CARRY_MSB_0
BCF STATUS,C
RRF CRC16_LSB,F
BCF CRC16_MSB,7
BTFSS STATUS,C
GOTO CARRY_LSB_0
GOTO CARRY_LSB_1
CARRY_MSB_1
BCF STATUS,C
RRF CRC16_LSB,F
BSF CRC16_LSB,7
BTFSS STATUS,C
GOTO CARRY_LSB_0
GOTO CARRY_LSB_1
CARRY_LSB_0
BCF STATUS,C
GOTO MOVE
CARRY_LSB_1
BCF STATUS,C
CALL POLINOMIO
GOTO MOVE
POLINOMIO
MOVF CRC16_MSB,W
XORWF POLINOMIO_MSB,W
MOVWF CRC16_MSB

MOVF CRC16_LSB,W
XORWF POLINOMIO_LSB,W
MOVWF CRC16_LSB
RETURN

CRC_OK
CLRF CONTADOR_BITS
RETURN

CONVERSAO_AD
CALL DELAY_50uSEG
BSF ADCON0,GO
BTFSC ADCON0,GO
GOTO $-1
MOVF ADRESH,W
MOVWF TESTE_MODBUS

RETURN

INICIA_LCD
BCF RS ; INICIALIZA LCD
BCF RW
MOVLW H'38'
MOVWF DADOS_LCD
CALL PULSO

MOVLW H'0E'
MOVWF DADOS_LCD
CALL PULSO

MOVLW H'06'
MOVWF DADOS_LCD
CALL PULSO

MOVLW H'01'
MOVWF DADOS_LCD
CALL PULSO
CALL DELAY_2mSEG

BCF RS
MOVLW H'80'
MOVWF DADOS_LCD
CALL PULSO
BSF RS
RETURN


DELAY_50uSEG
MOVLW .20
MOVWF TEMP1
REPEAT
DECFSZ TEMP1
GOTO REPEAT
RETURN
DELAY_2mSEG
MOVLW .38
MOVWF TEMP2
DELAY
CALL DELAY_50uSEG
DECFSZ TEMP2
GOTO DELAY
RETURN
PULSO
BSF E
NOP
NOP
NOP
BCF E
CALL DELAY_50uSEG
RETURN

ESCREVE_LCD
BCF RS
MOVLW H'C0'
MOVWF DADOS_LCD
CALL PULSO
BSF RS
MOVF CENTENA_,W
MOVWF DADOS_LCD
CALL PULSO
MOVF DEZENA_,W
MOVWF DADOS_LCD
CALL PULSO
MOVF UNIDADE_,W
MOVWF DADOS_LCD
CALL PULSO
RETURN

CONVERTER
CLRF UNIDADE
CLRF UNIDADE_
CLRF DEZENA
CLRF DEZENA_
CLRF CENTENA
CLRF CENTENA_
MOVF TESTE_MODBUS,W
MOVWF TEMP_TESTE_MODBUS
MOVLW .1
ADDWF TEMP_TESTE_MODBUS,F
VOLTA
DECFSZ TEMP_TESTE_MODBUS,F
GOTO $+2
GOTO OBTEM_VALOR
INCF UNIDADE
MOVLW .10
XORWF UNIDADE,W
BTFSS STATUS,Z
GOTO VOLTA
INCF DEZENA
CLRF UNIDADE
MOVLW .10
XORWF DEZENA,W
BTFSS STATUS,Z
GOTO VOLTA
INCF CENTENA
CLRF DEZENA
GOTO VOLTA
OBTEM_VALOR
MOVF UNIDADE,W
CALL VALOR_
MOVWF UNIDADE_
MOVF DEZENA,W
CALL VALOR_
MOVWF DEZENA_
MOVF CENTENA,W
CALL VALOR_
MOVWF CENTENA_
RETURN

;*********************************************************************************************************************************
; CHECA SE O ENDERECO DO DESTINATARIO é BROADCAST OU O ENDERECO DO MICROCONTROLADOR NA REDE *
;*********************************************************************************************************************************

CHECA_ENDERECO
MOVLW H'00' ; Verifica o endereco do micronrtrolador é 0 = broadcast
XORWF RCREG,W
BTFSC STATUS,Z
RETURN ; =0, libera para receber informacao
MOVF ENDERECO,W ; Verifica se o endereco da informacao é = ao endereco do microcontroldor
XORWF RCREG,W
BTFSC STATUS,Z
RETURN ; =1, libera para receber informacao
GOTO SAIR ; nao é o endereco do microcontrolador nem mensagem broadcast, sai da interrupcao
;*********************************************************************************************************************************
; VERIFICA QUAL A FUNCAO SOLICITADA NA COMUNICACAO E EXECUTA FUNCAO *
;*********************************************************************************************************************************

VERIFICA_FUNCAO
CALL NOVO_DADO ; Checa a chegada de novo dado
MOVLW H'01' ; Verifica se a funcao é de leitura de saidas
XORWF RCREG,W
BTFSC STATUS,Z
GOTO LEITURA_DE_SAIDAS

MOVLW H'02' ; Verifica se a funcao é de leitura de entradas
XORWF RCREG,W
BTFSC STATUS,Z
GOTO LEITURA_DE_ENTRADAS

MOVLW H'03' ; Verifica se a funcao é de leitura de registradores
XORWF RCREG,W
BTFSC STATUS,Z
GOTO LEITURA_DE_REGISTRADORES

MOVLW H'04' ; Verifica se a funcao é de leitura de registradores de entrada (analogicos)
XORWF RCREG,W
BTFSC STATUS,Z
GOTO LEITURA_DE_REGISTRADORES_DE_ENTRADA

MOVLW H'05' ; Verifica se a funcao é de escrita em uma saida
XORWF RCREG,W
BTFSC STATUS,Z
GOTO ESCRITA_DE_SAIDA

MOVLW H'06' ; Verifica se a funcao é de escrita em um registrador
XORWF RCREG,W
BTFSC STATUS,Z
GOTO ESCRITA_DE_REGISTRADOR

MOVLW H'15' ; Verifica se a funcao é de escrita em varias saidas
XORWF RCREG,W
BTFSC STATUS,Z
GOTO ESCRITA_DE_SAIDAS

MOVLW H'16' ; Verifica se a funcao é de escrita em varios registradores
XORWF RCREG,W
BTFSC STATUS,Z
GOTO ESCRITA_DE_REGISTRADORES

GOTO SAIR

LEITURA_DE_SAIDAS
CALL CHECA_ENDERECO_INICIO
CALL CHECA_TAMANHO_BUFFER
CALL CHECA_CRC
MOVLW H'05'
ADDWF ENDERECO_INICIAL_L,F
CALL OBTEM_INFORMACAO
MOVLW H'01'
MOVWF FUNCAO
CALL CHECA_QUANTIDADE_BYTES
RETURN

LEITURA_DE_ENTRADAS
CALL NOVO_DADO

LEITURA_DE_REGISTRADORES
CALL NOVO_DADO

LEITURA_DE_REGISTRADORES_DE_ENTRADA
CALL NOVO_DADO

ESCRITA_DE_SAIDA
CALL NOVO_DADO

ESCRITA_DE_REGISTRADOR
CALL NOVO_DADO

ESCRITA_DE_SAIDAS
CALL NOVO_DADO

ESCRITA_DE_REGISTRADORES
CALL NOVO_DADO

;*********************************************************************************************************************************
; CHECA ENDERECO INICIAL DE LEITURA, TAMANHO DO BUFFER, CRC E QUANTIDADE DE BYTES DA RESPOSTA *
;*********************************************************************************************************************************

CHECA_ENDERECO_INICIO
CALL NOVO_DADO
MOVF RCREG,W
MOVWF ENDERECO_INICIAL_H
CALL NOVO_DADO
MOVF RCREG,W
MOVWF ENDERECO_INICIAL_L
RETURN

CHECA_TAMANHO_BUFFER
CALL NOVO_DADO
MOVF RCREG,W
MOVWF TAMANHO_BUFFER_H
CALL NOVO_DADO
MOVF RCREG,W
MOVWF TAMANHO_BUFFER_L
MOVWF TAMANHO_BUFFER_L_2
MOVWF TAMANHO_BUFFER_L_3
RETURN

CHECA_CRC
CALL NOVO_DADO
MOVF RCREG,W
;MSB CRC
CALL NOVO_DADO
MOVF RCREG,W
;LSB CRC
RETURN

CHECA_QUANTIDADE_BYTES
CLRF COUNT_1
MOVLW .1
MOVWF QUANTIDADE_BYTES
VOLTA_3
INCF COUNT_1,F
MOVLW .9
XORWF COUNT_1,W
BTFSC STATUS,Z
GOTO VOLTA_4
DECFSZ TAMANHO_BUFFER_L_2,F
GOTO VOLTA_3
RETURN
VOLTA_4
INCF QUANTIDADE_BYTES
CLRF COUNT_1
DECFSZ TAMANHO_BUFFER_L_2,F
GOTO VOLTA_3
RETURN

;*********************************************************************************************************************************
; PREENCHE mensagem *
;*********************************************************************************************************************************

PREENCHE_MENSSAGEM
MOVLW H'4F'
MOVWF BUFFER
VOLTA_2
INCF BUFFER,F
; MOVLW H'00' ; nao usado para leitura de saidas
; MOVWF MENSSAGEM_LSB ; nao usado para leitura de saidas
; CALL TRANSMITE ; nao usado para leitura de saidas
; CALL CALCULA_CRC ; nao usado para leitura de saidas
MOVF BUFFER,W
MOVWF FSR
MOVF INDF,W
MOVWF MENSSAGEM_LSB
CALL TRANSMITE
CALL CALCULA_CRC
DECFSZ QUANTIDADE_BYTES,F
GOTO VOLTA_2
RETURN


END


;*****************************************************************************************************

Link para o comentário
Compartilhar em outros sites

O CRC_16 está funcionando 100%



MOVF MENSSAGEM_MSB,W
XORWF CRC16_MSB,F ;executa logica xor crc_lsb.menssagem_msb
MOVF MENSSAGEM_LSB,W
XORWF CRC16_LSB,F ;executa logica xor crc_msb.menssagem_lsb

MOVE
INCF CONTADOR_BITS,F
MOVLW .9
XORWF CONTADOR_BITS,W
BTFSC STATUS,Z
GOTO CRC_OK

BCF STATUS,C
RRF CRC16_MSB,F
BTFSS STATUS,C
GOTO CARRY_MSB_0
GOTO CARRY_MSB_1
CARRY_MSB_0
BCF STATUS,C
RRF CRC16_LSB,F
BCF CRC16_MSB,7
BTFSS STATUS,C
GOTO CARRY_LSB_0
GOTO CARRY_LSB_1
CARRY_MSB_1
BCF STATUS,C
RRF CRC16_LSB,F
BSF CRC16_LSB,7
BTFSS STATUS,C
GOTO CARRY_LSB_0
GOTO CARRY_LSB_1
CARRY_LSB_0
BCF STATUS,C
GOTO MOVE
CARRY_LSB_1
BCF STATUS,C
CALL POLINOMIO
GOTO MOVE
POLINOMIO
MOVF CRC16_MSB,W
XORWF POLINOMIO_MSB,W
MOVWF CRC16_MSB

MOVF CRC16_LSB,W
XORWF POLINOMIO_LSB,W
MOVWF CRC16_LSB
RETURN

CRC_OK
CLRF CONTADOR_BITS
RETURN
CALCULA_CRC

Link para o comentário
Compartilhar em outros sites

  • 2 semanas depois...

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...