打印

关于modbus

[复制链接]
1510|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
keer_zu|  楼主 | 2007-9-20 17:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用MEGA8写的modbus实现了一个功能 

还没有调试,请大家帮忙看看,第一次写通信程序,avr还不熟悉,不知道中断处理的如何。


主程序:

#include"485.h"
#include"modbus_client.h"

extern UINT16 Get_CRC ( BYTE *, BYTE);
extern void message_storage(BYTE *,BYTE,BYTE);
extern EQUIPMENT_PARAMETER EQUIPMENT_PARAMETER_TABLE[MAX_EQU_NUM];
//extern uchar T_flag;
//extern uchar buf_p;
//extern uchar Receive_now;         //在接收中断中,只要确认应答的设备地址正确就置位
                                   //
//===========================================
BYTE Receive_en;                   //接收使能
//===========================================                                   
BYTE WAIT_Responsion;              //等待应答:发送完一帧请求后置位,作为持续等待标志,
                                   //在接收中断中,如果接到这个设备的应答,只要地址正
                                   //就可以清除从而结束超时等待;
BYTE WAIT_Time;                    //
//===========================================
//  全局变量结构体
//===========================================
MB_INFORMATION      mb_infor;
//MASTER_INFORMATION  mas_infor;
ADU_CONTROL         adu;
//===========================================
//              超时错误
//===========================================
#define MAX_CHAOSHI  3
BYTE CHAOSHI_ErrTime[MAX_EQU_NUM];         //超时错误计数器  超过MAX_CHAOSHI次就要把
                          //EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQUIP_STATE
                          //变为ERR
//===========================================
//        帧错误
//===========================================
BYTE ZHEN_ErrTime[MAX_EQU_NUM];

int main(void)
{
    UINT16 CRC_BUF;
    BYTE CRC_CHAR;
    MESSAGE_ERR MESSAGE_err;
    //=================================================
    //                 变量初始化
    //=================================================
    WAIT_Time = 0;
    Receive_en =0;
    memset(TxAdu_buf,0,BUFSIZE);
    memset(RxAdu_buf,0,BUFSIZE);
    memset(CHAOSHI_ErrTime,0,MAX_EQU_NUM);
    memset(ZHEN_ErrTime,0,MAX_EQU_NUM);
//    Receive_now = 0;
//===========================================
    MB_INFORMATION_Init(&mb_infor);
//    MASTER_INFORMATION_Init( &mas_infor);
    ADU_CONTROL_Init(&adu);
    PORTd_INIT();
//===========================================
    cli();
    comInit();
    sei();
//    t_485("ni hao ma?\n");
//    t_485("Hello! da jia hao,wo shi tiao zao tuan zhang;\n");
    while(1)
    {
        begin:
        //&&&&&&&&&&&&&&&&&&&&&&&
        // 拼装帧 发送帧
        //&&&&&&&&&&&&&&&&&&&&&&&
        if(!EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQU_ADDR/*0代表没有设备*/ && EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQU_STATE/*设备无故障*/) 
        {
            adu.ADULength = 0;
            *(adu.TxADUBuffptr + adu.ADULength) = EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQU_ADDR;
                                                                          //地址
            adu.ADULength ++;
            *(adu.TxADUBuffptr + adu.ADULength) = 0x03;                    //功能号
            adu.ADULength ++;
            *(adu.TxADUBuffptr + adu.ADULength) = 0x00;                    
            adu.ADULength ++;
            *(adu.TxADUBuffptr + adu.ADULength) = EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW]. REG_ORIGINATION;
                                                                          //起始寄存器
            adu.ADULength ++;
            *(adu.TxADUBuffptr + adu.ADULength) = 0x00;
            adu.ADULength ++;
            *(adu.TxADUBuffptr + adu.ADULength) = EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].REG_NUM;
                                                                          //寄存器数量
            adu.ADULength ++;
            CRC_BUF = Get_CRC ( adu.TxADUBuffptr, adu.ADULength  ) ;
            CRC_CHAR = (BYTE)CRC_BUF;                                    
            *(adu.TxADUBuffptr + adu.ADULength) = (BYTE)(CRC_BUF >> 4);   //CRC校验高四位
            adu.ADULength ++;                                         
            *(adu.TxADUBuffptr + adu.ADULength) = CRC_BUF;                 //CRC校验低四位
            adu.ADULength ++;
            *(adu.TxADUBuffptr + adu.ADULength) = '\n';                    //在帧的结尾加上‘\n’做为发送结束标志
            t_485(adu.TxADUBuffptr);                                       //发送帧
            adu.ADULength = 0;
            WAIT_Responsion = 1;                                         //使能等待标志
            OPEN_WaitResponsionClk();                                    //打开超时计数器T0中断
            OPEN_USART1_ReINTERRUPT();                                   //打开接收中断
        }
        else     //如果设备不存在或设备故障转到下一台设备
        {
            if(++mb_infor.EQUIPMENT_NOW  > MAX_EQU_NUM)        //查询完一遍?
            mb_infor.EQUIPMENT_NOW = 0;                         //设备编号从0开始
            goto begin;
        }
        while(WAIT_Responsion)                                  //在接收中断中如果收到当前地址选中设备的应答则清除标志,跳出循环
        {
            if(WAIT_Time >= MAX_WAIT_TIME)                       //超时
            {
                //CLOSE_WaitResponsionClk();                      //关闭T0;
                WAIT_Time = 0;                                  //复位WAIT_Time
                CHAOSHI_ErrTime[mb_infor.EQUIPMENT_NOW] ++;     //超时错误计数器++
                if(CHAOSHI_ErrTime[mb_infor.EQUIPMENT_NOW] >= MAX_CHAOSHI)             //超过最大超时错误
                {
                    EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQU_STATE = ERR; //修改设备参数表中的状态,以后不再查询该设备
                    CHAOSHI_ErrTime[mb_infor.EQUIPMENT_NOW] = 0;                       //超时错误计数器清0
                }    
                if(++mb_infor.EQUIPMENT_NOW  > MAX_EQU_NUM)                            //设备查询过来一遍?
                mb_infor.EQUIPMENT_NOW = 0;                                             //设备编号从0开始
                WAIT_Responsion = 0;                                                    //重新初始化等待回应标志
                goto begin;
            }
        }
        //&&&&&&&&&&&&&&&&&&&&&&
        //接收除地址外的其他字节
        //&&&&&&&&&&&&&&&&&&&&&&
        for(;;)
        {
            while(!(UCSRA & (1<<RXC)))
            {
                if(mb_infor.T35_OUT)
                {
                    mb_infor.T35_OUT = FALSE;
                    WAIT_Time = 0;             //WAIT_Time复位
                    goto ZHEN_OVER;
                }
            }
            TCNT0 = 0x00;   //重新计数
            WAIT_Time = 0;  //中断次数清零
            delay_us(50);
            *(adu.RxADUBuffPtr + adu.ADULength) = UDR;
            adu.ADULength ++;
        }
        ZHEN_OVER:
        CLOSE_TIMER1(); //关定时器1
//================================================================
/*                   以下内容是帧处理:                            */
//================================================================
        MESSAGE_err = message_process(adu.RxADUBuffPtr,adu.ADULength);
        switch(MESSAGE_err)
        {
            case  CRC_ERR:  ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] ++;     //错误计数器++
                            if(ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] >= MAX_ZHENERR)                //超过最大超时错误
                            {
                                EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQU_STATE = ERR; //修改设备参数表中的状态,以后不再查询该设备
                                ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] = 0;                          //超时错误计数器清0
                            }
                            goto begin;
                            break;
            case  FUNC_ERR://&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
                            //   这里要分析错误代码 找到原因
                            //&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
                            ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] ++;     //错误计数器++
                            if(ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] >= MAX_ZHENERR)                //超过最大超时错误
                            {
                                EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQU_STATE = ERR; //修改设备参数表中的状态,以后不再查询该设备
                                ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] = 0;                          //超时错误计数器清0
                            }
                            break;
            case  LEN_ERR: ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] ++;     //错误计数器++
                            if(ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] >= MAX_ZHENERR)                //超过最大超时错误
                            {
                                EQUIPMENT_PARAMETER_TABLE[mb_infor.EQUIPMENT_NOW].EQU_STATE = ERR; //修改设备参数表中的状态,以后不再查询该设备
                                ZHEN_ErrTime[mb_infor.EQUIPMENT_NOW] = 0;                          //超时错误计数器清0
                            }
                            goto begin;
                            break;
            case  NO_ERR:   message_storage(adu.RxADUBuffPtr,mb_infor.EQUIPMENT_NOW,adu.ADULength);    //                   //存储帧
                            if(++mb_infor.EQUIPMENT_NOW  > MAX_EQU_NUM)                            //设备查询过来一遍?
                            mb_infor.EQUIPMENT_NOW = 0;                                             //设备编号从0开始
                            goto begin;
                            break;
        }
    }
}


 
 

相关帖子

沙发
keer_zu|  楼主 | 2007-9-20 17:50 | 只看该作者

呵呵,还请大家关注一下

使用特权

评论回复
板凳
keer_zu|  楼主 | 2007-9-20 17:55 | 只看该作者

怎么没人回?

使用特权

评论回复
地板
keer_zu|  楼主 | 2007-9-21 08:47 | 只看该作者

hehe

怎么没人看看啊

使用特权

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

本版积分规则

1338

主题

12373

帖子

53

粉丝