• AVR Freaks

Hot!Modbus RTU PIC18F Series

Author
AMPS
Super Member
  • Total Posts : 534
  • Reward points : 0
  • Status: offline
2019/07/05 21:28:11 (permalink)
0

Modbus RTU PIC18F Series

Dear all,
I am trying to implement Modbus RTU function code 1 on pic18F24k40 using 8mhz external crystal. I have used MCC code configurator for coding.I have few doubts . I am newbie to writing code here.But i have tried few things need some help to resolve the problem
 
1) weather CRC16 Error check can be written on MCU18 series. Or need to implement CRC8 function 8 bit controller.
2) I am trying to send some request but i am getting response in another passion.
Request  :[01][01][00][00][00][20][3d][d2]
Response :[01][d2][00][00][00][00][00][01] which is wrong. But still i am getting valid response why??
Is there any way or software available to check working of below code.
 
 

Attached Image(s)


Amps
*.*.*.*.*.*.*.*.*.*.*.*.*
#1

7 Replies Related Threads

    NKurzman
    A Guy on the Net
    • Total Posts : 18858
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: online
    Re: Modbus RTU PIC18F Series 2019/07/05 21:35:23 (permalink)
    0
    Yes you can do CRC16 on an 8 bit CPU.
    The slowest is bit by bit. Nibbles or bytes will be faster. But the tables take up a lot of code space.

    The are several CRC calculators on the Internet.
    #2
    AMPS
    Super Member
    • Total Posts : 534
    • Reward points : 0
    • Status: offline
    Re: Modbus RTU PIC18F Series 2019/07/06 03:58:40 (permalink)
    0
    Can someone check my code and let me know why i am getting valid response when i expected result something else.
    What are correction need to perform to make it work,

    Amps
    *.*.*.*.*.*.*.*.*.*.*.*.*
    #3
    AMPS
    Super Member
    • Total Posts : 534
    • Reward points : 0
    • Status: offline
    Re: Modbus RTU PIC18F Series 2019/07/06 04:11:15 (permalink)
    0
    Here is my code . The problem is in this part if i add below line only it start communicating. I have tested this code on p33FJ128GP706 module i wanted to modify the code for PIC18F24K40
     

    void UART_Receive(void) {
    unsigned char i,j;
    Device_ID =1;
    Rec_Data = RC1REG;
    uart_buf[Rx_Count] = Rec_Data;
    Rx_Count++;
    // This making line to print the value
    Serial_1_Send_byte( Rx_Count);
    Serial_1_Send_byte(uart_buf[0]);
    Serial_1_Send_byte(uart_buf[1]);
    Serial_1_Send_byte(uart_buf[2]);
    Serial_1_Send_byte(uart_buf[3]);
    Serial_1_Send_byte(uart_buf[4]);
    Serial_1_Send_byte(uart_buf[5]);
    Serial_1_Send_byte(uart_buf[6]);
    __delay_ms(100);

     
     

    #include "mcc_generated_files/mcc.h"
    #define LED_RX RC7 // Pin assigned RX LED
    #define LED_TX RC6 // Pin assigned TX LED
    #define LED RC3
    #define DE RC2
    #define RECEIVE 0
    #define TRANSMIT 1
    #define READ_REG 1
    #define WRITE_REG 6
    #define ILLEGAL_DATAVALUE 0x03
    #define FALSE 0
    #define TRUE 1
    #define METER_ID 1
    unsigned int j=0;
    unsigned char* str;
    unsigned int count = 0;
    char data = 0;
    unsigned char rxbuf[50], ser_data[100], crc_data[100], Max_scroll = 0;
    unsigned char buff[10];
    volatile uint8_t index = 0, rec_flag = 0, Delay_count = 0, Id[10], Buffer_count = 0, Cal_count = 0, Disp_count = 0, inc = 0, One_sec_update = 0, Auto_scroll_count = 0;
    char data1[10];
    unsigned char buf[20];
    unsigned char Fault[100];
    unsigned char Frame_Dly_flag,Transmit_flag;
    volatile union {
    unsigned char BYTEM;
    struct {
    unsigned slavid: 1; // flag of got slaveid ----- 00
    unsigned funcode:1; // flag of got functioncode ----- 00
    unsigned starthgh:1; // flag of got starthigh
    unsigned startlow:1; // flag of got startlow
    unsigned reghgh: 1; // flag of got register to read higher byte
    unsigned reglow: 1; // flag of got register to read lower byte
    unsigned chcksumlow: 1; // flag of got checksum lower byte
    unsigned chcksumhgh: 1; // flag of checksum higher byte
    unsigned Frame: 1; // flag of successfully received a frame, this flag is shared
    };
    unsigned char BYTE;
    struct {
    unsigned Head0: 1; // flag of got Header0 ----- 00
    unsigned Head1: 1; // flag of got Header1 ----- 00
    unsigned CMD: 1; // flag of got Data ID
    unsigned FrmLth: 1; // flag of got Frame Length
    unsigned DtFld: 1; // flag of got Data Field
    unsigned Chksum: 1; // flag of got Checksum
    unsigned End: 1; // flag of got the End of the frame
    unsigned Frame1: 1; // flag of successfully received a frame, this flag is shared
    // in other application,here it's the same as Rec_Flag.End
    };
    } Rec_Flag;
    unsigned char Device_match_M;
    unsigned char par_val[50];
    unsigned char Device_ID;
    unsigned char Rec_Data;
    unsigned char Command_ID; // Command type of current receiving frame
    unsigned char starthigh; // start high byte of current receiving frame
    unsigned char startlow; // start lower byte of current receiving frame
    unsigned char reghgh; // start higher byte of current receiving frame
    unsigned char reglow; // start lower byte of current receiving frame
    unsigned char chcksumhgh;
    unsigned char chcksumlow;
    float var;
    unsigned char start_byte;
    unsigned char byte_count;
    unsigned char ptr;
    unsigned char Data_Len_Count; // Length of current receiving frame
    unsigned char Check_Sum=0; // Current Checksum(receiving process)
    unsigned int Data_reg;
    unsigned char write_reg;
    unsigned char Check_Sumhgh=0;
    unsigned char Check_Sumlow=0;
    unsigned char crc_msb;
    unsigned char crc_lsb;
    //unsigned char Tx_Count; // transmit byte counter
    unsigned char *Tx_Ptr; // transmit buffer pointer
    unsigned char UART_Rx_Timer; // timer to count when every frame receiving begining
    unsigned char temp_id;
    unsigned char i;
    unsigned char para1,para2,para3;
    unsigned char temp_id;
    unsigned char uart_buf[20]; //receiving buffer,0xa0 is the max length of a frame
    unsigned int Rx_Count;
    unsigned int Tx_Count;
    void Blink_Count() {
    if(PIR4bits.TMR1IF == 1) {
    PIR4bits.TMR1IF =0;
    count=count+1;
    if(count>=20) {
    LED=!LED;
    count=0;
    }
    }
    }
    void Serial_1_Send_byte(uint8_t trbuf1) {
    TX1REG = trbuf1;
    while(0==TX1STAbits.TRMT);
    while (0 == PIR3bits.TXIF);
    PIR3bits.TXIF=0;
    //while (!TX1IF);
    }

    void ChecksumCal(char No_Bytes) {
    unsigned char highbyte,lowbyte;
    unsigned short crc,thisbyte,i,shift,lastbit;
    crc = 0xFFFF;
    No_Bytes = No_Bytes -1;
    for(i=0; i<=No_Bytes; i++) {
    thisbyte = uart_buf[i];
    crc = crc^thisbyte;
    for(shift=1; shift<=8; shift++) {
    lastbit = crc&0x0001;
    crc = (crc>>1)&0x7fff;
    if(lastbit==0x0001) {
    crc=crc^0xa001;
    }
    }
    }
    lowbyte = (crc>>8)&0xff;
    highbyte = crc & 0xff;
    crc_msb = highbyte;
    crc_lsb = lowbyte;
    }
    void Repeat_Relay_Transmit(unsigned char Tx_data ) {
    PIE3bits.TXIE = 1;
    DE= 1;//direction
    __delay_ms(2);
    EUSART_Write(Tx_data);
    __delay_ms(2);
    DE = 0; //direction
    PIR3bits.TXIF=0;
    PIE3bits.TXIE=0;
    }
    void UART_Transmit(void) {
    if(Device_match_M==1) {
    if(Tx_Count) { //if transmit buffer has data to send, send it out
    DE=1;
    if(Tx_Count > Data_Len_Count - 3) {
    EUSART_Write(uart_buf[Data_Len_Count-Tx_Count]);
    } else if(Tx_Count > 3) {
    EUSART_Write(*(Tx_Ptr));
    uart_buf[ptr]=*(Tx_Ptr);
    Tx_Ptr++;
    ptr++;
    } else if(Tx_Count ==3) {
    ChecksumCal(Data_Len_Count-3);
    EUSART_Write(crc_msb);
    } else if(Tx_Count == 2) {
    EUSART_Write(crc_lsb);
    } else if(Tx_Count == 1) {
    Tx_Ptr = 0;
    //PIE3bits.TXIE = 0; // Disable TXD interrupt
    PIE3bits.TXIE=0;
    PIR3bits.RCIF=0;
    __delay_ms(1);
    DE=0;
    PIE3bits.RC1IE=1;
    //IEC0bits.U1RXIE = 1; // Enable RxD Interrupt
    }
    Tx_Count--;
    }
    }
    }
    void UART_HandleRightFrame(unsigned char ucDt) {
    unsigned char i,j;
    unsigned char par,para1, para2, para3;
    unsigned int para4;
    extern unsigned char Device_ID;
    par_val[0] = 0b11111111;
    par_val[1] = 0X02;
    par_val[2] =0X00;
    par_val[3] = 0X00; // introduced for 4 bytes sending.
    Check_Sum = 0;
    uart_buf[0]=Device_ID;
    uart_buf[1]=1; //CHANGED TO 1
    uart_buf[2]=04; // changed t0 4 from 3 for 4 bytes data
    Tx_Count=(3+7); // changed from 6 to 7 for 4 bytes data
    Data_Len_Count=Tx_Count;
    ptr=3;
    Tx_Ptr = &par_val[(0)];
    TX1STAbits.TXEN=0;
    TX1STAbits.TXEN=1;
    UART_Transmit();
    PIE3bits.TXIE=1;
    }
     
     
    void UART_Receive(void) {
    unsigned char i,j;
    Device_ID =1;
    Rec_Data = RC1REG;
    uart_buf[Rx_Count] = Rec_Data;
    Rx_Count++;
    // This making line to print the value
    Serial_1_Send_byte( Rx_Count);
    Serial_1_Send_byte(uart_buf[0]);
    Serial_1_Send_byte(uart_buf[1]);
    Serial_1_Send_byte(uart_buf[2]);
    Serial_1_Send_byte(uart_buf[3]);
    Serial_1_Send_byte(uart_buf[4]);
    Serial_1_Send_byte(uart_buf[5]);
    Serial_1_Send_byte(uart_buf[6]);
    __delay_ms(100);

    if(Rx_Count > 8) {
    Rx_Count = 0;
    Rec_Flag.BYTEM = 0; // The data being received is not header1, back to non-receive status
    starthigh =0;
    Check_Sum = 0;
    UART_Rx_Timer =0;
    return;
    }

    if(!Rec_Flag.slavid) { // Not got header0 --- 0x00
    if((Rec_Data == Device_ID)&&(Device_ID>0)) {
    Device_match_M=1;
    Rec_Flag.slavid = 1; // Indicating header0 got
    Check_Sum = 0;
    } else {
    Device_match_M = 0;
    Rx_Count = 0;
    Rec_Flag.BYTEM = 0; // The data being received is not header1, back to non-receive status
    starthigh =0;
    Check_Sum = 0;
    UART_Rx_Timer =0;
    }
    }
    else if(!Rec_Flag.funcode) { // Not got header1--- 0xff
    if(Rec_Data == 1) { // CHANGED T0 01
    Rec_Flag.funcode = 1;
    }
    // Indicating header1 got
    else {
    Rec_Flag.BYTEM = 0;
    starthigh = 0; // The data being received is not header1, back to non-receive status
    Check_Sum = 0;
    UART_Rx_Timer =0;
    Rx_Count = 0;
    }
    }
    else if(starthigh==0) { // Not got ID
    //UART_Rx_Timer =1;
    if(Rec_Data == 0x00) {
    asm("nop");
    starthigh = 1; // Indicating header1 got
    } else {
    Rec_Flag.BYTEM = 0;
    starthigh = 0; // The data being received is not header1, back to non-receive status
    Check_Sum = 0;
    UART_Rx_Timer =0;
    Rx_Count = 0;
    }
    }
    else if(!Rec_Flag.startlow) { // Not got ID
    // aaudge the ID legality here
    Rec_Flag.startlow = 1;
    //UART_Rx_Timer =1;
    uart_buf[3]= Rec_Data;
    start_byte= uart_buf[3];
    }
    else if(!Rec_Flag.reghgh) { // Not got ID
    UART_Rx_Timer =1;
    if(Rec_Data == 0) {
    Rec_Flag.reghgh = 1; // Indicating header1 got
    uart_buf[4]= Rec_Data;
    } else {
    Rec_Flag.BYTEM = 0; // The data being received is not header1, back to non-receive status
    starthigh = 0;
    Check_Sum = 0;
    UART_Rx_Timer =0;
    Rx_Count = 0;
    }
    }
    else if(!Rec_Flag.reglow) {
    Rec_Flag.reglow= 1;
    UART_Rx_Timer =1;
    uart_buf[5]= Rec_Data;
    Data_reg=uart_buf[5];
    }
    else if(!Rec_Flag.chcksumlow) {
    Rec_Flag.chcksumlow = 1; // Check_Sum has aaust xored with the received checksum
    uart_buf[6]= Rec_Data;
    }
    else if(!Rec_Flag.chcksumhgh) {
    Rec_Flag.chcksumhgh = 1;
    uart_buf[7]= Rec_Data;
    ChecksumCal(6);
    if((uart_buf[6]==crc_msb)&&(uart_buf[7]==crc_lsb)) {
    Rec_Flag.BYTEM = 0;
    starthigh = 0;
    Frame_Dly_flag=1;
    Rx_Count = 0;
    8 bit PIE3bits.RCIE=0;
    } else {
    Rec_Flag.BYTEM = 0;
    starthigh = 0; // The data being received is not header1, back to non-receive status
    Check_Sum = 0;
    Rx_Count = 0;
    }
    UART_Rx_Timer =0;
    }
    }
     
     

    void process_UART( void) {
    unsigned char i =0;
    if(Tx_Count)
    PIE3bits.TXIE = 1; //enable TX interrupt
    else
    PIE3bits.TXIE = 0; //enable TX interrupt
    if(Transmit_flag == 1) { //modified for RIl
    Rec_Flag.Frame = 1;
    Transmit_flag = 0;
    }

    if(Rec_Flag.Frame) { // if successfully received a frame?
    Rec_Flag.BYTE = 0;
    Rec_Flag.BYTEM = 0;
    starthigh = 0;
    Check_Sum = 0;
    Rx_Count = 0;
    UART_HandleRightFrame(0); // pass the Data ID of the frame so as to be able to receive next frame while handling current frame
    }
    if(RCSTAbits.FERR) {
    RCSTAbits.FERR= 0;
    starthigh = 0;
    Rec_Flag.BYTE = 0;
    Rec_Flag.BYTEM = 0;
    Check_Sum = 0;
    Rx_Count = 0;
    }
    if(RCSTAbits.OERR) {
    RCSTAbits.OERR = 0;
    PIE3bits.RCIE=1;
    starthigh = 0;
    Rec_Flag.BYTE = 0;
    Rec_Flag.BYTEM = 0;
    Check_Sum = 0;
    Rx_Count = 0;
    }
    }

    void UART_ISR() {
    if( PIR0bits.TMR0IF ==1) {
    PIR0bits.TMR0IF= 0;
    TMR0 =250;
    //Fault_Check();
    Disp_count=Disp_count+1;
    if(Disp_count>150) {

    }
    if(DE==1) {
    UART_Transmit();
    }
    }
    }
    void Dummy_Stuck() {
    while(1); /* wait till watchdog timeout and then reset system */
    }
     
     
    void main(void) {
    // Initialize the device
    SYSTEM_Initialize();
    INTCONbits.GIE=1;
    INTCONbits.PEIE=1;
    DE=1;
    unsigned char c=0;
    WDTCON0bits.SEN=1;
    while (1) {
    process_UART();
    /*Repeat_Relay_Transmit(0X01);
    Repeat_Relay_Transmit(0x01);
    Repeat_Relay_Transmit(0X00);
    */
    UART_Receive();
    __delay_ms(10);
    }
     
    }
     

     

    Amps
    *.*.*.*.*.*.*.*.*.*.*.*.*
    #4
    marjian
    New Member
    • Total Posts : 12
    • Reward points : 0
    • Joined: 2015/05/15 12:06:16
    • Location: 0
    • Status: offline
    Re: Modbus RTU PIC18F Series 2019/08/28 01:28:05 (permalink)
    0
    Hi AMPS.
    I have the same problem with MODBUS RTU. MCC v3 under MPLAB v5.2 have library for RS485 interface (Micro-E Click/Interface/RS485), but it include only usart function for write and read. On MIKRO-E you can download Modbus RTU slave/master library  https://www.mikroe.com/rs485-5v-click 
    Unfortunately for me it's not easy to convert to XC8 and split together with MCC.
    I don't understand Microchip strategy: why they don't share ready library for 8 bit microcontrollers like do Arduino or Mikro E. Not everyone want to use PIC32 and harmony.
     
    Anyway, if you sort out your problem could you share your code please?
    #5
    AMPS
    Super Member
    • Total Posts : 534
    • Reward points : 0
    • Status: offline
    Re: Modbus RTU PIC18F Series 2019/09/06 00:02:30 (permalink)
    0
    I cant share my code. But i sorted out my problem. If u using MCC take care of MCC generated file properly. I am doing mistake in MCC generated Esuart Library. Just comment out Esuart ISR function and Follow the same step like you doing in Hitech Compiler. 
    This small technique i have done. Let me know which controller u r using. what FC you want to write code. I may can support portion only.
    if u send code/schmatic i can check if any issue with ur functions.
    Let me know if u success in basic Uart/UART ISR function get worked.
    if using MircoE IDE/compilers
    Code are proven.So it might be your hardware issue.

    Amps
    *.*.*.*.*.*.*.*.*.*.*.*.*
    #6
    AMPS
    Super Member
    • Total Posts : 534
    • Reward points : 0
    • Status: offline
    Re: Modbus RTU PIC18F Series 2020/07/07 20:33:17 (permalink)
    0
    Dear all
     
    I am using pic18f45k40 with non-isolated https://www.ti.com/lit/ds/symlink/sn75176b.pdf?ts=1594171410151&ref_url=https%253A%252F%252Fwww.google.com%252F       SN75176BDR IC for Rs485 communication. I have written simple code with FC1 where i could able to communicate with multiple slave device . i am getting valid response for each salve.
    I have connected Converter A to RS485 A and   converter B to RS485 B .  this way it wont give any issue while communication. 
    Now i interchanged Converter A to RS485 B  & converter A to RS485 A this way connected . By doing this it stop the product working. if Reconnect reverse and reset power it will start working properly without any issue. IS it possible to provide reason why it doing it weather its hardware or Software related issue.
     
    if it software related issue .. how should i tracj 

    Amps
    *.*.*.*.*.*.*.*.*.*.*.*.*
    #7
    ric
    Super Member
    • Total Posts : 28009
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Modbus RTU PIC18F Series 2020/07/07 20:46:45 (permalink)
    0
    ajitnayak87
    I have written simple code with FC1 where i could able to communicate with multiple slave device .

    what is "FC1" ?
     

    I have connected Converter A to RS485 A and   converter B to RS485 B .  this way it wont give any issue while communication.

    What on earth does this mean?
    Can you show a schematic?
     

    Now i interchanged Converter A to RS485 B  & converter A to RS485 A this way connected .

    Still don't understand what you are trying to say, but it doesn't sound good.
    If you are talking about the bus connections on the transceiver chip (A and B), all the "A" pins should connect to each other, and all the B pins should connect to each other. You should NOT reverse them.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #8
    Jump to:
    © 2020 APG vNext Commercial Version 4.5