性能小钢炮-注册技术-轰轰烈烈干一场

天下武功 其实都阅兵 

注册技术 其实timer模块的码云我已经写了V1.0 V2.0

前面的那个SDK用的是数组!!我觉得可以统一下 用链表!!

统一:定时器周期执行一次函数----定时器执行LED-BEEP-RELAY这样---挂接ID-FUNCTION这样的函数注册

开始吧:

最开始是模块 链表的数据结构 一个一个的节点!上面的区别就是节点 是不一样的结构体

下面就是以前的timer 基本OK

#ifndef _GBASELIST_H_
#define _GBASELIST_H_

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <stddef.h>//offsetof

typedef void    (*func_call_back)(void);

/*****************模式1 周期性执行一次函数类似[000000000001][000000000001]这样子*************/
//节点的结构体
//因为我放弃了malloc只能参数自己携带内存 所以也对外提供节点的结构体
typedef struct  
{
	void        *next;//下一个节点
	uint8_t     handle;//ID
	
	uint8_t     start;//开关
	
	uint32_t    cnt;//这个是实际计数值 每次+1 直到==下面设置值 就执行fun
	uint32_t    time_out;//这个是约定值 溢出值
	
	void        (*fun)(void);
}node_oncetime_type;

//操作 节点结构体的结构体
typedef struct
{
    uint8_t (*creat) (  node_oncetime_type* node ,uint32_t time_out ,uint8_t start, func_call_back call_back);
    uint8_t (*stop)  (  uint8_t  handle);
    uint8_t (*start) (  uint8_t  handle);
}once_time_ops_type;

//对外提供的句柄
extern once_time_ops_type   timer;

//周期轮训业务 轮训链表的函数
void once_timer_list_loop( void );
#include "gbaselist.h"



static uint8_t	           SoncetimerTaskId = 0;   //表示每个节点的标号 可以统计个数 以及 根据ID查找以小博大
static node_oncetime_type *Soncetimerhead = NULL;  //链表的头结点


//遍历链表 周期loop执行
void once_timer_list_loop( void )
{
	node_oncetime_type 	 *priv = Soncetimerhead;

	while( priv != NULL )
    {
        if( priv->start)
        {
            if( ++priv->cnt >= priv->time_out)
            {
                priv->cnt = 0;
                if(priv->fun != NULL)	priv->fun();
            }
        }
        priv = priv->next;      
	  }
}


//关闭节点 《并没有链表移除 而是用标记位 优点:方便简单 缺点:内存无法释放》
uint8_t once_timer_stop(uint8_t handle)
{
	node_oncetime_type *priv = Soncetimerhead;
	
	while( priv != NULL )
    {
        if( priv->handle == handle)
        {
            priv->start = false;
            return true;
        }
        priv = priv->next;     
	}  
    
    return false;
}
//开启节点 
uint8_t once_timer_start(uint8_t handle)
{
	node_oncetime_type *priv = Soncetimerhead;
	
	while( priv != NULL )
    {
        if( priv->handle == handle)
        {
            priv->start = true;
            priv->cnt = 0;
            return true;
        }
        priv = priv->next;     
	}  
    
    return false;
}

//一个节点添加到链表 返回它的ID
uint8_t once_timer_register( node_oncetime_type* node, uint32_t time_out ,uint8_t start, func_call_back call_back)
{
	node_oncetime_type *priv;
	node_oncetime_type *this;

	this = node;//可以思考用malloc实现  目前这里和button一样我是自带内存
	
	this->cnt = 0;//实际计数值
	this->start = start;//开关
	this->handle = ++SoncetimerTaskId;//在链表中的ID
	this->time_out = time_out;//超时计数值
	this->fun = call_back;//节点逻辑函数
	this->next = NULL;//节点后继
	if( Soncetimerhead == NULL)
	{
		Soncetimerhead = this;//第一次 实例化head
	}
	else
	{
		priv = Soncetimerhead;
		while( priv->next != NULL )	priv = priv->next;//第一次以后:尾插
		priv->next = this;
	}    

	printf("new oncetimer handle=%d\r\n",SoncetimerTaskId);
	return (this->handle);
}


once_time_ops_type   timer =
{
    .creat = once_timer_register,
    .stop  = once_timer_stop , 
    .start = once_timer_start,
};




下面开始兼容第二个结构体!


typedef void (*fc)(void);

/*****************模式2 函数A函数B周期性循环执行类似[AAAAABBBBB][AAAAABBBBB]这样子*************/
//节点的结构体
typedef struct
{
	uint8_t          handle;//ID

    uint8_t          start; //节点功能开关

	uint32_t         setcnt;//设定的次数 比如鸣叫2次
	uint32_t         realCnt;//实际的次数 比如当前叫第1次

	uint32_t         RTime;//实际的计数值
	uint32_t         ATime;//设定的A计数值
	uint32_t         BTime;//设定的B计数值

	fc               funA;//[0-A之间的函数]
	fc               funB;//[A-B之间的函数]

	void            *next;//下一个节点
}node_twinkle_type;


//操作 节点结构体的结构体
//操作节点的函数的结构体
typedef struct
{
    uint8_t (*set)( void *pnode,uint8_t handle,uint8_t enable,uint8_t Cnt , uint32_t ATime ,uint32_t BTime,fc Afun,fc Bfun);
}node_twinkle_ops_type;

//对外提供的句柄
extern node_twinkle_ops_type twinkler;

//周期轮训业务 轮训链表的函数
void twinkler_list_loop( void );




//开发给别人去做
//一个实例的应用 比如你有4个LED 那么id是你控制哪一个 cnt是闪烁几次
typedef struct
{
    void (*init)   (void); 
    void (*write)   (uint8_t id,uint8_t cnt); 
}twinkle_app_type;




static uint8_t	           StwinklerTaskId = 0;   //表示每个节点的标号 可以统计个数 以及 根据ID查找以小博大
static node_twinkle_type  *Stwinklerhead = NULL;  //链表的头结点
//对节点的实例化 也就是赋值 这就是注册!
//每次都是尾巴插入
uint8_t twinkler_set(void *node ,uint8_t handle,uint8_t enable,uint8_t Cnt , uint32_t ATime ,uint32_t BTime,fc Afun,fc Bfun)
{

	node_twinkle_type * this=(node_twinkle_type *)node;
	node_twinkle_type * priv;
	if(this==NULL)return 0;
	this->setcnt = Cnt;
	this->realCnt = 0;
	this->RTime = 0;
	this->ATime = ATime;
	this->BTime = BTime;
	this->funA = Afun;
	this->funB = Bfun;   
	this->start = enable;	
    if(handle == 0)//代表第一次过来 是init 不是set
    {
        this->handle = ++StwinklerTaskId;
	    this->next   = NULL;
    }

	if( Stwinklerhead == NULL)
	{
		Stwinklerhead = this;//第一次 实例化head
	}
	else
	{
		priv = Stwinklerhead;
        if(handle == 0)//代表第一次过来 是init 不是set
        {
            while( priv->next != NULL )	priv = priv->next;//尾插 为了避免一直扩大链表 把handle再次传进来
            priv->next = this;
        }
        else
        {
            while( priv->next != NULL )	
            {
                if(priv->handle == handle)//通过ID再次在链表中找到它
                memcpy(priv,this,offsetof(node_twinkle_type,next));//OK 这个节点完成覆盖  因为priv->next不会被修改所以安全
                 //memcpy(priv,this,sizeof(node_twinkle_type));//也OK 因为this过来的时候 是死的 最后的next不会修改                
                 printf("old twinkler this->handle=%d\r\n",this->handle);                 
                 return (this->handle);
            }
        }
	}    

	printf("new twinkler handle=%d\r\n",StwinklerTaskId);
	return (this->handle);
}

//遍历链表 周期loop执行
void twinkler_list_loop( void )
{
	node_twinkle_type 	 *priv = Stwinklerhead;

	while( priv != NULL )
    {
        if( priv->start)
        {

            if( priv->RTime ++ < priv->ATime) //[0---A]
            {
                if( *priv->funA )priv->funA() ;
            }
            else                             //[A----A+B]
            {
                if( *priv->funB )priv->funB() ;
            }

            if( priv->RTime  >  priv->ATime + priv->BTime)//[A+B---无穷大]
            {
                priv->RTime = 0;

                if( ++priv->realCnt >= priv->setcnt)
                {
                    priv->start = 0;//执行约定次数以后关闭
                }
            }
        }
        priv = priv->next;      
	}
}
node_twinkle_ops_type twinkler =
{
    .set = twinkler_set,
};

/*此后执行BEEP鸣叫2次的操作是 第一次先twinkler_set--0完成注册到链表 以后都是回传ID控制鸣叫就是再次设置*/


需要注意的就是不要重复注册

给了外部一个结构体 外部模块举例

#ifndef _twbeep_H_
#define _twbeep_H_

#include "gbaselist.h"

extern twinkle_app_type beep;


#endif




#include "main.h"
#include "twbeep.h"

node_twinkle_type twbeep;

void beepon(void) {	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8, GPIO_PIN_RESET);}
void beepoff(void){	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8, GPIO_PIN_SET);}


void TWBEEP_init(void)
{
    twinkler.set(&twbeep,0,0,0,100,200,beepon,beepoff);

}

 
void TWBEEP_write(uint8_t i,uint8_t num)
{

    twinkler.set(&twbeep,twbeep.handle,1,num,100,200,beepon,beepoff);
}




twinkle_app_type    beep=
{
    .init =  TWBEEP_init,
    .write = TWBEEP_write,
};

 

 

 

现在开始做第三个注册ID FUN


/*****************模式3 ID---FUNCTION对应的钩子函数列表作为CMD的列表*************/
typedef void (*CommandCallBack)(int fd, uint8_t sn, uint16_t len, uint8_t *data);
typedef struct  
{
    const char              *name;
    const char              *help;
	uint8_t                 handle;//ID	
	CommandCallBack         fun;
	void                    *next;//下一个节点
}node_command_type;


typedef struct
{
    int             (*Register)  ( node_command_type *cmds, int numCmds);
    node_command_type * (*find)  ( uint16_t handle);
}command_ops_type;

extern command_ops_type commer;
/*它的应用是直接在模块中自己扩展 我内部可以注册好ID-FUN以后去解析数据拿到ID就调用对应FUN*/
#endif



static uint8_t	           SclientCMDId = 0;   //可以不要
static node_command_type * Sclienthead =NULL;

//以小博大 根据其中一个成员找出节点
node_command_type *findCmd(uint16_t handle) 
{
	node_command_type *priv = Sclienthead;

    while( priv->next != NULL )	
    {
        if(priv->handle == handle)//通过ID再次在链表中找到它
        return priv;
    }
    return NULL;
}


//就是注册 都是废话 只需要 return 0;一句话
int cliRegisterCmd(node_command_type *cmd) 
{
    if (!cmd->name || !cmd->fun) 
        return -1;

    node_command_type *priv ;

	if( Sclienthead == NULL)
	{
		Sclienthead = cmd;
	}
	else
	{
		priv = Sclienthead;
		while( priv->next != NULL )	priv = priv->next;
		priv->next = cmd;
	}    
    ++SclientCMDId;
	printf("new cliRegisterCmd handle=%d\r\n",SclientCMDId);
	return (SclientCMDId);
}

//封装一层
int cliRegisterCmds(node_command_type *cmds, int numCmds) 
{
    int err; 
    for (int i = 0; i < numCmds; i++) 
    {
        if ((err = cliRegisterCmd(cmds++)) != 0) 
        {
            return err;
        }
    }
    
    return 0;
}

command_ops_type   commer =
{
    .Register = cliRegisterCmds,
    .find  = findCmd , 
};

这个时候 你会发现 它其实是最简单那个!!!!

APP

#include "GAppCmd.h"


static void connect(int fd, uint8_t sn, uint16_t len, uint8_t *data);
static void clearCard(int fd, uint8_t sn, uint16_t len, uint8_t *data);


static node_command_type commands[] = {
    {"connect",   NULL, 0, connect},
    {"clearCard", NULL, 1, clearCard},
};

static void connect(int fd, uint8_t sn, uint16_t len, uint8_t *data) {
}

static void clearCard(int fd, uint8_t sn, uint16_t len, uint8_t *data) {
}


void registerCmds(void) {
    commer.Register(&commands[0], sizeof(commands) / sizeof(commands[0]));
}



#ifndef GAppCmd_h
#define GAppCmd_h

#include "gbasetimerlist.h"

void registerCmds(void);

#endif 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值