载波通信模块的代码分析

struct PLC_STATE 
{
    uint8 cur_state;
    uint8 next_state;


    uint8 (*action)(uint8 init, void *args);//这个结构体是怎么用的
                                            
};
void plc_machine_opt(void *args)
{
    struct PLC_STATE *pstate = plc_state.pstate;//关键是看看谁改变了 plc_state.pstate,找到了谁改变了它,就是把上游的数据打通了。
    uint8 init;


    init = plc_state.init;
    if(init) plc_state.wait_t=0;
    plc_state.init = 0;
    if(NULL != pstate)
    {
        pstate->action(init, args);调用完这个他又调用的哪里的代码????
    }
}

经过在代码中的查找我们可以清楚的看到,是void chg_state(uint8 cur_state)改变了plc _state.pstate的值。改变的部分如下红色代码所示。
void chg_state(uint8 cur_state)
{
    uint8 i;
    static uint8 last_state=INVALID;
    
    plc_state.wait_t = 0;
    plc_state.init=1;
    for(i = 0; i < PLC_SLOT_SZ; i++)
    {
        if(plc_state_slot[i].cur_state == cur_state)
        {
            plc_state.pstate = (struct PLC_STATE *)&plc_state_slot[i];
            break;
        }
    }
    if(i >= PLC_SLOT_SZ)
    {
        plc_state.pstate = (struct PLC_STATE *)&plc_state_slot[0];
    }


    if(last_state != plc_state.pstate->cur_state)
    {
        plc_state.trycnt = 0;
    }
    last_state = plc_state.pstate->cur_state;
    notify(EV_STATE);
}


我们会不知不觉的考虑到谁调用了void chg_state(uint8 cur_state)
调用的上述函数的代码如下红色所示
void sys_init(void)
{


    /*初始化状态机参数*/
    memset_my(&plc_state, 0x00, sizeof(plc_state));
    memset_my(&reg, 0x00, sizeof(reg));
    reg.type = PASSWORD_REG;//上电密码注册
    chg_state(RST_PLC);//这是一个复位操作
    //chg_state(_END);//noly for debug
    memset_my(g_frame_buffer, 0x00, sizeof(g_frame_buffer));
    ir_eng.g_ir_state = IR_IDLE;
}


static void chk_plc_alive(void)
{
    if(rst_plc_t > 120)//2小时没有通信,复位载波芯片
    {
        rst_plc_t = 0;
        chg_state(RST_PLC);
    }
    else if((60 == rst_plc_t) || (120 == rst_plc_t))
    {//读取载波EID
        get_ID(CMD_GET_EID, g_frame_buffer);
    }
}


/**********************************************
设备注册:1、第一次注册不使用密码; 
          2、第二次以后注册,与原记录的网关号相同不使用密码
          3、第二次以后注册,新网关拉取设备需要使用设备密码
***********************************************/
static uint8 get_reg(struct SHS_frame *pframe)
{
    uint8 need_wr=1;




    if(PASSWORD_REG == reg.type)
    {
        if(UNVALID_DATA == eep_param.panid_flag)
        {//第一次注册,不判段密码
        }
        else if((VALID_DATA == eep_param.panid_flag)
           && (0x00 == memcmp_my(eep_param.panid, &pframe->infor[1], PANID_LEN)))
        {//成功注册完成后,再次启动注册,只判断panid
            need_wr = 0;
        }
        else if((eep_param.pwd_magic == VALID_DATA)
                && (0x00 != memcmp_my(eep_param.password, &pframe->infor[PANID_LEN+1], PWD_LEN)))
        {//判断是否是已经注册成功的panid
            reg.last_status = PASSWORD_ERR;
            chg_state(PWD_ERR);
            return(0);
        }
    }
    //成功,设置密码注册成功




    reg.type = PASSWORD_REG;
    chg_state(G_GWID);//读取网关aid




    if(need_wr)
    {
        mymemcpy(eep_param.panid, &pframe->infor[1], PANID_LEN);
        eep_param.panid_flag = VALID_DATA;
        EEP_Write(OF_PLC_PARAM, (uint8 *)&eep_param, sizeof(eep_param));
    }
    return(0);
}
#if 0
{
    uint8 need_wr=1;




    if(PASSWORD_REG == reg.type)
    {
        if(INVALID_DATA == eep_param.panid_flag)
        {//第一次注册,不判段密码
        }
        else if((VALID_DATA == eep_param.panid_flag)
           && (0x00 == memcmp_my(eep_param.panid, &pframe->infor[1], PANID_LEN)))
        {//成功注册完成后,再次启动注册,只判断panid
            need_wr = 0;
        }
        else if((eep_param.pwd_magic == VALID_DATA)
                && (0x00 != memcmp_my(eep_param.password, &pframe->infor[PANID_LEN+1], PWD_LEN)))
        {//判断是否是已经注册成功的panid
            reg.last_status = PASSWORD_ERR;
            chg_state(PWD_ERR);
            return(0);
        }
    }
    //成功,设置密码注册成功




    reg.type = PASSWORD_REG;
    chg_state(G_GWID);//读取网关aid




    if(need_wr)
    {
        mymemcpy(eep_param.panid, &pframe->infor[1], PANID_LEN);
        eep_param.panid_flag = VALID_DATA;
        EEP_Write(OF_PLC_PARAM, (uint8 *)&eep_param, sizeof(eep_param));
    }
    return(0);
}
#endif

static uint8 get_reg(struct SHS_frame *pframe)这个函数由那个函数来调用,由void local_frame_opt(struct SHS_frame *pframe)


/**************************************************************** 
                        本地通信协议解析
****************************************************************/
void local_frame_opt(struct SHS_frame *pframe)
{
    if(CMD_REGINFOR == pframe->infor[0])
    {
        get_reg(pframe);
    }
    else if(CMD_REQ_AID == pframe->infor[0])
    {
        chg_state(S_AID);//载波出现主动获取aid,说明载波芯片可能复位!!
    }
    else if(CMD_UNLINK == pframe->infor[0])
    {//网关断开连接,载波芯片上报断开连接,启动载波注册panid设置????
        chg_state(S_PWDREG);
    }
//    else if(CMD_GET_GWAID == pframe->infor[0])
//    {
//        mymemcpy(eep_param.gateway_id, &pframe->infor[1], ID_LEN);
//        EEP_Write(OF_PLC_PARAM, (uint8 *)&eep_param, sizeof(eep_param));
//    }

}

我们的疑问又来了,那个函数调用的void local_frame_opt(struct SHS_frame *pframe)答案是uint8 frame_handle(uint8 init, void *args) 协议解析函数

uint8 frame_handle(uint8 init, void *args)
{
    uint8 len,ret;
    struct SHS_frame *pframe = (struct SHS_frame *)args;


    if(pframe == NULL) return(0);
    if(is_all_xx(pframe->said, 0x00, ID_LEN))
    {//本地通信
        local_frame_opt(pframe);
        return(1);
    }
    else
    {//异地通信
        ret = remote_frame_opt(pframe);
        if (ret > 1) {
            len = set_ret_frame(pframe, ret);
            uart_write((uint8 *)pframe, len);
        }
    }
    
    return(0); 
}

那个函数调用了这个函数uint8 frame_handle(uint8 init, void *args)呢????答案是下面的这个结构体

struct PLC_STATE 
{
    uint8 cur_state;
    uint8 next_state;


    uint8 (*action)(uint8 init, void *args);//这个结构体是怎么用的
                                            
};

const struct PLC_STATE plc_state_slot[]=
{
    //init plc
    {RST_PLC,   R_EID,   reset_plc},
    //{R_EID,     S_BPS,   rd_plc_eid},
    {R_EID,     S_AID,   rd_plc_eid},
    {S_BPS,     S_AID,   wr_plc_bps},
    {S_AID,     S_PWDREG,wr_plc_aid},
    {S_PWDREG,  S_PANID, set_register},
    {S_PANID,   _END,    wr_plc_panid},
#if KEY_REG
    //key reg
    {UNLINK1,   S_REG,   set_unlink},
#endif
    
    //密码注册
    {PWD_ERR,   UNLINK2, set_register},
    {UNLINK2,   S_PANID,    set_unlink},
    //注册成功
    {G_GWID,    S_REG,   rd_gw_aid},
    {S_REG,     G_SID,   set_register},//设置注册属性,等待载波芯片上报panid
{G_SID,     _END,    rd_gw_sid},


    {_END,      _END,    frame_handle},
};

下面的函数又重新调用了 plc_state_slot[]

/****************************************
            载波初始化状态转换
****************************************/
void chg_state(uint8 cur_state)
{
    uint8 i;
    static uint8 last_state=INVALID;
    
    plc_state.wait_t = 0;
    plc_state.init=1;
    for(i = 0; i < PLC_SLOT_SZ; i++)
    {
        if(plc_state_slot[i].cur_state == cur_state)
        {
            plc_state.pstate = (struct PLC_STATE *)&plc_state_slot[i];
            break;
        }
    }
    if(i >= PLC_SLOT_SZ)
    {
        plc_state.pstate = (struct PLC_STATE *)&plc_state_slot[0];
    }


    if(last_state != plc_state.pstate->cur_state)
    {
        plc_state.trycnt = 0;
    }
    last_state = plc_state.pstate->cur_state;
    notify(EV_STATE);
}


void plc_machine_opt(void *args)
{
    struct PLC_STATE *pstate = plc_state.pstate;
    uint8 init;


    init = plc_state.init;
    if(init) plc_state.wait_t=0;
    plc_state.init = 0;
    if(NULL != pstate)
    {
        pstate->action(init, args);调用这个函数是不是就相当于调动了那个结构体const struct PLC_STATE plc_state_slot[]=????????
    }
}


代码的分析到此为止,有些不理解的地方还要回公司问问高手,或者让问问我的高手哥们。分析无止境,我会坚持,代码就是打破砂锅问到底。找出代码最真实的一面。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MI200E 电力线载波通讯芯片简述: MI200E 是一款针对低压电力线环境优化设计的高性能通讯芯片。内部集成了诸如多阶开关电容滤波器,高效数字放大器, CRC-16 硬件校验等多种电路。由于MI200E 是一款数模混合芯片,因此在进行软硬件设计时都必须遵循一定的准则。 MI200E电力线载波通信模块简述: 模块采用 MI200E 电力线载波通讯芯片,具有通讯可靠,抗干扰能力强等特点。配合专门设计的外围滤波电路与电力线接口电路,用户可以非常容易地将模块嵌入到系统中。 可搭载弥亚微电子最新研发的网络通讯协议,可实现自动组网,网络自适应,多级中继转发等多种功能。 作为一个简单的透明传输模块使用,通过 TTL 电平串行接口,实现数据透明传输。 模块硬件部分采用 MI200E+MCU 的方式,所有MI200E 外围电路(包括信号耦合电路)均包含在内。用户只需将220V 接入到模块,并为模块提供一组+5V 直流电源即可。 模块可广泛应用于集抄系统,智能楼宇/家居控制系统,能源管理系统等多个领域。 电力线载波通信模块硬件框图: 实物图片展示: 附件内容包括: 电子载波通讯模块硬件设计,包括原理图+PCB源文件,用candence软件打开; 载波通讯收发例程; MI200E芯片应用笔记,包括MI200E典型应用电路设计及软件设计等; MI200E芯片手册; MI200E电子线载波通讯模块说明书;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值