zigbee开发Word下载.docx
- 文档编号:5804747
- 上传时间:2023-05-05
- 格式:DOCX
- 页数:37
- 大小:1.13MB
zigbee开发Word下载.docx
《zigbee开发Word下载.docx》由会员分享,可在线阅读,更多相关《zigbee开发Word下载.docx(37页珍藏版)》请在冰点文库上搜索。
switch(pkt->
clusterId)
{
caseSAMPLEAPP_PERIODIC_CLUSTERID:
break;
caseSAMPLEAPP_FLASH_CLUSTERID:
flashTime=BUILD_UINT16(pkt->
cmd.Data[1],pkt->
cmd.Data[2]);
HalLedBlink(HAL_LED_4,4,50,(flashTime/4));
}
}
意味着要找到ClusterID才能进行下一步操作?
?
5事件
每一个task共有16个事件,用一个UINT16变量表示,每一个二进制位表示一个事件,其中0x8000为系统事件,剩余15个为用户可定义事件,如定时器。
系统事件可定义256个消息。
6HALDriverAPI
这部分介绍了HAL驱动的应用程序编程接口。
API为每个程序提供了接口以方便访问GPIO、UART、ADC、定时器。
7C语言相关
7.1Typedef
typedef作为类型定义关键字,用于在原有数据类型(包括基本类型、构造类型和指针等)的基础上,由用户自定义新的类型名称。
在编程中使用typedef的好处,除了为变量取一个简单易记且意义明确的新名称之外,还可以简化一些比较复杂的类型声明。
比如:
typedefintINT32;
将INT32定义为与int具有相同意义的名字,这样类型INT32就可用于类型声明和类型转换了,它和类型int完全相同。
INT32
a;
//定义整型变量a
(INT32)
b;
//将其它的类型b转换为整型
既然已经有了int这个名称,为什么还要再取一个名称呢?
主要是为了提高程序的可移植性。
比如,某种微处理器的int为16位,long为32位。
如果要将该程序移植到另一种体系结构的微处理器,假设编译器的int为32位,long为64位,而只有short才是16位的,因此必须将程序中的int全部替换为short,long全部替换为int,如此这样修改势必工作量巨大且容易出错。
如果将它取一个新的名称,然后在程序中全部用新取的名称,那么要移植的工作仅仅只是修改定义这些新名称即可。
也就是说,只需要将以前的:
typedefintINT16;
typedeflongINT32;
替换成:
typedefshortINT16;
由此可见,typedef声明并没有创建一个新类型,而是为某个已经存在的类型增加一个新的名字而已。
用这种方式声明的变量与通过声明方式声明的变量具有完全相同的属性。
至于typedef如何简化复杂的类型声明,将在后续的章节中详细阐述。
综上所述,如果在变量定义的前面加上typedef,即可定义该变量的类型。
intsize;
这里定义了一个整型变量size,当加上typedef后:
typedefintsize;
那么,size就成为了上面的size变量的类型,即int类型。
既然size是一个类型,当然可以用它来定义另外一个变量。
即:
sizea;
类似于变量的类型定义,也可以用typedef声明新的类型,比如:
char
*ptr_to_char;
//声明ptr_to_char为一个指向字符的指针
typedefcharptr_to_char;
//声明ptr_to_char为指向char的指针类型
ptr_to_char
pch;
//声明pch是一个指向字符的指针
对于初学者来说,也许会产生一个这样的疑问,为什么不使用#define创建新的类型名?
#defineptr_to_charchar*
ptr_to_charpch1,pch2;
由于有了“#defineptr_to_charchar*”,因此“ptr_to_charpch1,pch2”可以展开为
char*pch1,pch2;
所以pch2为char型变量。
如果用typedef来定义的话,其代码如下:
typedefchar*
ptr_to_char;
pch1,pch2;
则“ptr_to_charpch1,pch2”等价于
*pch1;
*pch2;
因此,pch1、pch2都是指针。
虽然#define语句看起来象typedef,但实际上却有本质上的差别。
对于#define来说,仅在编译前对源代码进行了字符串替换处理;
而对于typedef来说,它建立了一个新的数据类型别名。
由此可见,只是将pch1定义为指针变量,却并没有实现程序员的意图,而是将pch2定义成了char型变量。
在指针函数中,有这样一类函数,它们也返回指针,但是这个指针不是指向int、char之类的基本类型,而是指向函数。
对于初学者,别说写出这样的函数声明,就是看到这样的写法也是一头雾水。
比如,下面的语句:
int(*ff(int))(int*,int);
我们用上面介绍的方法分析一下,ff首先与后面的“()”结合,即:
int(*(ff(int)))(int*,int);
//用括号将ff(int)再括起来
也就意味着,ff是一个函数。
接着与前面的“*”结合,说明ff函数的返回值是一个指针。
然后再与后面的“()”结合,也就是说,该指针指向的是一个函数。
这种写法确实让人非常难懂,以至于一些初学者产生误解,认为写出别人看不懂的代码才能显示自己水平高。
而事实上恰好相反,能否写出通俗易懂的代码是衡量程序员是否优秀的标准。
一般来说,用typedef关键字会使该声明更简单易懂。
在前面我们已经见过:
int(*PF)(int*,int);
也就是说,PF是一个函数指针“变量”。
当使用typedef声明后,则PF就成为了一个函数指针“类型”,即:
typedefint(*PF)(int*,int);
这样就定义了返回值的类型。
然后,再用PF作为返回值来声明函数:
PFff(int);
返回函数指针会用在什么地方呢?
且听下文分解。
7.2函数指针
以typedefvoid(*halKeyCBack_t)(uint8keys,uint8state)为例,halKeyCBack_t是一个变量的名字,利用halKeyCBack_t可以声明变量,如halKeyCBack_tpHalKeyProcessFunction。
在C语言中,这种类型叫做函数指针,即指针指向的是一个函数。
具体形式为:
int(*pfun)(int,int)。
分析,通过括号强行将pfun首先与“*“结合,也就意味着,pfun是一个指针,接着与后面的“()”结合,说明该指针指向的是一个函数,然后再与前面的int结合,也就是说,该函数的返回值是int。
由此可见,pfun是一个指向返回值为int的函数的指针。
7.3指针函数
指针函数的声明:
类型名*函数名(函数参数表列);
以int*pfun(int,int);
为例。
由于“*”的优先级低于“()”的优先级,因而pfun首先和后面的“()”结合,也就意味着,pfun是一个函数。
int*(pfun(int,int));
接着再和前面的“*”结合,说明这个函数的返回值是一个指针。
由于前面还有一个int,也就是说,pfun是一个返回值为整型指针的函数。
7.4函数指针作为函数的返回值
在上面提到的指针函数里面,有这样一类函数,它们也返回指针型数据(地址),但是这个指针不是指向int、char之类的基本类型,而是指向函数。
下面将以程序清单1为例,说明用函数指针作为函数的返回值的用法。
当程序接收用户输入时,如果用户输入d,则求数组的最大值,如果输入x,则求数组的最小值,如果输入p,则求数组的平均值。
程序清单1求最值与平均值示例
1#include<
stdio.h>
2#include<
assert.h>
3doubleGetMin(double*dbData,intiSize)//求最小值
4{
5doubledbMin;
6inti;
7
8assert(iSize>
0);
9dbMin=dbData[0];
10for(i=1;
i<
iSize;
i++){
11if(dbMin>
dbData[i]){
12dbMin=dbData[i];
13}
14}
15returndbMin;
16}
17
18doubleGetMax(double*dbData,intiSize)//求最大值
19{
20doubledbMax;
21inti;
22
23assert(iSize>
24dbMax=dbData[0];
25for(i=1;
26if(dbMax<
dbData[i]){
27dbMax=dbData[i];
28}
29}
30returndbMax;
31}
32
33doubleGetAverage(double*dbData,intiSize)//求平均值
34{
35doubledbSum=0;
36inti;
37
38assert(iSize>
39for(i=0;
i++)
40{
41dbSum+=dbData[i];
42}
43returndbSum/iSize;
44}
45
46doubleUnKnown(double*dbData,intiSize)//未知算法
47{
48return0;
49}
50
51typedefdouble(*PF)(double*dbData,intiSize);
//定义函数指针类型
52PFGetOperation(charc)//根据字符得到操作类型,返回函数指针
53{
54switch(c)
55{
56case'
d'
:
57returnGetMax;
58case'
x'
59returnGetMin;
60case'
p'
61returnGetAverage;
62default:
63returnUnKnown;
64}
65}
66
67intmain(void)
68{
69doubledbData[]={3.1415926,1.4142,-0.5,999,-313,365};
70intiSize=sizeof(dbData)/sizeof(dbData[0]);
71charc;
72
73printf("
PleaseinputtheOperation:
\n"
);
74c=getchar();
printf("
resultis%lf\n"
GetOperation(c)(dbData,iSize));
//通过函数指针调用函数
上述程序中前面4个函数分别实现求最大值、最小值、平均值和未知算法,然后实现了GetOperation函数。
这个函数根据字符的返回值实现上面4个函数。
它是以函数指针的形式返回的,从后面的main函数的GetOperation(c)(dbData,iSize)可以看出,通过这个指针可以调用函数。
7.5结构体指针
指向一个结构体类型数据的指针叫做结构体指针,如下图所示,structnode*next就是指向一个node结构体的指针,node只是一个结构体的标识。
结构体指针也可以强制转换,那么就由指向A类型的结构体变为了指向B类型的结构体。
7.6->
运算符
这个运算符是用来获取结构体成员的值,它是用于指向结构体、C++中的class等含有子数据的指针用来取子数据(该运算符常见于C语言中的链表部分)。
换种说法,如果我们在C语言中定义了一个结构体,然后申明一个指针指向这个结构体,那么我们要用指针取出结构体中的数据,就要用到“->
”,通常的做法是pkt->
cmd.Data[0]。
->
是*运算符和.运算符的结合,相当于(*pkt).cmd.Data[0]被pkt->
cmd.Data[0]替换了。
即为定位pkt指向的结构,先对pkt间接寻址,然后再选择结构的成员cmd。
7.7运算符优先级
优先级
运算形式
名称或含义
运算对象的个数
结合方向
1
()
(e)
圆括号
左->
右
[]
a[e]
数组下标
p->
x
指针指向成员
.
x.y
结构体、共用体成员
2
!
e
逻辑非
(单目运算符)1
左<
-右
~
~e
按位取反
++
++x或x++
自增
--
--x或x--
自减
-+
-e
正负号
(类型)
(类型)e
强制类型转换
*
*p
指针运算,由地址求内容
&
求变量地址
sizeof
sizeof(t)
求某类型变量长度(byte)
3
e1*e2
乘、除和求余
/
%
4
+
e1+e2
加和减
-
5
<
e1<
e2
左移和右移
>
6
关系运算
=
7
==
e1==e2
等于和不等于比较
8
e1&
按位与
9
^
e1^e2
按位异或
10
|
e1|e2
按位或
11
逻辑与(并且)
12
||
e1||e2
逻辑或(或者)
13
?
e1?
e2:
e3
条件运算
14
x=e
赋值运算
+=
x+=e
复合赋值运算
-=
*=
/=
%=
^=
|=
15
e1,e2
顺序求值运算
右
注:
右为自左向右。
第一、像()[]->
.之类的理所当然是最优先的,其实它们压根也不算什么运算符了第二、除了上面的四种运算符之外,接下来就是单目运算符,也就是!
~++---(type)*&
sizeof了。
记住它们的顺序可是自右向左啊!
其实结合实例是很容易理解的,比如i++等。
第三、跟着就是双目运算符了,也是C语言运算符优先级中最容易让人混淆的地方了。
其实也没有那么可怕,你认真观察就会发现。
在双目运算符中,算术运算符优先级最高,然后是移位运算符,接着是关系运算符,再着是逻辑运算符。
不过这边需要说的是,在关系运算符中,<
<
=>
>
=比==!
=的优先级来得高。
此外,在逻辑运算符中,与运算又比或运算优先级来得高,异或则处于二者之间。
同样的,你可以类比出&
与||的优先级关系.第四、在双目操作符之后,就是三目操作符了,没有什么好说的了。
第五、然后是赋值操作符,你也许会把赋值操作符与三目运算符的优先级搞混。
没有关系,我想你一定写过这样的语句(如果没有,请你记住!
):
max=(a>
b)?
a:
b;
从这个语句里,你就不难记住赋值运算符为什么比三目运算符的优先级低了!
第六、逗号运算符是分割各个子语句的(感觉这么说有点不准确,不过我想大家会明白我的意思的),自然优先级最低了,我想这个应该不是很容易混淆的。
总结一下,按运算符优先级从高到低:
单目运算符->
双目运算符->
三目运算符->
赋值运算符->
逗号运算符特别在双目运算符中,按运算符优先级从高到低:
算术运算符->
移位运算符->
关系运算符(其中==和!
=优先级又较低)->
逻辑运算符(按位与-〉按位异或-〉按位或-〉逻辑与-〉逻辑或)!
运算符的结合性指同一优先级的运算符在表达式中操作的组织方向,即:
当一个运算对象两侧运算符的优先级别相同时,运算对象与运算符的结合顺序,C语言规定了各种运算符的结合方向(结合性)。
大多数运算符结合方向是“自左至右”,即:
先左后右,例如a-b+c,b两侧有-和+两种运算符的优先级相同,按先左后右结合方向,b先与减号结合,执行a-b的运算,再执行加c的运算。
除了自左至右的结合性外,C语言有三类运算符参与运算的结合方向是从右至左。
即:
单目运算符,条件运算符,以及赋值运算符。
关于结合性的概念在其他高级语言中是没有的,这是C语言的特点之一。
++a或a++和--a或a--分别称为前置加或后置加运算和前置减或后置减运算,都是单目运算符。
值得注意的是,前置、后置运算只能用于变量,不能用于常量和表达式,且结合方向是从右至左。
如当i=6时,求-i++的值和i的值。
由于“-”(负号)“++”为同一个优先级,故应理解为-(i++),又因是后置加,所以先有-i++的值为-6,然后i增值1为7,即i=7。
例1main()
inta=3,b=5,c;
c=a*b+++b;
printf(“c=%d”,c);
要得出c的值,首先要搞清+++的含义。
++运算符的结合方向是自右向左的,如果将表达式理解为:
c=a*b+(++b);
实际上C编译器将表达式处理为:
c=(a*b++)+b,因为
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- zigbee 开发