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

用户程序的基本原理和注意事项可以参见下面链接:
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;
}
}