视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
从零开始学习Zstack之2
2025-10-06 11:38:20 责编:小OO
文档
从零开始学习Zstack之2

--------Sample例子演示

上节基本上初步认识了Zstack的一些情况,今天继续我的学习,打开Sample例子看看,究竟ZIGBEE是怎么回事。

毫无疑问:如果是第一次打开这个例子工程,肯定很迷糊,因为此时我迷糊了。对图2-1我简直是相当迷糊。

 

图2-1

这么多文件夹,打开之后又有那么多文件,从何看起?不要着急,特别是有些人拿到之后,啥都不知道的人第一个问题就是:我要实现XXX,在哪修改或者在哪添加我的函数呢?凡是我遇到这样的客户,我就可以肯定他技术部咋的。就连我这个外行都知道,不把这些弄明白,就是实现XXX只需要修改一个字母,那也不知道在哪改啊?所以我不急,但是我也理解很多客户,因为有时候项目催的比较急,毕竟老板都是外行嘛!

两条路:1就是先看主函数,2就是看看TI提供例子说明文档没有。

我这里先看看主函数再说哈!因为我就知道从主函数看起.

没办法大概每个文件夹找啊,主函数的特征还是比较明明显的,见图2-2所示:

 

图2-2

下面把主函数复制过来简单看下:

ZSEG int main( void )

{

  // Turn off interrupts------------关闭中断

  osal_int_disable( INTS_ALL );

  // Initialize HAL-----------初始化HAL,关于HAL是什么我想后面会有介绍的。

  HAL_BOARD_INIT();

  // Make sure supply voltage is high enough to run----电压检测,最好是能保证芯片能正常工作的电压

  zmain_vdd_check();

  // Initialize stack memory-------------初始化stack存储区

  zmain_ram_init();

  // Initialize board I/O------------初始化板载IO

  InitBoard( OB_COLD );

  // Initialze HAL drivers-------------初始化HAL驱动

  HalDriverInit();

  // Initialize NV System--------------初始化NV系统,NV是什么后面我想也会有介绍的

  osal_nv_init( NULL );

  // Determine the extended address------------确定扩展地址(位IEEE/物理地址)

  zmain_ext_addr();

  // Initialize basic NV items----------------初始化基本NV条目

  zgInit();

  // Initialize the MAC----------------初始化MAC

  ZMacInit();

#ifndef NONWK

  // Since the AF isn't a task, call it's initialization routine

  afInit();

#endif

  // Initialize the operating system----------初始化操作系统,看样子这里面还有OS,麻烦了……..!

  osal_init_system();

  // Allow interrupts-------------允许中断

  osal_int_enable( INTS_ALL );

  // Final board initialization------------------最后的版在初始化

  InitBoard( OB_READY );

  // Display information about this device---------------显示设备信息

  zmain_dev_info();

  /* Display the device info on the LCD */------------液晶支持显示

#ifdef LCD_SUPPORTED

  zmain_lcd_init();

#endif

  osal_start_system(); // No Return from here-------------------这里没有返回,大概是进入OS了。

} // main()

可以看到基本上都是初始化函数,因为函数名称都基本上带了init字样的,呵呵,个人觉得TI的变成习惯比我好,一看名称就知道大概功能了。所以这里也奉劝各位像我这样菜鸟级的初学者,一开始一定就要养成规范化编程的习惯,据说这样维护以及以后升级或者移植兼容性都比较好。我就先不管各个初始化函数是怎么实现的,我先看看各个功能是什么,现掌握整体功能在细化,我觉得这样的学习方法比较好,因为代码是在太多了,从一开始就逐句看,我敢保证没几个人有耐心看完看明白!

幸好每个初始化函数都有一句说明,虽然是英文的,但是理解起来一点都不难的。关于每个函数的功能我就直接写在上面的程序里面,节省纸张哈!

………………………………….

一句话:主函数的功能就是初始化!

主函数看完了又开始模糊了,又从何看起呢?在无从下手之际,只有去寻求TI说明文档的帮助了。上节不是漏掉了内容,是关于演示结果的,这里做上补充,怕因为缺调一点后面遇到什么不理解的就惨了!

Sample例子演示演示现象:

1、认识硬件------------按键和LED

上节提到了 EB和DB两个板子,其硬件是不一样的。按键EB就有5各SW1~SW5,而DB只有1各方向键,但是他们有个对应关系,如图2-3所示.

 

图2-3

LED数量和颜色也不一样,EB有四个LED,如图2-4;而DB只有两个,如图2-5。

 

如图2-4

 

如图2-5

关于上面几个图2-4/5中出现的LEDx实际上是程序中出现的关键字。

2、初始化位IEEE地址

实际上在主函数中有这么个初始化函数的:zmain_ext_addr()。这里说如果地址复位为0xFFFFFFFFFFFFFFFF的话,那么就会不停的闪烁LED1,一直等到按键SW5按下后程序才能继续运行,意思就是说按下SW5后就把无效的地址初始化为有效地物理地址了,这个应该是程序上实现的,那么就来看看对应的程序zmain_ext_addr。

/*********************************************************************

 * @fn      zmain_ext_addr

 * @brief   Makes extended address if none exists.确定扩展地址是有效的

 * @return  none

 *********************************************************************/

static ZSEG void zmain_ext_addr( void )

{

  uint8 i;

  uint8 led;

  uint8 tmp;

  uint8 *xad;

  uint16 AtoD;

  // Initialize extended address in NV初始化NV里的扩载地址

  osal_nv_item_init( ZCD_NV_EXTADDR, Z_EXTADDR_LEN, NULL );

  osal_nv_read( ZCD_NV_EXTADDR, 0, Z_EXTADDR_LEN, &aExtendedAddress );

  // Check for uninitialized value (erased EEPROM = 0xFF)检查是否为无效值(地址)

  xad = (uint8*)&aExtendedAddress;

  for ( i = 0; i < Z_EXTADDR_LEN; i++ )

    if ( *xad++ != 0xFF ) return;-------------------如果有一个字节不为0xFF,那么该地址有效返回

#ifdef ZDO_COORDINATOR

  tmp = 0x10;

#else

  tmp = 0x20;

#endif

  // Initialize with a simple pattern----------------简单初始化扩展地址

  xad = (uint8*)&aExtendedAddress;

  for ( i = 0; i < Z_EXTADDR_LEN; i++ )

    *xad++ = tmp++;

  // Flash LED1 until user hits SW5 ---------闪烁LED1直到SW5按下

  led = HAL_LED_MODE_OFF;

  while ( HAL_KEY_SW_5 != HalKeyRead() )---------------------SW5循环检测

  {

    MicroWait( 62500 );

    HalLedSet( HAL_LED_1, led^=HAL_LED_MODE_ON );  // Toggle the LED

    MicroWait( 62500 );

  }

  HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF );

  // Plug AtoD data into lower bytes

  AtoD = HalAdcRead (HAL_ADC_CHANNEL_7, HAL_ADC_RESOLUTION_10);

  xad = (uint8*)&aExtendedAddress;

  *xad++ = LO_UINT16( AtoD );

  *xad = HI_UINT16( AtoD );

#if !defined( ZTOOL_PORT ) || defined( ZPORT ) || defined( NV_RESTORE )

  // If no support for Z-Tool serial I/O,

  // Write temporary -bit address to NV些临时的位物理地址进入NV

  osal_nv_write( ZCD_NV_EXTADDR, 0, Z_EXTADDR_LEN, &aExtendedAddress );

#endif

}

从程序中可以看出,一开始就检测FLASH中的物理地址,因为这个地址在FLASH中是固定的存储空间,一旦为有效地址就退出函数,一旦为无效地址(0xFFFFFFFFFFFFFFFF),那么就对其物理地址进行简单的初始化并检测SW5按键。还是比较好理解的!

3、运行例子

在这里提到了跳线,由于本人采用的非TI原装硬件,没有该跳线,所以必须对程序进行修改,否则检测不到跳线,连ZIGBEE的设备类型都不能确定,肯定不能正常运行了。所以这里就先暂时不说了,这里要说的是一切都正常的情况下,例子的验尸结果。小小跳跃一下。不然学习一直没有进展很麻烦的!

协调器:上电运行,地址检测如上面介绍的情况,通过之后呢-------就进行通道扫描,此时LED1闪烁,一旦协调器成功建立网络,此时LED1停止闪烁,而LED3被点亮。

路由器:上电运行,仍然是地址检测在前。之后就是通道扫描寻求是否又存在的网络,此时LED1闪烁,一旦检测到存在网络并成功加入该网络,LED1将停止闪烁,被替换的是LED3别点亮,也就表明路由器成功加入了网络。

那么此时能进行的操作控制是什么呢,也是最简单的表现手法---按键无线控制LED:

? 周期(5S)发送信息到网络中每个设备

? SW1按下,发送一个信息到组1的设备

? SW2按下,退出/加入组1

这个我是经过验证的。如:

? 按下协调器SW1,路由器的LED1狂闪几下;按下路由器的SW1,那么协调器的LED1也就狂闪几下;当然我是只有两个节点。

? 如果按1下协调器的SW2,在按下路由器的SW1,此时协调器就没有反应,表明协调器已经退出组1;但是再按下协调器SW2在按路由器的SW1就与上一步类似了。路由器与此类似可以通过SW2退出/加入组1.

终于把演示弄完了,接下来就来看看程序。在此之前还是来看看TI提供的Sample指导文档。这个文档个人觉得写的不错,要是没看之前就看程序的却很郁闷的!

但是本人英文很差,所以需要慢慢看,等点时间放上来!

YYYtech于成都

2008年6月25日22:26下载本文

显示全文
专题