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