您的位置:首页 > 其它

转】学习ZigBee入门-2

2014-04-30 16:48 232 查看
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 指导文档。这个文档个人觉得写的不错,要是没看之前就看程序的却很郁闷的!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: