3210|3

1万

帖子

25

TA的资源

版主

楼主
 

[ATMEL SAM R21]WsnDemo 通信过程初步分析 [复制链接]

这几天研究了一下ASF中WsnDemo的通信过程,简单的给大家分析一下,仅供参考。

首先看主程序文件main.c,WsnDemo的主程序很简洁,就是系统初始化和调用了一下wsndemo_main()函数。

  1. int main(void)
  2. {
  3.         #if SAMD || SAMR21
  4.         system_init();
  5.         delay_init();
  6.         #else
  7.         sysclk_init();
  8.         board_init();
  9.         #endif
  10.         irq_initialize_vectors();
  11.         wsndemo_main();
  12. }
复制代码


而wsndemo_main()函数也没有太多内容:

  1. int wsndemo_main(void)
  2. {
  3.         SYS_Init();
  4. #if APP_ENDDEVICE
  5.         sm_init();
  6. #endif
  7. #if APP_COORDINATOR
  8.         sio2host_init();
  9. #endif
  10.         cpu_irq_enable();
  11.         while (1) {
  12.                 SYS_TaskHandler();
  13.                 APP_TaskHandler();
  14.         }
  15. }
复制代码


在这里可以看到,主要就是在while(1)循环中不断调用SYS_TaskHandler()和APP_TaskHandler()两个函数,就是不断处理系统事件和用户事件。


SYS_TaskHandler()函数则是调用了三个子函数,从函数名上我们可以猜出应该是无线网络通信和系统定时器底层处理,所以就先放到一边吧。


  1. void SYS_TaskHandler(void)
  2. {
  3.         PHY_TaskHandler();
  4.         NWK_TaskHandler();
  5.         SYS_TimerTaskHandler();
  6. }
复制代码


在看看APP_TaskHandler()函数,它使用了一个简单的状态机方式,通过当前的状态决定下一步的操作。

  1. static void APP_TaskHandler(void)
  2. {
  3.         switch (appState) {
  4.         case APP_STATE_INITIAL:
  5.         {
  6.                 appInit();
  7.         }
  8.         break;

  9.         case APP_STATE_SEND:
  10.         {
  11.                 appSendData();
  12.         }
  13.         break;

  14.         case APP_STATE_SENDING_DONE:
  15.         {
  16. #if APP_ENDDEVICE
  17.                 appState = APP_STATE_PREPARE_TO_SLEEP;
  18. #else
  19.                 SYS_TimerStart(&appDataSendingTimer);
  20.                 appState = APP_STATE_WAIT_SEND_TIMER;
  21. #endif
  22.         }
  23.         break;

  24. #if APP_ENDDEVICE
  25.         case APP_STATE_PREPARE_TO_SLEEP:
  26.         {
  27.                 if (!NWK_Busy()) {
  28.                         NWK_SleepReq();
  29.                         appState = APP_STATE_SLEEP;
  30.                 }
  31.         }
  32.         break;

  33.         case APP_STATE_SLEEP:
  34.         {
  35.                 sm_sleep(APP_SENDING_INTERVAL / 1000);
  36.                 appState = APP_STATE_WAKEUP;
  37.         }
  38.         break;

  39.         case APP_STATE_WAKEUP:
  40.         {
  41.                 NWK_WakeupReq();

  42.                 /*
  43.                  * #if (LED_COUNT > 0)
  44.                  *    LED_On(LED_NETWORK);
  45.                  #endif*/

  46.                 appState = APP_STATE_SEND;
  47.         }
  48.         break;
  49. #endif
  50.         default:
  51.                 break;
  52.         }

  53. #if (APP_COORDINATOR)
  54.         uint16_t bytes;
  55.         if ((bytes = sio2host_rx(rx_data, APP_RX_BUF_SIZE)) > 0) {
  56.                 UartBytesReceived(bytes, (uint8_t *)&rx_data);
  57.         }
  58. #endif
  59. }
复制代码


状态机有APP_STATE_INITIAL(初始化)、APP_STATE_SEND(数据发送)、APP_STATE_SENDING_DONE(发送完成)、APP_STATE_PREPARE_TO_SLEEP(准备休眠)、APP_STATE_SLEEP(休眠)、APP_STATE_WAKEUP(唤醒)等几种模式。除了初始化是执行一次,其他模式是不断循环,轮流执行,执行完当前模式后就切换到下一个模式。当然只有ENDDEVICE才有休眠模式,COORDINATOR和ROUTER是不能休眠的。

休眠使用了语句
  1. sm_sleep(APP_SENDING_INTERVAL / 1000);
复制代码


sm_sleep先设置RTC唤醒时间,然后进入待机模式(STANDBY,SAM R21的低功耗模式只有IDLE 0/IDLE 1/IDEL 2/STANDBY四种)。其中APP_SENDING_INTERVAL是在config.h中定义的发送周期时间,默认是2000,就是2S,修改这个时间常数就可以改变发送时间。这个地方比较奇怪的是sm_sleep的参数是秒,而函数内部是按照ms计算的,这样最低的时间就是1S。

从上面APP_STATE_SEND模式中,我们可以看到数据发送是调用了appSendData()函数。这个函数如下:

  1. static void appSendData(void)
  2. {
  3. #ifdef NWK_ENABLE_ROUTING
  4.         appMsg.parentShortAddr = NWK_RouteNextHop(0, 0);
  5. #else
  6.         appMsg.parentShortAddr = 0;
  7. #endif

  8.         appMsg.sensors.battery     = rand() & 0xffff;
  9.         appMsg.sensors.temperature = rand() & 0x7f;
  10.         appMsg.sensors.light       = rand() & 0xff;

  11. #if APP_COORDINATOR
  12.         appUartSendMessage((uint8_t *)&appMsg, sizeof(appMsg));
  13.         SYS_TimerStart(&appDataSendingTimer);
  14.         appState = APP_STATE_WAIT_SEND_TIMER;
  15. #else
  16.         appNwkDataReq.dstAddr = 0;
  17.         appNwkDataReq.dstEndpoint = APP_ENDPOINT;
  18.         appNwkDataReq.srcEndpoint = APP_ENDPOINT;
  19.         appNwkDataReq.options = NWK_OPT_ACK_REQUEST | NWK_OPT_ENABLE_SECURITY;
  20.         appNwkDataReq.data = (uint8_t *)&appMsg;
  21.         appNwkDataReq.size = sizeof(appMsg);
  22.         appNwkDataReq.confirm = appDataConf;
  23. #if (LED_COUNT > 0)
  24.         LED_On(LED_DATA);
  25. #endif
  26.         NWK_DataReq(&appNwkDataReq);

  27.         appState = APP_STATE_WAIT_CONF;
  28. #endif
  29. }
复制代码
如果是APP_COORDINATOR,那么就将数据通过appUartSendMessage函数发到串口,否则调用NWK_DataReq(&appNwkDataReq)发送到RF。

上面的过程其实不复杂,但是绕了很多弯,一个处理需要通过多个函数,在不同的文件中跳来跳去。这还只是分析了主流程中的一部分,也是最重要的一部分。不过看清楚了这个基本流程,在看其他部分也就简单多了,再去看其他的ASF程序也都是差不多的了。


最新回复

mark一下,这两天我也开始研究无线这部分了,老兄你一直都很领先呀  详情 回复 发表于 2015-1-5 12:48

赞赏

1

查看全部赞赏

点赞 关注
 

回复
举报

79

帖子

1

TA的资源

一粒金砂(中级)

沙发
 
顶一个 学习一下
 
 
 

回复

524

帖子

0

TA的资源

一粒金砂(高级)

板凳
 
mark一下,这两天我也开始研究无线这部分了,老兄你一直都很领先呀

点评

这段时间事情太多,在不抓紧就跟不上你们了。  详情 回复 发表于 2015-1-5 20:13
 
 
 

回复

1万

帖子

25

TA的资源

版主

4
 
770781327 发表于 2015-1-5 12:48
mark一下,这两天我也开始研究无线这部分了,老兄你一直都很领先呀

这段时间事情太多,在不抓紧就跟不上你们了。


 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表