2019-10-24NB联网的巧妙设计

与通过外部MCU来控制NB模块的方式不同,在NB芯片内部的开发自然是更需要花些心思的,因为必须要配合芯片自身的程序,在保证其不受干扰的情况下才能开发。
这次谈谈最基础也是最关键的联网操作。
如果是用外部MCU的方式,自然简单,仅仅使用AT指令轮询的方式就可满足。
但是,要直接使用芯片的底层接口,则有一番讲究。


typedef enum CFUN_ATTACH
{
    USER_ATTACH_STATUS_INIT = 0,
    USER_ATTACH_STATUS_TRIGGER_CFUN,
    USER_ATTACH_STATUS_TRIGGER_ATTACH,
}USER_ATTACH_STATUS;


uint8 user_cfun_attach = USER_ATTACH_STATUS_INIT;
static osTimerId_t  user_cfun_timer = NULL;

typedef void (*neul_radio_power_state_callback)(uint8 result);

NEUL_RET set_cfun(uint16 cfun, neul_radio_power_state_callback callback)
{
    NEUL_RET cfun_set_result;
    RPC_ERR rpc_return_code;

    rpc_return_code = command_set_ue_cfun(cfun, (uint8 *)&cfun_set_result);

    if(rpc_return_code == RPC_ERR_OK)
    {
        if(cfun_set_result == NEUL_RET_OK)
        {
            cfun_result_callback = callback;
        }

        return cfun_set_result;
    }

    return NEUL_RET_ERROR;
}

static void user_set_service_result_callback(NEUL_RET result)
{
    static uint8 set_service_count = 0;//需要注意这里一定要用静态变量来计数,否则会一直被清零
    if(result == NEUL_RET_OK)
    {
        //next step
        APP_COAP_INFO("attached");
    }
    else
    {
        if(set_service_count <=RETRY)//与set_cfun函数不同,这里的执行方式相对简单,就是在失败的时候再次尝试
        {
            set_service_sta te(RADIO_POWER_ON, user_set_service_result_callback);
            set_service_count++;
        }
    }
}

static void user_cfun_attach_timer(osTimerId_t xTimer)
{
    UNUSED(xTimer);

    switch(user_cfun_attach)
    {
        case USER_ATTACH_STATUS_INIT:
            //定时器创建失败的情况直接退出
            break;
        case USER_ATTACH_STATUS_TRIGGER_CFUN:
            //在cfun开启失败的情况下并且在允许的重复次数之内,再次开启cfun
            user_set_cfun();
            break;
        case USER_ATTACH_STATUS_TRIGGER_ATTACH:
            //开启cfun成功的条件下,进入attach的操作,该函数与set_cfun类似,都可设置回调函数根据结果执行下一步
            if (set_service_state(RADIO_POWER_ON, user_set_service_result_callback) !=  NEUL_RET_OK)
            {
                return;
            }
            break;
        default:
            break;
    }
}

//根据rpc的返回结果rpc_return_code,来处理下一步
static void user_cfun_result_callback(NEUL_RET result)
{
    static uint8 cfun_count = 0;

    if(result == NEUL_RET_OK)
    {
        cfun_count = 0;
        user_cfun_attach = USER_ATTACH_STATUS_TRIGGER_ATTACH;//如果成功开启射频,将标志位设置成即将进行attach

        if (user_cfun_timer == NULL)
        {
            user_cfun_timer = osTimerNew(user_cfun_attach_timer, osTimerOnce, NULL, NULL);//创建定时器计划执行attach和cfun的操作
            if (user_cfun_timer == NULL)
            {
                cfun_count = 0;
                user_cfun_attach = USER_ATTACH_STATUS_INIT;//如果定时器创建失败则将标志位设置成初始化状态,将直接返回
            }
            else
            {
                osTimerStart(user_cfun_timer, (uint32_t)osMs2Tick(USER_CFUN_ATTACH_TIMER));//创建成功则开启计时,这里是100ms
            }
        }
        else
        {
            osTimerStart(user_cfun_timer, (uint32_t)osMs2Tick(USER_CFUN_ATTACH_TIMER));//如果定时器已经存在,就直接开启计时
        }
    }
    else
    {
        if (cfun_count < RETRY)//允许重复3次
        {
            cfun_count++;
            user_cfun_attach = USER_ATTACH_STATUS_TRIGGER_CFUN;//这里是开启射频失败的情况,标志位设置成即将开启CFUN,就是从头再来一遍
            if (user_cfun_timer == NULL)
            {
                user_cfun_timer = osTimerNew(user_cfun_attach_timer, osTimerOnce, NULL, NULL);//这里的定时器操作跟上面一致,只是到了时间根据标志位的设定会再次执行cfun操作
                if (user_cfun_timer == NULL)
                {
                    cfun_count = 0;
                    user_cfun_attach = USER_ATTACH_STATUS_INIT;
                }
                else
                {
                    osTimerStart(user_cfun_timer, (uint32_t)osMs2Tick(USER_CFUN_ATTACH_TIMER));
                }
            }
            else
            {
                osTimerStart(user_cfun_timer, (uint32_t)osMs2Tick(USER_CFUN_ATTACH_TIMER));
            }
        }
        else
        {
            cfun_count = 0;
            user_cfun_attach = USER_ATTACH_STATUS_INIT;
            if (user_cfun_timer != NULL)
            {
                (void) osTimerStop(user_cfun_timer);
            }
        }
    }
}


static void user_set_cfun(void)
{
    uint16 nconfig_value = 0;
    get_nconfig(NEUL_AUTOCONNECT_FUNCTION, &nconfig_value);

    /*if auto config,return*/
    if (nconfig_value == AUTO_SEARCH)
    {
        return ;
    }

    set_cfun(RADIO_POWER_ON, user_cfun_result_callback);//通过此函数开启射频,并且可设置回调函数根据执行结果处理下一步操作
}


你可能感兴趣的:(2019-10-24NB联网的巧妙设计)