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);//通过此函数开启射频,并且可设置回调函数根据执行结果处理下一步操作
}


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,635评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,628评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,971评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,986评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,006评论 6 394
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,784评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,475评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,364评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,860评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,008评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,152评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,829评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,490评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,035评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,428评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,127评论 2 356

推荐阅读更多精彩内容