Arsalan
Starting Member
- Total Posts : 11
- Reward points : 0
- Joined: 2012/10/17 03:21:37
- Location: 0
- Status: offline
PIC18F MODBUS COMMUNICATION
Hello everyone, this is my first post so forgive/bear me if i am wrong, I wrote a code for MODBUS RTU SLAVE protocol for PIC18F46K22, which was working fine when i was in debug mode, data were travelling to and fro from PC SIDE MODPOLL software to PIC18F26K22 slave. But when i programmed the device for standalone application, PC software gives me TIMEOUT ERROR. and if i again connect it in debug mode it again works fine. any suggestion please where i am getting wrong. Thanks Regards
|
DarioG
Allmächtig.
- Total Posts : 54081
- Reward points : 0
- Joined: 2006/02/25 08:58:22
- Location: Oesterreich
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2017/10/30 13:53:01
(permalink)
Is your code running at all in "not-debug" mode? Do you have MCLR pin raised, proper power supply, proper decoupling capacitors...?
|
qhb
Superb Member
- Total Posts : 9999
- Reward points : 0
- Joined: 2016/06/05 14:55:32
- Location: One step ahead...
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2017/10/30 15:30:42
(permalink)
Which pins are you using for communication? If they are analog capable, have you switched them to digital mode? (The debugger switches some pins to digital mode for its own use. That won't happen in run mode.)
|
Arsalan
Starting Member
- Total Posts : 11
- Reward points : 0
- Joined: 2012/10/17 03:21:37
- Location: 0
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2017/10/30 22:31:01
(permalink)
ya my rest of the code was running in "not-debug" mode. By the way i resolved that issue by selecting my current project as 'main project' from RUN toolbar menu which was earlier set to 'none'. But now i am facing other problem that when i program my code using PICKIT-3 at first it works and all the features including modbus communication works properly. But when i restart my project, rest of the code works fine except for rs-485 modbus and again at PC side modbpoll software it gives me TIMEOUT error.
|
Arsalan
Starting Member
- Total Posts : 11
- Reward points : 0
- Joined: 2012/10/17 03:21:37
- Location: 0
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2017/10/30 22:40:36
(permalink)
i am using tx1 and rx1 RC6 and RC7 which are analog pins as well but i had disable the analog function in my main code. also i am using RE2 pin for communication direction control of MAX-485. which is also i guess i had set as digital pin. below is main code. static bit disp_mode,prog_mode; char read1,read2,read3,read4;
OSCCON = 0b01110011; //internal osc 16 Mhz HFINTOSC ANSELA = 0x00; //DISABLE ANALOG CHANNELS TRISA = 0b00000000; //LCD DATA PINS DIRECTION = OUTPUT
lcd = 0b00000000; //LCD DATA PINS DEFAULT VALUE ANSELCbits.ANSC2 = 0; //digital pins and not analog ANSELCbits.ANSC3 = 0; //digital pins and not analog ANSELCbits.ANSC4 = 0; //digital pins and not analog ANSELCbits.ANSC6 = 0; //digital pins and not analog TX1 ANSELCbits.ANSC7 = 0; //digital pins and not analog RX1 TRISCbits.TRISC4 = 1; TRISCbits.TRISC3 = 1; TRISCbits.TRISC2 = 1; // SET CAPTURE CCP1 AS INPUT PIN ANSELE = 0x00; //DIGITAL PINS ADCON0 = 0x00; //SHUT OFF ADC MODULE TRISE = 0b00000000; //LCD CONTROL PINS and TX_RX CONTROL PINS DIRECTION = OUTPUT ANSELB = 0x00; TRISB = 0x3C; //PINS RB2 - RB5 SELECTED AS INPUTS. PORTB = 0xFF; //DEFAULT VALUE OF INPUT PINS AS 1 (SINCE ACTIVE LOW INPUTS) WPUB = 0x3C; // enable weak pull up of corresponding input pin INTCON2bits.RBPU = 0; // enable weak pull up of port B; init_lcd(); display_all("PCD-TFM-V2.0"); lcdcmd(0xC2); display_all("PROCESS"); eunit.ui = read_eeprom(0x01); tunit.ui = read_eeprom(0x02); deci.ui = read_eeprom(0x03); read1 = read_eeprom(0x04); read2 = read_eeprom(0x05); read3 = read_eeprom(0x06); read4 = read_eeprom(0x07); range_val.ui = (read1*1000)+(read2*100)+(read3*10)+read4; __delay_ms(200);__delay_ms(200);__delay_ms(200); lcdcmd(0xC2); display_all("CONTROL"); k1 = read_eeprom(0x08); k2 = read_eeprom(0x09); k3 = read_eeprom(0x0A); k4 = read_eeprom(0x0B); k5 = read_eeprom(0x0C); K_VALUE.f = ((k1+(k2*0.1)+(k3*0.01)+(k4*0.001)+(k5*0.0001))); read1 = read_eeprom(0x16); read2 = read_eeprom(0x17); read3 = read_eeprom(0x18); read4 = read_eeprom(0x19); zero.ui = (read1*1000)+(read2*100)+(read3*10)+read4; __delay_ms(200);__delay_ms(200);__delay_ms(200); lcdcmd(0xC2); display_all("DEVICES"); __delay_ms(200);__delay_ms(200);__delay_ms(200); read1 = read_eeprom(0x1A); read2 = read_eeprom(0x1B); read3 = read_eeprom(0x1C); read4 = read_eeprom(0x1D); span.ui = (read1*1000)+(read2*100)+(read3*10)+read4; read1 = read_eeprom(0x10); read2 = read_eeprom(0x11); read3 = read_eeprom(0x12); read4 = read_eeprom(0x13); ENTFREQ.f = (read1*1000)+(read2*100)+(read3*10)+read4; read1 = read_eeprom(0x28); read2 = read_eeprom(0x29); read3 = read_eeprom(0x2A); read4 = read_eeprom(0x2B); ENTFR.f = (read1*1000)+(read2*100)+(read3*10)+read4; sen_k.f=(ENTFR.f/ENTFREQ.f); //calculate the k-value eeprom_read_object(0x20, &total.f, sizeof total.f); lpm.f=((span.ui-zero.ui)/(float)range_val.ui); I2CINIT(); init_timer0(); init_timer1(); init_ccp1(); init_esuart1(); lcdcmd(0x01); i=0; disp_mode=1;prog_mode=0; state=1;dp=1;kmode=0;baud_sel=4; database[20] = password.ub[1];database[21] = password.ub[0]; database[54] = xtal.ub[3];database[55] = xtal.ub[2];database[56] = xtal.ub[1];database[57] = xtal.ub[0]; database[62] = 0;database[63] = hw_version; database[64] = 0;database[65] = sw_version; rx_index=0;rx_done=0;tx_enable=0; ovr_bit=0;fer_bit=0;tx_rx=0; T0CONbits.TMR0ON = 1; // start timer0 for totalizer sampling T1CONbits.TMR1ON = 1; // start timer1 for counting timeperiod
|
Arsalan
Starting Member
- Total Posts : 11
- Reward points : 0
- Joined: 2012/10/17 03:21:37
- Location: 0
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2017/10/30 22:49:33
(permalink)
sorry for incomplete code, below is my esuart1 initialization code void init_esuart1(void) { INTCONbits.GIE = 0; //disable global interrupt INTCONbits.PEIE = 0; //DISABLE PERIPHERAL INTERRUPT SPBRGH1 = 0x01; //HEX values for 416 for 9592~9600 baud rate SPBRG1 = 0xA0; TXSTA1bits.BRGH = 1; //high baud rates BAUDCON1bits.BRG16 = 1; //16-bits baud register. TRISCbits.TRISC6 = 1; //FOR ESUART AYSYNCHRONOUS RECEPTION AND TRANSMISSION TRISCbits.TRISC7 = 1; RCSTA1bits.SPEN = 1; //ENABLE EUSART TXSTA1bits.SYNC = 0; //ASYNCHRONOUS MODE INTCONbits.GIE = 0; //GLOBAL INTERRUPT DISABLE INTCONbits.PEIE = 0; //PERIPHERAL INTERRUPT DISBALE PIE1bits.RC1IE = 0; //RECEIVE INTERRUPT DISBALE RCSTA1bits.RX9 = 1; //ENABLE 9-BIT RECEPTION RCSTA1bits.CREN = 1; //enable reception. TXSTA1bits.TX9 = 1; //ENABLE 9-bit TRANSMISSION TXSTA1bits.TX9D = 1; //SET 9TH BIT TO 1 FOR TWO STOP BITS PURPOSE TXSTA1bits.TXEN = 1; //enable transmission. temp1 = RCREG1; //FLUSH RECEIVE REGISTER temp2 = RCREG1; INTCONbits.GIE = 1; //GLOBAL INTERRUPT DISABLE INTCONbits.PEIE = 1; //PERIPHERAL INTERRUPT DISBALE PIE1bits.RC1IE = 1; //RECEIVE INTERRUPT ENABLE }
|
Arsalan
Starting Member
- Total Posts : 11
- Reward points : 0
- Joined: 2012/10/17 03:21:37
- Location: 0
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2017/10/30 23:34:47
(permalink)
i have the raised the MCLR pin to VDD by using 10K resistor, power supply is also proper but i dnt knw about decoupling capacitor. i have used 0.1mfd capacitor on vdd and vss thats it.
|
DarioG
Allmächtig.
- Total Posts : 54081
- Reward points : 0
- Joined: 2006/02/25 08:58:22
- Location: Oesterreich
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2017/10/31 02:02:39
(permalink)
|
Arsalan
Starting Member
- Total Posts : 11
- Reward points : 0
- Joined: 2012/10/17 03:21:37
- Location: 0
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2017/10/31 02:15:19
(permalink)
But the issue is still there as, when i am first programming (not in debug mode)my device using pickit-3, the code works fine and so as modbus communication. but when switch off the power and switch it back on, except for modbus communicaton feature rest of the code works fine. on PC side modpoll software it gives me TIMEOUT error. Please help me with this, i dnt knw whether something is wrong in my code or my programming methods are wrong. i am using MPLAB X IDE V3.5 with xc8 compiler which is in free mode.
|
Arsalan
Starting Member
- Total Posts : 11
- Reward points : 0
- Joined: 2012/10/17 03:21:37
- Location: 0
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2017/10/31 07:30:06
(permalink)
Okay so after 2 days i found out that after power on restart. my code or pic18f itself(i dont know) is generating receive interrupt. which was not being generated first time when i programmed it. I dont know why and how. But to solve this issue i just put a flag saying that it is initialized receive interrupt and not actual. and problem solved Thanks all of you guys.
|
Jim Nickerson
User 452
- Total Posts : 6846
- Reward points : 0
- Joined: 2003/11/07 12:35:10
- Location: San Diego, CA
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2017/10/31 07:41:51
(permalink)
|
rotting79
New Member
- Total Posts : 20
- Reward points : 0
- Joined: 2012/04/17 17:29:08
- Location: 0
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2018/08/20 21:47:17
(permalink)
hey there (even when the thread in a little old) Im gonna try to contribute with some hints instead complain about some bug. Last week I just finished a little program with PIC18F26K80, I chose that one because the memory space as Im using an OLED display and no other reason, and hopefully u can find out that this hint useful - even on a PIC16 fits. Im communicating with a gen-set controller on MODBus RTU protocol, and as almost everything on industrial components such HMIs, PLC, etc. This gen-set controllers acts as 'slave' so u have to"ask" for some information from it as a 'master'. So the easy part is to get the UART works, set a pair of arrays, one for Transmission and the other one for Reception. #define MAX_BUFFER_SIZE_TX 0x08 #define MAX_BUFFER_SIZE_RX 0x40 // 64 dec. unsigned char PAYLOAD_MODBUS_TX [ MAX_BUFFER_SIZE_TX ]; unsigned char PAYLOAD_MODBUS_RX [ MAX_BUFFER_SIZE_RX ];
Writing the transmission array fulfilling the RTU protocol (ID, function, starting address Hi, Lo, number of points Hi, Lo, CRC Hi, Lo) which these information get it from every control manufacturer as everyone chose their own registers, and getting a response. On my library u only set the Tx Array once, as the same information u are going to get it every second. then just the Rx Array will be fill it up with the new data, at the end if the CRC (Checksum) is matching, it will display the new data. void setFrameMODBus ( unsigned char id, unsigned char functionCode, unsigned char addHi, unsigned char addLo, unsigned char registerHi, unsigned char registerLo, unsigned char *ptrArrayTx ) { ptrArrayTx [ 0 ] = id; ptrArrayTx [ 1 ] = functionCode; ptrArrayTx [ 2 ] = addHi; ptrArrayTx [ 3 ] = addLo; ptrArrayTx [ 4 ] = registerHi; ptrArrayTx [ 5 ] = registerLo; modBusCRC ( ptrArrayTx, WRITE_MODBUS, WRITE_MODBUS_CRC ); } // setting frame values. writeModBusRegsiter ( PAYLOAD_MODBUS_TX ); readModBusRegister ( PAYLOAD_MODBUS_RX ); if ( modBusCRC ( PAYLOAD_MODBUS_RX, PAYLOAD_MODBUS_RX [ 3 ] + 3, READ_MODBUS_CRC ) ) printfOutData ( );
post edited by rotting79 - 2018/08/21 21:34:06
Attached Image(s) 
|
SILAMBU
New Member
- Total Posts : 9
- Reward points : 0
- Joined: 2018/08/21 05:11:54
- Location: 0
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2018/08/22 01:00:46
(permalink)
Hello Friends, Is there any code for PIC16F877a as a Modbus RTU Master to read holding register from slave. Thanks SILAMBU
|
rotting79
New Member
- Total Posts : 20
- Reward points : 0
- Joined: 2012/04/17 17:29:08
- Location: 0
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2018/08/22 22:05:31
(permalink)
for sure SILAMBU there is no magic on that and reading "hold register" is the easiest part of the journey, just to need to know whats the register number from the slave and your are in, do u have those registers numbers??? so u can apply these library
|
rotting79
New Member
- Total Posts : 20
- Reward points : 0
- Joined: 2012/04/17 17:29:08
- Location: 0
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2018/08/27 19:36:23
(permalink)
well, here is a video where I explain how to apply these piece of code https://www.youtube.com/watch?v=ppxZgfDghPI As I dont have access to upload any file, here is the fragments from them... main.c
int main ( int argc, char** argv ) { /* Set Up the uC. */ setUp ( ); setFrameMODBus ( slaveID, functionCode, startingAddressHi, startingAddressLo, numberOfRegistersHi, numberOfRegistersLo, PAYLOAD_MODBUS_TX );
EnableInterrupt ( TMR0_INTERRUPT ); EnableInterrupt ( GLOBAL_INTERRUPT );
/* Forever Loop */ while ( TRUE ) { if ( INT_1000ms ) { writeModBusRegsiter ( PAYLOAD_MODBUS_TX ); readModBusRegister ( PAYLOAD_MODBUS_RX );
if ( modBusCRC ( PAYLOAD_MODBUS_RX, PAYLOAD_MODBUS_RX [ 3 ] + 3, READ_MODBUS_CRC ) ) printfOutData ( );
else { printf( "shit, CRC No valid \n"); sprintf ( OLED_VAR, "CRC NOT OK!", CLEAR ); OLEDText ( 5, 26, OLED_VAR, SIZE_TWO, OLED_WHITE );
OLEDUpdateDisplay ( DDGRAM_CLEAR ); }
INT_3 = CLEAR; }
} // forever loop. return ( EXIT_SUCCESS ); } // main fuction.
[/code] MODBus.h
#define DE_RE_PIN LATAbits . LATA0
//#define DETECT_I2C_MODULE_PRESENT #define I2C_BUS_1 //#define MODBUS_UART1 #define MODBUS_UART2
#define OLED_ADDRESS 0x78
unsigned char slaveID = 0x0A; unsigned char functionCode = 0x03; unsigned char startingAddressHi = 0x04; unsigned char startingAddressLo = 0x00; unsigned char numberOfRegistersHi = 0x00; unsigned char numberOfRegistersLo = 0x07; unsigned char CRCHi = 0x06; unsigned char CRCLo = 0x07;
unsigned char OLED_Text_1 [ ] = "MODBus v1.0"; unsigned char OLED_Text_2 [ ] = "theRottingOne";
#define MAX_BUFFER_SIZE_TX 0x08 #define MAX_BUFFER_SIZE_RX 0x40 // 64 dec. unsigned char PAYLOAD_MODBUS_TX [ MAX_BUFFER_SIZE_TX ]; unsigned char PAYLOAD_MODBUS_RX [ MAX_BUFFER_SIZE_RX ];
unsigned char OLED_VAR [ 6 ];
#define WRITE_MODBUS 0X06 #define WRITE_MODBUS_CRC 0X00 #define READ_MODBUS_CRC 0X01
void setFrameMODBus ( unsigned char id, unsigned char functionCode, unsigned char addHi, unsigned char addLo, unsigned char registerHi, unsigned char registerLo, unsigned char *ptrArrayTx ); void writeModBusRegsiter ( unsigned char *ptrArrayTx ); void readModBusRegister ( unsigned char *ptrArrayRx ); bit checkDataBuffer ( void ); bit modBusCRC ( unsigned char *ptrArray, unsigned char byteCount, unsigned char crcWR );
[/code] ModBus.c
void setFrameMODBus ( unsigned char id, unsigned char functionCode, unsigned char addHi, unsigned char addLo, unsigned char registerHi, unsigned char registerLo, unsigned char *ptrArrayTx ) { ptrArrayTx [ 0 ] = id; ptrArrayTx [ 1 ] = functionCode; ptrArrayTx [ 2 ] = addHi; ptrArrayTx [ 3 ] = addLo; ptrArrayTx [ 4 ] = registerHi; ptrArrayTx [ 5 ] = registerLo; modBusCRC ( ptrArrayTx, WRITE_MODBUS, WRITE_MODBUS_CRC ); } // setting frame values.
void writeModBusRegsiter ( unsigned char *ptrArrayTx ) { DE_RE_PIN = HIGH; // Activating trasnmition. LED_0 = ON;
for ( unsigned char i = 0; i < MAX_BUFFER_SIZE_TX; i++ ) // Transmitting 8bytes of info. { #ifdef MODBUS_UART1 while( !TXSTA1bits . TRMT ) // While transmit shift register is full. ; TX1REG = *ptrArrayTx++; // Write the data byte to the USART. #endif #ifdef MODBUS_UART2 while( !TXSTA2bits . TRMT ) // While transmit shift register is full. ; TX2REG = *ptrArrayTx++; // Write the data byte to the USART. #endif }
DE_RE_PIN = LOW; // Deactivationg transmition. LED_0 = OFF; } // write 8bytes of transmition.
void readModBusRegister ( unsigned char *ptrArrayRx ) { unsigned char counter = CLEAR; signed char skipSearching = CLEAR;
// The function will do the scan on the Rx pin until there is nothing in the bus. while ( !skipSearching ) if ( !checkDataBuffer ( ) ) skipSearching = SET; else { if ( counter < MAX_BUFFER_SIZE_RX ) { #ifdef MODBUS_UART1 *ptrArrayRx = getChUSART1 ( ); #endif #ifdef MODBUS_UART2 *ptrArrayRx = getChUSART2 ( ); #endif ptrArrayRx++; // Increment the string pointer counter++; } else printf ( " MAXIMUM BUFFER SIZE REACHED\n" );
} #ifdef DEBUG // printf ( "%d ", counter ); printfBuffer ( PAYLOAD_MODBUS_RX ); #endif
} // read n bytes from the buffer.
bit checkDataBuffer ( void ) { unsigned int j = CLEAR;
#ifdef MODBUS_UART1 while ( ( !dataRdyUSART1 ( ) ) && ( j < 30000 ) ) j++; return RC1IF; #endif #ifdef MODBUS_UART2 while ( ( !dataRdyUSART2 ( ) ) && ( j < 30000 ) ) j++; return RC2IF; #endif }
bit modBusCRC ( unsigned char *ptrArray, unsigned char byteCount, unsigned char crcWR ) { unsigned int checkSum = 0xFFFF; if ( crcWR == READ_MODBUS_CRC ) { for ( unsigned char i = 0x01; i <= byteCount; i++ ) { checkSum = checkSum ^ ( unsigned int ) ptrArray [ i ]; for ( unsigned char j = 8; j > 0; j-- ) if ( checkSum & 0x0001 ) checkSum = ( checkSum >> 1 ) ^ 0xA001; else checkSum >> = 0x01; }
unsigned char crcHi = checkSum; unsigned char crcLo = checkSum >> 0x08; #ifdef DEBUG printf( "[%d], [%d] \n", crcHi, crcLo ); #endif if ( ( ptrArray [ byteCount + 1 ] == crcHi ) && ( ptrArray [ byteCount + 2 ] == crcLo ) ) return 0x01; } // if CRC functions comes froma a Read command.
if ( crcWR == WRITE_MODBUS_CRC ) { for ( unsigned char i = 0x00; i < WRITE_MODBUS; i++ ) { checkSum = checkSum ^ ( unsigned int ) ptrArray [ i ]; for ( unsigned char j = 8; j > 0; j-- ) if ( checkSum & 0x0001 ) checkSum = ( checkSum >> 1 ) ^ 0xA001; else checkSum >> = 0x01; }
ptrArray [ CRCHi ] = checkSum; ptrArray [ CRCLo ] = checkSum >> 0x08; return 0x00; } // if CRC functions comes froma a Write command. return 0; } // calculate and write CRC to the buffer.
[/code]
|
rotting79
New Member
- Total Posts : 20
- Reward points : 0
- Joined: 2012/04/17 17:29:08
- Location: 0
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2018/08/27 19:54:48
(permalink)
for some reason I can't edit my previous writing and I just mess up the files, but u get the idea
post edited by rotting79 - 2018/08/27 19:57:50
|
qhb
Superb Member
- Total Posts : 9999
- Reward points : 0
- Joined: 2016/06/05 14:55:32
- Location: One step ahead...
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2018/08/27 20:57:56
(permalink)
rotting79 well, here is a video where I explain how to apply these piece of code https://www.youtube.com/watch?v=ppxZgfDghPI As I dont have access to upload any file, here is the fragments from them... main.c
int main ( int argc, char** argv ) { /* Set Up the uC. */ setUp ( ); setFrameMODBus ( slaveID, functionCode, startingAddressHi, startingAddressLo, numberOfRegistersHi, numberOfRegistersLo, PAYLOAD_MODBUS_TX );
EnableInterrupt ( TMR0_INTERRUPT ); EnableInterrupt ( GLOBAL_INTERRUPT );
/* Forever Loop */ while ( TRUE ) { if ( INT_1000ms ) { writeModBusRegsiter ( PAYLOAD_MODBUS_TX ); readModBusRegister ( PAYLOAD_MODBUS_RX );
if ( modBusCRC ( PAYLOAD_MODBUS_RX, PAYLOAD_MODBUS_RX [ 3 ] + 3, READ_MODBUS_CRC ) ) printfOutData ( );
else { printf( "shit, CRC No valid \n"); sprintf ( OLED_VAR, "CRC NOT OK!", CLEAR ); OLEDText ( 5, 26, OLED_VAR, SIZE_TWO, OLED_WHITE );
OLEDUpdateDisplay ( DDGRAM_CLEAR ); }
INT_3 = CLEAR; }
} // forever loop. return ( EXIT_SUCCESS ); } // main fuction.
MODBus.h
#define DE_RE_PIN LATAbits . LATA0
//#define DETECT_I2C_MODULE_PRESENT #define I2C_BUS_1 //#define MODBUS_UART1 #define MODBUS_UART2
#define OLED_ADDRESS 0x78
unsigned char slaveID = 0x0A; unsigned char functionCode = 0x03; unsigned char startingAddressHi = 0x04; unsigned char startingAddressLo = 0x00; unsigned char numberOfRegistersHi = 0x00; unsigned char numberOfRegistersLo = 0x07; unsigned char CRCHi = 0x06; unsigned char CRCLo = 0x07;
unsigned char OLED_Text_1 [ ] = "MODBus v1.0"; unsigned char OLED_Text_2 [ ] = "theRottingOne";
#define MAX_BUFFER_SIZE_TX 0x08 #define MAX_BUFFER_SIZE_RX 0x40 // 64 dec. unsigned char PAYLOAD_MODBUS_TX [ MAX_BUFFER_SIZE_TX ]; unsigned char PAYLOAD_MODBUS_RX [ MAX_BUFFER_SIZE_RX ];
unsigned char OLED_VAR [ 6 ];
#define WRITE_MODBUS 0X06 #define WRITE_MODBUS_CRC 0X00 #define READ_MODBUS_CRC 0X01
void setFrameMODBus ( unsigned char id, unsigned char functionCode, unsigned char addHi, unsigned char addLo, unsigned char registerHi, unsigned char registerLo, unsigned char *ptrArrayTx ); void writeModBusRegsiter ( unsigned char *ptrArrayTx ); void readModBusRegister ( unsigned char *ptrArrayRx ); bit checkDataBuffer ( void ); bit modBusCRC ( unsigned char *ptrArray, unsigned char byteCount, unsigned char crcWR );
ModBus.c
void setFrameMODBus ( unsigned char id, unsigned char functionCode, unsigned char addHi, unsigned char addLo, unsigned char registerHi, unsigned char registerLo, unsigned char *ptrArrayTx ) { ptrArrayTx [ 0 ] = id; ptrArrayTx [ 1 ] = functionCode; ptrArrayTx [ 2 ] = addHi; ptrArrayTx [ 3 ] = addLo; ptrArrayTx [ 4 ] = registerHi; ptrArrayTx [ 5 ] = registerLo; modBusCRC ( ptrArrayTx, WRITE_MODBUS, WRITE_MODBUS_CRC ); } // setting frame values.
void writeModBusRegsiter ( unsigned char *ptrArrayTx ) { DE_RE_PIN = HIGH; // Activating trasnmition. LED_0 = ON;
for ( unsigned char i = 0; i < MAX_BUFFER_SIZE_TX; i++ ) // Transmitting 8bytes of info. { #ifdef MODBUS_UART1 while( !TXSTA1bits . TRMT ) // While transmit shift register is full. ; TX1REG = *ptrArrayTx++; // Write the data byte to the USART. #endif #ifdef MODBUS_UART2 while( !TXSTA2bits . TRMT ) // While transmit shift register is full. ; TX2REG = *ptrArrayTx++; // Write the data byte to the USART. #endif }
DE_RE_PIN = LOW; // Deactivationg transmition. LED_0 = OFF; } // write 8bytes of transmition.
void readModBusRegister ( unsigned char *ptrArrayRx ) { unsigned char counter = CLEAR; signed char skipSearching = CLEAR;
// The function will do the scan on the Rx pin until there is nothing in the bus. while ( !skipSearching ) if ( !checkDataBuffer ( ) ) skipSearching = SET; else { if ( counter < MAX_BUFFER_SIZE_RX ) { #ifdef MODBUS_UART1 *ptrArrayRx = getChUSART1 ( ); #endif #ifdef MODBUS_UART2 *ptrArrayRx = getChUSART2 ( ); #endif ptrArrayRx++; // Increment the string pointer counter++; } else printf ( " MAXIMUM BUFFER SIZE REACHED\n" );
} #ifdef DEBUG // printf ( "%d ", counter ); printfBuffer ( PAYLOAD_MODBUS_RX ); #endif
} // read n bytes from the buffer.
bit checkDataBuffer ( void ) { unsigned int j = CLEAR;
#ifdef MODBUS_UART1 while ( ( !dataRdyUSART1 ( ) ) && ( j < 30000 ) ) j++; return RC1IF; #endif #ifdef MODBUS_UART2 while ( ( !dataRdyUSART2 ( ) ) && ( j < 30000 ) ) j++; return RC2IF; #endif }
bit modBusCRC ( unsigned char *ptrArray, unsigned char byteCount, unsigned char crcWR ) { unsigned int checkSum = 0xFFFF; if ( crcWR == READ_MODBUS_CRC ) { for ( unsigned char i = 0x01; i <= byteCount; i++ ) { checkSum = checkSum ^ ( unsigned int ) ptrArray [ i ]; for ( unsigned char j = 8; j > 0; j-- ) if ( checkSum & 0x0001 ) checkSum = ( checkSum >> 1 ) ^ 0xA001; else checkSum >> = 0x01; }
unsigned char crcHi = checkSum; unsigned char crcLo = checkSum >> 0x08; #ifdef DEBUG printf( "[%d], [%d] \n", crcHi, crcLo ); #endif if ( ( ptrArray [ byteCount + 1 ] == crcHi ) && ( ptrArray [ byteCount + 2 ] == crcLo ) ) return 0x01; } // if CRC functions comes froma a Read command.
if ( crcWR == WRITE_MODBUS_CRC ) { for ( unsigned char i = 0x00; i < WRITE_MODBUS; i++ ) { checkSum = checkSum ^ ( unsigned int ) ptrArray [ i ]; for ( unsigned char j = 8; j > 0; j-- ) if ( checkSum & 0x0001 ) checkSum = ( checkSum >> 1 ) ^ 0xA001; else checkSum >> = 0x01; }
ptrArray [ CRCHi ] = checkSum; ptrArray [ CRCLo ] = checkSum >> 0x08; return 0x00; } // if CRC functions comes froma a Write command. return 0; } // calculate and write CRC to the buffer.
|
qhb
Superb Member
- Total Posts : 9999
- Reward points : 0
- Joined: 2016/06/05 14:55:32
- Location: One step ahead...
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2018/08/27 20:59:37
(permalink)
rotting79 for some reason I can't edit my previous writing and I just mess up the files, but u get the idea
It's the live link in the post causing the problem. You have to "unlink" it to be able to edit the post. See: How to avoid errors when editing posts
|
rotting79
New Member
- Total Posts : 20
- Reward points : 0
- Joined: 2012/04/17 17:29:08
- Location: 0
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2018/08/29 12:28:33
(permalink)
@ qhb thanks for your help
|
rotting79
New Member
- Total Posts : 20
- Reward points : 0
- Joined: 2012/04/17 17:29:08
- Location: 0
- Status: offline
Re: PIC18F MODBUS COMMUNICATION
2018/08/30 21:38:08
(permalink)
hey there Here is a small video on how the PIC18F26K80 is working with two Genset controllers, the first one from DeepSea and the second one is from ComAp, and the modifications done toke about 2 minutes https://youtu.be/J9WQsv_28Jw
|