打印
[开发工具]

MODBUS精简版对比!

[复制链接]
1972|22
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Diyer2015|  楼主 | 2018-12-17 12:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MODBUS精简版

#include <all.h>


void main()
{
   P5M0 = 0;
   P5M1 = 0;
   P3M0 = 0;
   P3M1 = 0;
   UartInit();           //9600bps@11.0592MHz
   Modbus_Init();  //利用定时器2来计算数据帧 定时1MS
   while(1)
   {
           Modbus_data_Decode();
   }
}


沙发
Diyer2015|  楼主 | 2018-12-17 12:34 | 只看该作者
#include <STC15.h>

#include "UART.h"
#include "MODBUS_Drive.h"

使用特权

评论回复
板凳
Diyer2015|  楼主 | 2018-12-17 12:34 | 只看该作者
#ifndef UART
#define UART




extern void UartInit(void);                //9600bps@11.0592MHz





#endif

使用特权

评论回复
地板
Diyer2015|  楼主 | 2018-12-17 12:34 | 只看该作者
#ifndef MODBUS_Drive
#define        MODBUS_Drive


extern void Modbus_Init();
extern void Modbus_Read_Drive();
extern void Modbus_data_Decode();


extern unsigned char xdata Modbus_Read_Buffer[256];
extern unsigned char xdata Modbus_Write_Buffer[256];
extern unsigned char Modbus_Read_Complete;
extern unsigned int Modbus_Read_Value;
extern unsigned int Modbus_Write_Value;
extern unsigned char Modbus_Read_Complete;


#endif

使用特权

评论回复
5
Diyer2015|  楼主 | 2018-12-17 12:34 | 只看该作者
#include <all.h>







void UartInit(void);                //9600bps@11.0592MHz



void UartInit(void)                //9600bps@11.0592MHz
{
        SCON = 0x50;                //8位数据,可变波特率
        AUXR |= 0x40;                //定时器1时钟为Fosc,即1T
        AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
        TMOD &= 0x0F;                //设定定时器1为16位自动重装方式
        TL1 = 0xE0;                //设定定时初值
        TH1 = 0xFE;                //设定定时初值
        ET1 = 0;                //禁止定时器1中断
        TR1 = 1;                //启动定时器1
        EA = 1;
        ES = 1;
}


void UART1_Rountine(void) interrupt 4        //串口1
{
       

        if(RI)
        {       
                 RI = 0;               
                Modbus_Read_Buffer[Modbus_Read_Value++] = SBUF;
        }

        if(TI)
        {
                TI = 0;
        }
       
       
       
}






使用特权

评论回复
6
Diyer2015|  楼主 | 2018-12-17 12:35 | 只看该作者
#include <all.h>

unsigned char xdata Modbus_Read_Buffer[256] = 0;  //数据接收缓冲区
unsigned char xdata Modbus_Write_Buffer[256] = 0; //数据发送缓冲区

unsigned int Modbus_Read_Value = 0;        //接收字节计数
unsigned int Modbus_Write_Value = 0;  //发送字节计数
unsigned char Modbus_Read_Complete = 0; //帧接收完成标志位

unsigned int Modbus_CRC_Cecode(unsigned char *puchMsg, unsigned int usDataLen);        //CRC校验
void Modbus_Init();        //帧检测定时器
void Modbus_data_Decode();


void Modbus_Init()//利用定时器2来计算数据帧 定时1MS
{
        AUXR |= 0x04;//定时器2用作定时,不分频
        IE2 |= 0x04;//允许定时器2中断
        T2L = 0xCD;                //设置定时初值
        T2H = 0xD4;                //设置定时初值
        EA = 1;  //开总中断
        AUXR |= 0x10;
}

使用特权

评论回复
7
Diyer2015|  楼主 | 2018-12-17 12:35 | 只看该作者
unsigned int Modbus_CRC_Cecode(unsigned char *puchMsg, unsigned int usDataLen)
{
       
         unsigned int i,j,CRC_Reg,Check;
         CRC_Reg = 0xFFFF;
         for(i=0;i<usDataLen;i++)
         {
                CRC_Reg = CRC_Reg ^ (unsigned int)*(puchMsg + i);
                for(j=0;j<8;j++)
                {
                        Check = CRC_Reg & 0x0001;
                        CRC_Reg >>= 1;
                        if(Check==0x0001)
                        {
                                CRC_Reg ^= 0xA001;
                        }
                }
         }
         
         return CRC_Reg;
}

使用特权

评论回复
8
Diyer2015|  楼主 | 2018-12-17 12:35 | 只看该作者
void Modbus_data_Decode()
{
         unsigned int CRC_Data,i;
         unsigned char CRC_H, CRC_L;
         
        if(Modbus_Read_Complete)
        {

                 EA = 0;
                 Modbus_Read_Complete = 0;

                 CRC_Data = Modbus_CRC_Cecode(Modbus_Read_Buffer,Modbus_Read_Value-2);
       
                 CRC_H = CRC_Data >> 8;
                 CRC_L = CRC_Data & 0x00ff;

       
                 if((CRC_H == Modbus_Read_Buffer[Modbus_Read_Value-1]) && (CRC_L == Modbus_Read_Buffer[Modbus_Read_Value-2]))

                 {
                         //这里可以开始分析数据 程序进入这里就证明CRC检验已经通过了

                        Modbus_Write_Value = 0; //清除发送直接计数 ,调试用
                         for(i = 0; i < (Modbus_Read_Value-2); i++)         //调试用主要把接收的数据发送出去
                        {

                                Modbus_Write_Buffer[i] = Modbus_Read_Buffer[i];         //调试用
                                Modbus_Write_Value++;                                                    //调试用
                        }

                 }
                 Modbus_Write_Buffer[Modbus_Write_Value] = CRC_L;          //调试用
                 Modbus_Write_Value++;                                                                  //调试用
                 Modbus_Write_Buffer[Modbus_Write_Value] = CRC_H;           //调试用
                 Modbus_Read_Value = 0;                //接收直接数清零                                                  
                 
                 EA = 1;
                 for(i = 0; i <= Modbus_Write_Value; i++)                 //调试用
                 {
                         SBUF = Modbus_Write_Buffer[i];                          //调试用
                        while(!TI);                                                                  //调试用
                 }
                 Modbus_Write_Value = 0;                                          //调试用
                 
         }
}

使用特权

评论回复
9
Diyer2015|  楼主 | 2018-12-17 12:36 | 只看该作者
/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
void UartRxMonitor(unsigned char ms)
{
    static unsigned char cntbkp = 0;
    static unsigned char idletmr = 0;

    if (Modbus_Read_Value > 0)  //接收计数器大于零时,监控总线空闲时间
    {
        if (cntbkp != Modbus_Read_Value)  //接收计数器改变,即刚接收到数据时,清零空闲计时
        {
            cntbkp = Modbus_Read_Value;
            idletmr = 0;
        }
        else                   //接收计数器未改变,即总线空闲时,累积空闲时间
        {
            if (idletmr < 2)  //空闲计时小于30ms时,持续累加
            {
                idletmr += ms;
                if (idletmr >= 2)  //空闲时间达到2ms时,即判定为一帧接收完毕
                {
                                        Modbus_Read_Complete = 1;  //设置帧接收完成标志
                }
            }
        }
    }
    else
    {
        cntbkp = 0;
    }
}

使用特权

评论回复
10
Diyer2015|  楼主 | 2018-12-17 12:36 | 只看该作者
void Timer2_Routine() interrupt 12
{
        UartRxMonitor(1);
       
}

使用特权

评论回复
11
Diyer2015|  楼主 | 2018-12-17 12:36 | 只看该作者
#include <all.h>

unsigned char xdata Modbus_Read_Buffer[256] = 0;  //数据接收缓冲区
unsigned char xdata Modbus_Write_Buffer[256] = 0; //数据发送缓冲区

unsigned int Modbus_Read_Value = 0;        //接收字节计数
unsigned int Modbus_Write_Value = 0;  //发送字节计数
unsigned char Modbus_Read_Complete = 0; //帧接收完成标志位

unsigned int Modbus_CRC_Cecode(unsigned char *puchMsg, unsigned int usDataLen);        //CRC校验
void Modbus_Init();        //帧检测定时器
void Modbus_data_Decode();


void Modbus_Init()//利用定时器2来计算数据帧 定时1MS
{
        AUXR |= 0x04;//定时器2用作定时,不分频
        IE2 |= 0x04;//允许定时器2中断
        T2L = 0xCD;                //设置定时初值
        T2H = 0xD4;                //设置定时初值
        EA = 1;  //开总中断
        AUXR |= 0x10;
}



unsigned int Modbus_CRC_Cecode(unsigned char *puchMsg, unsigned int usDataLen)
{
       
         unsigned int i,j,CRC_Reg,Check;
         CRC_Reg = 0xFFFF;
         for(i=0;i<usDataLen;i++)
         {
                CRC_Reg = CRC_Reg ^ (unsigned int)*(puchMsg + i);
                for(j=0;j<8;j++)
                {
                        Check = CRC_Reg & 0x0001;
                        CRC_Reg >>= 1;
                        if(Check==0x0001)
                        {
                                CRC_Reg ^= 0xA001;
                        }
                }
         }
         
         return CRC_Reg;
}
void Modbus_data_Decode()
{
         unsigned int CRC_Data,i;
         unsigned char CRC_H, CRC_L;
         
        if(Modbus_Read_Complete)
        {

                 EA = 0;
                 Modbus_Read_Complete = 0;

                 CRC_Data = Modbus_CRC_Cecode(Modbus_Read_Buffer,Modbus_Read_Value-2);
       
                 CRC_H = CRC_Data >> 8;
                 CRC_L = CRC_Data & 0x00ff;

       
                 if((CRC_H == Modbus_Read_Buffer[Modbus_Read_Value-1]) && (CRC_L == Modbus_Read_Buffer[Modbus_Read_Value-2]))

                 {
                         //这里可以开始分析数据 程序进入这里就证明CRC检验已经通过了

                        Modbus_Write_Value = 0; //清除发送直接计数 ,调试用
                         for(i = 0; i < (Modbus_Read_Value-2); i++)         //调试用主要把接收的数据发送出去
                        {

                                Modbus_Write_Buffer[i] = Modbus_Read_Buffer[i];         //调试用
                                Modbus_Write_Value++;                                                    //调试用
                        }

                 }
                 Modbus_Write_Buffer[Modbus_Write_Value] = CRC_L;          //调试用
                 Modbus_Write_Value++;                                                                  //调试用
                 Modbus_Write_Buffer[Modbus_Write_Value] = CRC_H;           //调试用
                 Modbus_Read_Value = 0;                //接收直接数清零                                                  
                 
                 EA = 1;
                 for(i = 0; i <= Modbus_Write_Value; i++)                 //调试用
                 {
                         SBUF = Modbus_Write_Buffer[i];                          //调试用
                        while(!TI);                                                                  //调试用
                 }
                 Modbus_Write_Value = 0;                                          //调试用
                 
         }
}

/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
void UartRxMonitor(unsigned char ms)
{
    static unsigned char cntbkp = 0;
    static unsigned char idletmr = 0;

    if (Modbus_Read_Value > 0)  //接收计数器大于零时,监控总线空闲时间
    {
        if (cntbkp != Modbus_Read_Value)  //接收计数器改变,即刚接收到数据时,清零空闲计时
        {
            cntbkp = Modbus_Read_Value;
            idletmr = 0;
        }
        else                   //接收计数器未改变,即总线空闲时,累积空闲时间
        {
            if (idletmr < 2)  //空闲计时小于30ms时,持续累加
            {
                idletmr += ms;
                if (idletmr >= 2)  //空闲时间达到2ms时,即判定为一帧接收完毕
                {
                                        Modbus_Read_Complete = 1;  //设置帧接收完成标志
                }
            }
        }
    }
    else
    {
        cntbkp = 0;
    }
}



void Timer2_Routine() interrupt 12
{
        UartRxMonitor(1);
       
}

使用特权

评论回复
12
Diyer2015|  楼主 | 2018-12-17 12:37 | 只看该作者
附件!

MODBUS调试.rar

46.66 KB

使用特权

评论回复
13
磨砂| | 2019-1-1 10:56 | 只看该作者
MODBUS是什么总线啊

使用特权

评论回复
14
晓伍| | 2019-1-1 11:03 | 只看该作者

MODBUS 是不是就是485通讯啊

使用特权

评论回复
15
八层楼| | 2019-1-1 11:10 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
16
观海| | 2019-1-1 16:11 | 只看该作者
好详细 感谢分享

使用特权

评论回复
17
guanjiaer| | 2019-1-1 16:16 | 只看该作者
其实就是串口通讯吧

使用特权

评论回复
18
heimaojingzhang| | 2019-1-1 16:22 | 只看该作者
哪里精简了啊  不就是串口的通讯吗

使用特权

评论回复
19
keaibukelian| | 2019-1-1 16:27 | 只看该作者
非常感谢分享 很详细

使用特权

评论回复
20
Diyer2015|  楼主 | 2019-1-2 09:20 | 只看该作者
比起freemodbus 还是非常精简的!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

63

主题

1615

帖子

13

粉丝