为了代码易维护 可读性 将app和设备驱动功能分开 不直接调用函数
而是采用回调和注册回调方式
dev_io.h
c
#ifndef __DEV_IO__H__
#define __DEV_IO__H__
#include "main.h"
//回调
typedef void (*Fun)(uint16_t GPIO_Pin); // 回调函数类型
uint8_t BatAdd(Fun func); //注册回调
#endif
dev_io.c
c
#include <stdio.h>
#include <stdlib.h>
//#include "stdio.h"
#include <string.h>
#include <stdarg.h>
#include "dev_io.h"
//当前app是否打印
#if 1
#define debug printf
#else
static void debug(const char *format, ...){}
#endif
//打印16进制
static void debugH(uint8_t *buf,int len){
for(int i=0; i < len; i++){
debug("0x%0X ",buf[i]);
}
debug("\n");
}
//*********************回调 */
typedef struct {
//EventID ID; // 回调事件标志id
Fun fun; // 指向函数的指针
} CallbackStruct; //回调结构
CallbackStruct *Bat = NULL; //回调表
uint8_t BatLen = 0; //回调表成员数
//释放回调 表
void BatFree(void) {
free(Bat);
Bat = NULL;
BatLen = 0;
}
/****************
注册回调函数,成功返回ID 失败返回0
****************/
uint8_t BatAdd(Fun func) {
if (Bat == NULL) { //分配初始内存
Bat = malloc(sizeof(CallbackStruct));
if (Bat == NULL) {
return 0; // 内存分配失败,返回0或错误代码
}
BatLen = 0; // 初始化大小为0(但实际上在第一次添加时会被加1)
}
CallbackStruct *temp =
realloc(Bat, (BatLen + 1) * sizeof(CallbackStruct)); // 为回调表分配更多内存
if (temp == NULL) {
return 0; // realloc失败,返回0或错误代码
}
Bat = temp;
Bat[BatLen].fun = func; // 添加回调并更新大小
BatLen++;
return BatLen; // 返回回调的ID(索引+1)
}
/****************
触发回调
****************/
static void CallFun(uint16_t GPIO_Pin) {
for(uint8_t i=0;i < BatLen;i++){ //遍历储存在变量的回调函数
if (Bat[i].fun != NULL ) {
Bat[i].fun(GPIO_Pin); //调用
}
}
}
//*********************回调 */
// 外部中断回调函数
/*
- UART8 作为输出,当io倍触发时通过UART发出数据
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
CallFun(GPIO_Pin);
}
在app上使用
c
//io回调
static void Callio(uint16_t GPIO_Pin){
}
BatAdd(Callio); //注册io回调
这样每设备驱动文件回调都不会直接调用app的函数
app主动采用注册回调方式
实现设备驱动和app彻底分开