TEL:0755-32882616   公司简介 - 委托交易 - 收费标准 - 汇款方式 - 联系我们 - 免责申明 - 站点地图

设为桌面图标 | 设为首页 | 加入收藏夹 | IC型号 | 黑名单

   当前位置: IC37首页 > 博士 > 热帖推荐

我写了个实现一种功能的modbus的主机


用户名:keer_zu
注册时间:2007-9-20 17:08:00
楼主  发布时间:2013-3-13 17:12:21    点击率:5242

我写了个实现一种功能的modbus的主机

#ifndef_MB_CLIENT

#define_MB_CLIENT

#include

#include

#include

#include"485.h"

#defineTRUE1

#defineFALSE0

#defineUINT16unsignedint

#defineBYTEunsignedchar

#defineMAX_EQU_NUM3//现在使用3个设备

#defineOK1

#defineERR0

//===================================================================

//错误常量

//===================================================================

#defineCHAOSHI0XFF

//===================================================================

//设备数据结构用于构建设备参数表

typedefstruct_EQUIPMENT_PARAMETER

{

BYTEEQU_ADDR;//设备地址

BYTEEQU_TYPE;//设备类型

BYTEEQU_STATE;//设备状态

BYTEREG_ORIGINATION;//起始寄存器地址

BYTEREG_NUM;//寄存器数量

}EQUIPMENT_PARAMETER;

//ADU处理信息结构

typedefstruct_ADU_CONTROL

{

BYTEAddress;//地址域

BYTE*RxADUBuffPtr;//指向ADU发送缓冲区的指针

BYTE*TxADUBuffptr;//指向ADU接收缓冲区的指针

BYTEADULength;//ADU数据长度

BYTEFrameOK;//如果该ADU报文有效(地址有效,奇偶、CRC校验通过)则TRUE

}ADU_CONTROL;

//通信状态

typedefstruct_MB_INFORMATION

{

BYTEEQUIPMENT_NOW;//当前正在处理设备编号

//enum_MODBUS_STATEMODBUS_STATE;//描述modbus状态的变量

BYTET15_OUT;//1.5ms延时到

BYTET35_OUT;//3.5ms延时到

BYTETO_times;//时钟中断次数计数器

}MB_INFORMATION;

//帧错误类型

typedefenum_MESSAGE_ERR

{

CRC_ERR,//CRC校验错

FUNC_ERR,//功能号错-应该处理错误类型

LEN_ERR,//长度错

NO_ERR//没有错误

}MESSAGE_ERR;

//=====================================================================================

voidMB_INFORMATION_Init(MB_INFORMATION*);

//voidMASTER_INFORMATION_Init(MASTER_INFORMATION*);

voidADU_CONTROL_Init(ADU_CONTROL*);

MESSAGE_ERRmessage_process(BYTE*,BYTE);

#endif


用户名:keer_zu
注册时间:2007-9-20 17:11:00
1楼  发布时间:2013-3-13 17:12:21
#include "modbus_client.h"
#ifndef _PGM
#define _PGM
#include <avr/pgmspace.h>
#endif
//=========================================
//          返回CRC校验结果
//=========================================
extern unsigned int Get_CRC(BYTE *,BYTE);
//=========================================
//                 缓冲区
//=========================================
extern ADU_CONTROL adu;
extern MB_INFORMATION      mb_infor;
extern BYTE WAIT_Time,Receive_en,WAIT_Responsion;

//========================================================================
//   设备参数表
//========================================================================
EQUIPMENT_PARAMETER EQUIPMENT_PARAMETER_TABLE[MAX_EQU_NUM]=
{
  {0X09,0,OK,0,0x15},             //1、地址 2、类型 3、状态 4、起始寄存器 5、寄存器数量(十六位,两个字节)
  {0x02,1,OK,0,0x0f},
  {0x11,0,OK,0,0x15}/*,
  {0x00,0,OK,0,0},
  {0x00,0,OK,0,0}*/
};

//==========================================================================
// 定时计数器1溢出中断函数
//==========================================================================
ISR(SIG_OVERFLOW1)
{
    TCNT1 = 0xf70c;          //4M时0.5个字符-0.000573s产生一个中断
    mb_infor.TO_times ++;
    if(mb_infor.TO_times == 3)mb_infor.T15_OUT = TRUE;    //1.5ms延时到
    if(mb_infor.TO_times == 7)
    {
        mb_infor.T35_OUT = TRUE;    //3.5ms延时到
        CLOSE_TIMER1();                                        //关定时器
    }
}
//==========================================================================
// 定时计数器0溢出中断函数
//==========================================================================
ISR(SIG_OVERFLOW0)
{
    WAIT_Time ++;
    if(WAIT_Time >= MAX_WAIT_TIME)              
    {
        //WAIT_Time = MAX_WAIT_TIME;
        CLOSE_WaitResponsionClk();  //关T0中断
        OPEN_USART1_ReINTERRUPT();  //关接收中断
    }
    else
    TCNT0 = 0x00;                   //重新装入计数器初值
}
//==========================================================================
// USART接收中断函数
//==========================================================================
ISR(SIG_UART_RECV)    //串口接受中断
{
    BYTE Rdata;
    Rdata = UDR;
    if(Rdata == EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQU_ADDR)    //是当前等待帧
    {
        WAIT_Responsion = 0;                                                    //结束超时判断
        Receive_en = 1;                                                         //使能接收
        adu.ADULength = 0;
        *(adu.RxADUBuffPtr + adu.ADULength) = Rdata;                           //为了CRC计算方便,还是要在缓冲区存储整个PDU帧
        adu.ADULength ++;
        CLOSE_USART1_ReINTERRUPT();                                             //关接收中断
        OPEN_TIMER1();                                                          //开定时器T1
    }
//    delay_us(40);                   //退出时启动定时器
}
//===========================================================================
//       初始化函数
//===========================================================================
//modbus状态
void MB_INFORMATION_Init(MB_INFORMATION *MBi)
{
    MBi -> EQUIPMENT_NOW = 0;                         //初始化时,从第0台设备开始
//    MBi -> MODBUS_STATE = (enum _MODBUS_STATE)0;     
    MBi -> T15_OUT = FALSE;
    MBi -> T35_OUT = FALSE;
    MBi -> TO_times = 0;
}

void ADU_CONTROL_Init(ADU_CONTROL *adu)   
{
    adu -> Address = 0;
    adu -> TxADUBuffptr = TxAdu_buf;
    adu -> RxADUBuffPtr = RxAdu_buf;
    adu -> ADULength = 0;
    adu -> FrameOK = FALSE;
}
//================================================================================
// 接收帧的处理;
// 参数:  1.要处理帧的指针  2.要处理帧的长度
//================================================================================
MESSAGE_ERR  message_process(BYTE *Message,BYTE len)
{
    unsigned int CRC_data,RX_crc;
    RX_crc = *(adu.RxADUBuffPtr + adu.ADULength - 2)/*CRC高位*/*256 + *(adu.RxADUBuffPtr + adu.ADULength - 1)/*CRC低位*/;
    CRC_data = Get_CRC (adu.RxADUBuffPtr,adu.ADULength - 2);      //计算CRC校验
    if(CRC_data == RX_crc)                                        //CRC校验正确
    {
        if(bit_is_clear(*(adu.RxADUBuffPtr + 1),7))              //功能码返回正确?
        {
            if(*(adu.RxADUBuffPtr + 2) == adu.ADULength - 5)     //
            {
                return NO_ERR;
            }
            else
            return LEN_ERR;
        }
        else
        return FUNC_ERR;
    }
    else
    return CRC_ERR;
}


用户名:jinshan2000
注册时间:2009-3-30 21:49:00
2楼  发布时间:2013-3-13 17:12:21
辛苦了,下去仔细看看。
热门型号:
UC3843AD1 UCC5950 UDZSTE-172.7B ULN2003ADRG3 UPA1524H UPA1802GR-9JG-E1 UPB587G-E1 UPC1215V UPC1458G2-E2 UPC1477C