// 通常,我们使用int num来定义个int变量
int num;
// 使用int* num来定义一个指向num的指证
int* num;
// 也就是去掉num变量,int*是固定句式,表示定义一个int指针
// 因此我们可以类比,void (*pFunc)(void)是定义一个函数指针,指向pFunc这个函数,那么去掉变量pFunc,void (*)(void)就是一个固定句式
void (*pFunc)(void);
/*
当申明一个int num时,其类型是int,我们也可以使用(int)将变量强制转换为int类型
如:
int num;
char str = 'A';
num = (int)str;
同理,当申明一个int* num时,其类型是int*,我们也可以使用(int*)将变量强制转换为int*类型
同理,当申明一个void (*pFunc)(void)时,其类型是void (*)(void),我们也可以使用(void (*)(void))将变量强制转换为void (*)(void)类型
*/
函数名本身就是一个指针,指向该函数在内存中的入口地址。
函数指针的类型必须严格匹配,包括:返回值类型 和 参数列表(参数个数和类型)
例如:
void foo(void); // 函数声明
void (*pFunc)(void); // 匹配的函数指针
pFunc = foo; // 正确赋值
在 bsp_StartHardTimer 函数中:
void bsp_StartHardTimer(uint8_t _CC, uint32_t _uiTimeOut, void *_pCallBack);
参数 _pCallBack 是 void * 类型(泛型指针),目的是让函数可以接受任意类型的指针(如函数指针、数据指针等)。
但 void * 会丢失原始类型信息,编译器无法直接用它调用函数。
C语言规定:
void * 是“无类型指针”,仅表示一个内存地址,不包含类型信息。
函数调用必须知道:函数的返回类型 和 函数的参数列表
如果直接用 void * 调用函数,编译器无法生成正确的机器码(不知道如何传参、如何返回值)。
错误示例:
void *pFunc = (void *)foo; // 假设 foo 是一个函数
pFunc(); // 编译错误!不知道 pFunc 的类型
1、按下按钮后,启动定时器。需要传入回调函数
// main.c
/* 摇杆OK键按下,启动单次定时器中断,50ms后在定时器中断将任务vTaskLED恢复 */
case JOY_DOWN_OK:
printf("摇杆OK键按下,启动单次定时器中断,50ms后在定时器中断将任务vTaskLED恢复\r\n");
bsp_StartHardTimer(1 ,50000, (void *)TIM_CallBack1);
break;
// 其中
static void TIM_CallBack1(void)
{
BaseType_t xYieldRequired;
/* 恢复挂起任务 */
xYieldRequired = xTaskResumeFromISR(xHandleTaskLED);
/* 退出中断后是否需要执行任务切换 */
if( xYieldRequired == pdTRUE )portYIELD_FROM_ISR(xYieldRequired);
}
2、bsp_timer.c中定义了回调函数指针
// bsp_timer.c
/* 保存 TIM定时中断到后执行的回调函数指针 */
static void (*s_TIM_CallBack1)(void);
void bsp_StartHardTimer(uint8_t _CC, uint32_t _uiTimeOut, void * _pCallBack)
{
...
s_TIM_CallBack1 = (void (*)(void))_pCallBack;
...
}
// 在中断服务程序中,调用回调函数
void TIM2_IRQHandler(void){
...
s_TIM_CallBack1();
...
}