转】学习ZigBee入门-2

来源:互联网 发布:在线mysql数据库 编辑:程序博客网 时间:2024/05/11 18:06
Sample 例子演示 

       上节基本上初步认识了 Zstack 的一些情况,今天继续我的学习,打开 Sample例子看看,究竟 ZIGBEE 是怎么回事。 毫无疑问:如果是第一次打开这个例子工程,肯定很迷糊,因为此时我迷糊了。很多的文件夹,很多层,这么多文件夹,打开之后又有那么多文件,从何看起?不要着急,特别是有些人拿到之后,啥都不知道的人第一个问题就是:我要实现 XXX,在哪修改或者在哪添加我的函数呢?凡是我遇到这样的客户,我就可以肯定他技术部咋的。就连我这个外行都知道,不把这些弄明白,就是实现 XXX 只需要修改一个字母,那也不知道在哪改啊?所以我不急,但是我也理解很多客户,因为有时候项目催的比较急,毕竟老板都是外行嘛! 两条路:1 就是先看主函数,2 就是看看 TI 提供例子说明文档没有。 我这里先看看主函数再说哈!因为我就知道从主函数看起. 没办法大概每个文件夹找啊,主函数的特征还是比较明明显的。 
下面把主函数复制过来简单看下: 
ZSEG int main( void )
{
// Turn off interrupts --关闭中断
osal_int_disable( INTS_ALL );

// Initialize 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条目
osal_nv_init( NULL );

// Determine the extended address 决定长地址
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

#ifdef LCD_SUPPORTED
HalLcdInit();
#endif
    // Initialize the operating system --初始化操作系统
osal_init_system();

// Allow interrupts                        --允许中断
osal_int_enable( INTS_ALL );

// Final board initialization           --在初始化板子
InitBoard( OB_READY );
//HalLcdInit();                                
// 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 
      上节提到了 EM 和 DB 两个板子,其硬件是不一样的。按键的定义 ---hal_key.h中,具体的功能定义在hal_key.c中
/-------------------hal_key.h---------------------/
/* Interrupt option - Enable or disable */
#define HAL_KEY_INTERRUPT_DISABLE    0x00 //--禁止中断
#define HAL_KEY_INTERRUPT_ENABLE     0x01 //--中断使能

/* Key state - shift or nornal */
#define HAL_KEY_STATE_NORMAL          0x00
#define HAL_KEY_STATE_SHIFT              0x01

/* Switches (keys) */
#define HAL_KEY_SW_1 0x01 // Joystick up
#define HAL_KEY_SW_2 0x02 // Joystick right
#define HAL_KEY_SW_5 0x04 // Joystick center
#define HAL_KEY_SW_4 0x08 // Joystick left
#define HAL_KEY_SW_3 0x10 // Joystick down
#define HAL_KEY_SW_6 0x20 // Button S1 if available
#define HAL_KEY_SW_7 0x40 // Button S2 if available

/* Joystick */ //---游戏杆
#define HAL_KEY_UP     0x01       // Joystick up
#define HAL_KEY_RIGHT 0x02    // Joystick right
#define HAL_KEY_CENTER 0x04 // Joystick center
#define HAL_KEY_LEFT   0x08     // Joystick left
#define HAL_KEY_DOWN   0x10 // Joystick down

//--------------------hal_key.c-----------------------------//
#define HAL_KEY_DEBOUNCE_VALUE 25 //--去抖动值
#define HAL_KEY_POLLING_VALUE   100   //--查询值

#if defined (HAL_BOARD_CC2430EB) || defined (HAL_BOARD_CC2430BB) //--EB/BB P0.6
#define HAL_KEY_SW_6_ENABLE
#define HAL_KEY_SW_6_PORT     P0                        /* Port location of SW1 */
#define HAL_KEY_SW_6_BIT      HAL_KEY_BIT1            /* Bit location of SW1 */ //--SW1
#define HAL_KEY_SW_6_SEL      P0SEL                   /* Port Select Register for SW1 */
#define HAL_KEY_SW_6_DIR      P0DIR                   /* Port Direction Register for SW1 */
#define HAL_KEY_SW_6_IEN      IEN1                    /* Interrupt Enable Register for SW1 */
#define HAL_KEY_SW_6_IENBIT   HAL_KEY_BIT5            /* Interrupt Enable bit for SW1 */
#define HAL_KEY_SW_6_EDGE     HAL_KEY_RISING_EDGE     /* Type of interrupt for SW1 */
#define HAL_KEY_SW_6_EDGEBIT HAL_KEY_BIT0            /* EdgeType enable bit SW1 */
#define HAL_KEY_SW_6_ICTL     PICTL                   /* Port Interrupt Control for SW1 */
#define HAL_KEY_SW_6_ICTLBIT HAL_KEY_BIT3            /* Interrupt enable bit for SW1 */
#define HAL_KEY_SW_6_PXIFG    P0IFG                   /* Port Interrupt Flag for SW1 */

#define HAL_KEY_P0INT_LOW_USED    HAL_KEY_SW_6_BIT    /* P0 can only be enabled/disabled as group of high or low nibble */
#endif   //--注意条件编译的灵活使用

#if defined (HAL_BOARD_CC2430BB) //--BB
#define HAL_KEY_POINT_HIGH_USED 0
#endif

#if defined (HAL_BOARD_CC2430EB) //--EB
#define HAL_KEY_JOYSTICK_ENABLE
#define HAL_KEY_JOY_CHN   HAL_ADC_CHANNEL_6   //--ADC采样的通道6

#define HAL_KEY_SW_5_ENABLE
#define HAL_KEY_SW_5_PORT     P0                            /* Port location of SW5 */
#define HAL_KEY_SW_5_BIT      HAL_KEY_BIT5            /* Bit location of SW5 */
#define HAL_KEY_SW_5_SEL      P0SEL                        /* Port Select Register for SW5 */
#define HAL_KEY_SW_5_DIR      P0DIR                        /* Port Direction Register for SW5 */
#define HAL_KEY_SW_5_INP      P0INP                         /* Port Input Mode Register for SW5 */
#define HAL_KEY_SW_5_IEN      IEN1                           /* Interrupt Enable Register for SW5 */
#define HAL_KEY_SW_5_IENBIT   HAL_KEY_BIT5            /* Interrupt Enable bit for SW5 */
#define HAL_KEY_SW_5_EDGE     HAL_KEY_RISING_EDGE     /* Type of interrupt for SW5 */
#define HAL_KEY_SW_5_EDGEBIT HAL_KEY_BIT2            /* EdgeType enable bit SW5 */
#define HAL_KEY_SW_5_ICTL     PICTL                   /* Port Interrupt Control for SW5 */
#define HAL_KEY_SW_5_ICTLBIT HAL_KEY_BIT4            /* Interrupt enable bit for SW5 */
#define HAL_KEY_SW_5_PXIFG    P0IFG                   /* Port Interrupt Flag for SW5 */

#define HAL_KEY_POINT_HIGH_USED   HAL_KEY_SW_5_BIT    /* P0 can only be enabled/disabled as group of high or low nibble */
#endif

/**************************************----LED定义相关----*****************************/
//----------------------------hal_led.h-------------------------------
/* LEDS - The LED number is the same as the bit position */
#define HAL_LED_1     0x01
#define HAL_LED_2     0x02
#define HAL_LED_3     0x04
#define HAL_LED_4     0x08
#define HAL_LED_ALL   (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4)

/* Modes */
#define HAL_LED_MODE_OFF     0x00
#define HAL_LED_MODE_ON      0x01
#define HAL_LED_MODE_BLINK   0x02
#define HAL_LED_MODE_FLASH   0x04
#define HAL_LED_MODE_TOGGLE 0x08

/* Defaults */
#define HAL_LED_DEFAULT_MAX_LEDS      4
#define HAL_LED_DEFAULT_DUTY_CYCLE    5
#define HAL_LED_DEFAULT_FLASH_COUNT   50
#define HAL_LED_DEFAULT_FLASH_TIME    1000

//-------------------------hal_board_cfg.h-------------------------------//
//-----------LED Configuration

#define HAL_NUM_LEDS            2
#define HAL_LED_BLINK_DELAY()   st( { volatile uint32 i; for (i=0; i<0x5800; i++) { }; } )

/* 1 - Green */
#define LED1_BV           BV(0)
#define LED1_SBIT         P1_0
#define LED1_DDR          P1DIR
#define LED1_POLARITY     ACTIVE_LOW
/* 2 - Red */
#define LED2_BV           BV(1)
#define LED2_SBIT         P1_1
#define LED2_DDR          P1DIR
#define LED2_POLARITY     ACTIVE_LOW
/* 3 - Yellow */
#define LED3_BV           BV(1)
#define LED3_SBIT         P1_1
#define LED3_DDR          P1DIR
#define LED3_POLARITY     ACTIVE_LOW

/* 4 - Blue */
#define LED4_BV           BV(0)
#define LED4_SBIT         P1_0
#define LED4_DDR          P1DIR
#define LED4_POLARITY     ACTIVE_LOW
关于上面出现的 LEDx 实际上是程序中出现的关键字。

2、初始化 64 位 IEEE 地址 --很重要哦
       实际上在主函数中有这么个初始化函数的:zmain_ext_addr()。这里说如果地址复位为 0xFFFFFFFFFFFFFFFF 的话,那么就会不停的闪烁 LED1,一直等到按键 SW5 (P0_5)按下后程序才能继续运行,意思就是说按下 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 64-bit address to NV 些临时的 64 位物理地址进入 NV 
osal_nv_write( ZCD_NV_EXTADDR, 0, Z_EXTADDR_LEN, &aExtendedAddress ); 
#endif 
        从程序中可以看出,一开始就检测 FLASH 中的物理地址,因为这个地址在 FLASH中是固定的存储空间,一旦为有效地址就退出函数,一旦为无效地址(0xFFFFFFFFFFFFFFFF),那么就对其物理地址进行简单的初始化并检测 SW5 按键。还是比较好理解的! 
3、运行例子及现象观察
       协调器:上电运行,地址检测如上面介绍的情况,通过之后呢---就进行通道扫描(channl 和PANID),此时 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 指导文档。这个文档个人觉得写的不错,要是没看之前就看程序的却很郁闷的!

0 0