在内嵌模式中,用户程序和系统程序运行在同一处理器上,但是它是独立编译和链接的,可以动态下载到节点模块,扩充节点功能,用来控制外接外接各类传感器,是对节点模块的二次开发,这样不但可以节省一个外部处理器。而且用户程序只需关注新增接口和设备,这样就比较容易达到总体功耗要求。

用户程序的基本原理和注意事项可以参见下面链接:
http://www.tinywsn.net/wordpress/index.php/docs/manual/node/node-wbed/
下面的连接是用户程序开发包SDK,包含了许多的例程以及各类传感器总线的驱动:
https://gitee.com/tinywsn/fw-stm32l1-wbed-usr
传感器通过扩展板,安装在节点模块上,如下图所示,用户程序用配置软件TinyCFG下载到模块内。

软件结构
用户程序和系统程序通过消息进行交互,为了提高系统的响应效率,用户程序采用的事件驱动的状态机模型,其中消息的来源主要有三类,用户程序只需对接收消息进行响应:
- 系统程序产生的消息
- 中断程序产生的消息
- 用户程序自己的消息
为了更好的配和系统程序,下图就是目推荐采用的的状态转换图:

从图中可以看出共有5个状态,其中def(默认消息处理状态)是后台状态,一直存在,其他都是前台状态,只有一个是当前激活的状态,它们之间根据接受的消息进行切换,下表对各个状态分别进行说明
符号 | 名称 | 说明 |
---|---|---|
init | 初始状态 | 系统上电进入的状态,进行程序和设备的初始化 |
disc | 断链状态 | 当无线断链进入的状态,关闭设备进入低功耗模式 |
conn | 连接状态 | 处理各类系统消息,发送测量结果,当转换定时器 触发时,进入转换状态 |
conv | 转换状态 | 启动传感器转换,结束后关闭传感器,返回连接状态 |
def | 默认状态 | 默认消息处理状态,未处理的消息都进入这个状态 |
初始状态
消息 | 动作 | 跳转 |
---|---|---|
WIPC_MSG_FSM_INIT | 进入状态机初始化消息,开始设备初始化,开启一个同步定时器,以便提前一个时隙唤醒,完成传感器测量 | 连接状态(如果在线) 断链状态(如果断链) |
// 初始状态机消息处理入口 wipc_result_t init_msg_proc(uint8_t msg, void *in, void *out, ctx_t *ctx) { wipc_msg_tmr_init_t tmr_init; switch(msg){ case WIPC_MSG_FSM_INIT: // 初始化NVM内存 net_msg_send(WIPC_MSG_NVM_LOAD, 0, &((ctx_t*)ctx)->nvm, ctx); // 初始化设备 pwr_init(true); led_init(((ctx_t*)ctx)->nvm.led); // 开启一同步定时器 tmr_init.type = WIPC_TMR_SYNC; // 提前一个时隙唤醒 tmr_init.arg.oft = -1; net_msg_send(WIPC_MSG_TMR_INIT, &tmr_init, 0, 0); // 初始化传感器 ds18b20_init(&ctx->ds18b20); // 根据当前网络状态, // 切换到不同状态机 if(((wipc_msg_sys_init_t*)in)->stat & WIPC_S_CONN){ fsm_goto(conn_msg_proc, ctx); }else{ fsm_goto(disc_msg_proc, ctx); } return WIPC_RES_SUCC; case WIPC_MSG_FSM_EXIT: return WIPC_RES_SUCC; default: return WIPC_RES_CONT; } }
连接状态
消息 | 动作 | 跳转 |
---|---|---|
WIPC_MSG_TMR_TICK | 同步定时器触发消息,跳转到转换状态,开启传感器测量 | 转换状态 |
WIPC_MSG_NTS_INIT | 节点时隙开始消息,检查传感器测量结果,发送数据 |
// 连接状态机消息处理入口 wipc_result_t conn_msg_proc(uint8_t msg, void *in, void *out, ctx_t *ctx) { switch(msg){ case WIPC_MSG_FSM_INIT: return WIPC_RES_SUCC; case WIPC_MSG_FSM_EXIT: return WIPC_RES_SUCC; case WIPC_MSG_TMR_TICK: // 检查定时器的类别 if(((wipc_msg_tmr_tick_t*)in)->type == WIPC_TMR_SYNC){ // 跳转到转换状态 fsm_goto(conv_msg_proc, ctx); return WIPC_RES_SUCC; } return WIPC_RES_SUCC; case WIPC_MSG_NTS_INIT: // 检查转换的结果 if(ctx->flag & CTX_F_DONE){ uint8_t *q = CTX_USR_BUF(ctx); stringf((char*)q, "val,t,%.1fC", ctx->t); // 发送测量数据 tx_usr_data(q, strlen((char*)q), TX_F_NONE, ctx); ctx->flag &=~CTX_F_DONE; return WIPC_RES_SUCC; } return WIPC_RES_FAIL; default: return WIPC_RES_CONT; } }
转换状态
消息 | 动作 | 跳转 |
---|---|---|
WIPC_MSG_FSM_INIT | 进入状态机初始化消息, 重新初始化处于低功耗模式的设备,打开传感器的电源,等待上电稳定 | |
WIPC_MSG_WAIT_DONE | 上电稳定完成,启动传感器的转换 | |
WIPC_MSG_CONV_DONE | 传感器转换结束,获取测量数据 | 连接状态 |
WIPC_MSG_WAIT_TMRO | 传感器转换失败,跳转回原来状态 | 连接状态 |
WIPC_MSG_FSM_EXIT | 退出状态机析构化消息, 关闭设备使得它们进入低功耗模,关闭传感器电源 |
// 转换状态机消息处理入口 wipc_result_t conv_msg_proc(uint8_t msg, void *in, void *out, ctx_t *ctx) { switch(msg){ case WIPC_MSG_FSM_INIT: // 打开电源,重新初始化设备 pwr_reinit(true); led_reinit(ctx->nvm.led); ds18b20_reinit(&ctx->ds18b20); // 等待传感器电源稳定 dev_wait_msec(&ctx->ds18b20.wait, DS18B20_PWRON_MSEC, ctx); return WIPC_RES_SUCC; case WIPC_MSG_FSM_EXIT: // 停止系统时钟节拍 drv_wait_halt(&ctx->ds18b20.wait); // 关闭电源和设备 ds18b20_deinit(&ctx->ds18b20); led_deinit(); pwr_deinit(); return WIPC_RES_SUCC; case WIPC_MSG_LPM_REQ: // 阻止系统进入低功耗模式 return WIPC_RES_FAIL; case WIPC_MSG_SYS_TICK: // msec tick drv_msec_tick(&ctx->ds18b20.wait, &ctx->ds18b20); return WIPC_RES_SUCC; case WIPC_MSG_WAIT_TMRO: // 传感器转换失败 fsm_goto(conn_msg_proc, ctx); return WIPC_RES_SUCC; case WIPC_MSG_WAIT_DONE: // 重置一下传感器 ds18b20_reset(&ctx->ds18b20); // 启动传感器的转换 if(!ds18b20_conv(&ctx->ds18b20)){ fsm_goto(conn_msg_proc, ctx); return WIPC_RES_FAIL; } return WIPC_RES_SUCC; case WIPC_MSG_CONV_DONE: // 传感器转换结束 if(ds18b20_get(&ctx->ds18b20, &ctx->t)){ ctx->flag |= CTX_F_DONE; } // goto conn fsm_goto(conn_msg_proc, ctx); return WIPC_RES_SUCC; default: return WIPC_RES_CONT; } }
断链状态
消息 | 动作 | 跳转 |
---|---|---|
WIPC_MSG_FSM_INIT | 进入状态机初始化消息, 关闭设备使得它们进入低功耗模,关闭传感器电源 |
// 断链状态消息处理入口 wipc_result_t disc_msg_proc(uint8_t msg, void *in, void *out, ctx_t *ctx) { switch(msg){ case WIPC_MSG_FSM_INIT: // 停止系统时钟节拍 drv_wait_halt(&ctx->ds18b20.wait); // 关闭电源和设备 ds18b20_deinit(&ctx->ds18b20); led_deinit(); pwr_deinit(); return WIPC_RES_SUCC; case WIPC_MSG_FSM_EXIT: return WIPC_RES_SUCC; default: return WIPC_RES_CONT; } }
默认状态
消息 | 动作 | 跳转 |
---|---|---|
WIPC_MSG_NET_CONN | 接受到网络连接消息,切换到连接状态 | |
WIPC_MSG_NET_DISC | 接受到网络断链消息,切换到断链状态 | |
WIPC_MSG_USR_DATA | 接受到网络的命令,解析命令,执行响应动作 |
// 默认状态消息处理入口 wipc_result_t def_msg_proc(uint8_t msg, void *in, void *out, ctx_t *ctx) { switch(msg){ case WIPC_MSG_LPM_REQ: return WIPC_RES_SUCC; case WIPC_MSG_LPM_INIT: return WIPC_RES_SUCC; case WIPC_MSG_LPM_EXIT: return WIPC_RES_SUCC; case WIPC_MSG_NET_CONN: // 切换到连接状态 fsm_goto(conn_msg_proc, ctx); return WIPC_RES_SUCC; case WIPC_MSG_NET_DISC: // 切换到断链状态 fsm_goto(disc_msg_proc, ctx); return WIPC_RES_SUCC; case WIPC_MSG_USR_DATA: // 接受到网络命令 return rx_usr_data(in, out, ctx); case WIPC_MSG_IRQ_VTOR: return WIPC_RES_SUCC; default: return WIPC_RES_FAIL; } }