函数指针数组与返回函数指针的函数的含义与使用实例
近期在工作中遇到了一个对执行时间要求比较严格的嵌入式项目,使用指针相关的程序进行运行速度的优化。
一、什么是函数指针数组
void (*p)(void) = work1;
首先是函数指针,指针可以指向函数的地址。
void (*p[2])(void) = {work1,work2};
函数指针数组是由函数指针组成的数组,由于函数指针在数组内顺序排列,形成了数组成员和对应函数的映射关系。
二、什么是返回函数指针的函数
void (*get_bit(void)){
return work1;
}
函数的返回值可以是地址,更进一步成为函数的执行地址,可以写入到对应的函数指针中。
三、在单片机系统中的使用例子
这次实际的编程环境是主频为16m的单片机,输出一个8位的信号。
1.功能需求
信号由两个io的高低电平组成,一位信号表示(0x00-0x0f)中的一个数。
2.一开始的方案
void DsiWriteBit(u8 data){
switch(data){
case 0x00:BIT_0();break;
case 0x01:BIT_2();break;
case 0x02:BIT_2();break;
.
.
.
}
void Write(u32 data){
u8 i=8;
while(i--){
WriteBit(u8(data&0x0F));
data=data>>4;
}
}
writebit() 函数参数为对应当前为位的数值。通过switch语句确认对应的执行语句。
存在的问题
在实际使用中两个bit之间由于要执行switch语句,执行时间过长,单个语句的执行时间在1us左右,执行程序调用,switch的时间在10us以上。
3.使用指针后的方案
/*
对应bit的执行函数
*/
void BIT_0(void)
void BIT_F(void)
void (*get_bit(void))(u8 num){
switch(num){
case 0x00:return BIT_0;break;
.
.
.
case 0x0F:return BIT_F;break;
default:
break;
}
}
void Write(uint32 wdata){
u8 bitdata;
void (*p)(void);
void (*p1)(void);
void (*p2)(void);
void (*p3)(void);
void (*p4)(void);
void (*p5)(void);
void (*p6)(void);
void (*p7)(void);
//指针链接到对应的执行函数
bitdata = wdata&0x0f;
p = get_bit(bitdata);
wdata=wdata>>4;
.
.
.
bitdata = wdata&0x0f;
p7 = get_bit(bitdata);
wdata=wdata>>4;
//通过指针一次设定三次电流值,bittime在2.9us到3us之间
//从高位发送到低位
p7();
.
.
.
p();
}
3.1.返回函数指针的函数的方案
在P7()-P0()的执行部分所有的输出部分,一次执行bit之间的执行时间提升。
在执行之前将对应的执行函数的地址写入这几个函数指针。
3.2.函数指针数组的方案
void Write(uint32 data){
u8 bitdata[8];
u8 i;
void (*p[16])(void) = {BIT_0,BIT_1,BIT_2...........BIT_F};
for(i=0;i<8;i++){
bitdata[i] = data&0x0F;
data = data>>4;
}
p[bitdata[0]]();
.
.
.
p[bitdata[7]]();
}
通过函数数组与执行函数的映射关系,bit大小与数组成员直接链接,按照成员执行。