【内附源码】对【钴钥金库———点亮LED】进行优化:兼容hal库和标准库(stm32f103zet6)励志在CSDN上拉坨大的!!!!

        默认情况下,高电平点亮LED,低电平熄灭。

修改的地方

1、兼容hal库和标准库(新增)

        在led.c的起始处的定义了一个宏(后期会移到其他地方),给他赋值0就是使用标准库,使用hal库的话就给他改成1,这里不用担心,放心改,后面已经使用预处理处理了了。

2、led_cfg_t结构体(删去)

        把原来的时钟删去了,因为时钟只在初始化GPIO的时候用到,而且hal的GPIO初始化都是直接生成的,所以找到了其他解决办法来代替这个位置,就给丫干掉了!

至于GPIO初始化时钟怎么玩的,看下文!

3、注册led端口及引脚(修改)

        注册led的地方也换位置了喔,由原来在led_init()函数里的局部变量改为全局变量(有点点费内存就是了)

4、预处理(新增)

        为了兼容 hal,在各个位置加了预处理,不用管他

5、p_led_task函数(修改)

         因为该函数的返回值是一个指针,所以把它函数名改成了“p_led_task”,给丫加了个前缀"p_",意为返回值为指针类型。另外节省行数,把if else改成了三段式,不影响,跟原来食用方法一样

6、 v_led_task函数(新增)

        如你所见这个函数和上面那个长的及其相像,没错这俩玩意实现的功能是一样的,看到这个“v_”的前缀,,想必会明白该函数返回值为void也就是没有返回值。

        是的没错,就是这样,这个是直接操作gpio口的高低电平,并没有返回指针,至于我收起来的那部分也无需管,就是为了兼容hal的

7、led_init函数(修改)

         众所周知hal用不到这玩意儿。。。。。所以第一个修改的地方就是用预处理括起来。(不用管不用管),唯一起作用的就是把led灯全给丫关上。

        (这里不给放全部代码了,两个文件的代码插文章末尾)

        然后看我给开时钟那里做的手脚。

        我先用要初始化的端口减去GPIOA,就得到了端口号的偏移量,然后给丫右移10位,把字节单位转为字单位,就是对应的时钟的偏移量的,然后再用GPIOA的时钟左移这个偏移量就是开启当前要初始化的端口的时钟了。????这里看不懂,其实我也不懂,我们不妨问问神奇的海螺。

 

8、led_test函数(新增) 

         这就是把上篇文章的主函数里运行的玩意挪了过来,其功能如注释所言,注册多少个led灯,,就跑这些数目的流水灯,同样兼容hal库

源码

led.c

#include "led.h"

//点灯:默认是0点亮 1熄灭

//如果使用HAL开发则把下面的0改成1,使用标准库则无需管
#define HAL_Lib 0//默认标准库\
                   0是标准库 \
                   1为hal库

/***************************************************************************/

//根据需求在该数组进行注册
led_cfg_t led_cfg[] =
{
    /*端口*/    /*引脚*/
    {led1_port,  led1_pin},

    //.....
};
/***************************************************************************/

//在以下区间定义开关灯函数/
void led1_on(void)
{
#if HAL_Lib
    /*根据电路图看是高电平点亮还是低电平点亮选择注释掉*/
    // HAL_GPIO_WritePin(led1_port,led1_pin,GPIO_PIN_SET);//1点亮
    HAL_GPIO_WritePin(led1_port, led1_pin, GPIO_PIN_RESET);//0点亮

#else
    /*根据电路图看是高电平点亮还是低电平点亮选择注释掉*/
    // GPIO_SetBits(led1_port,led1_pin);//1点亮
    GPIO_ResetBits(led1_port,led1_pin); //0点亮
#endif
}

void led1_off(void)
{
#if HAL_Lib
    /*根据电路图看是高电平点亮还是低电平点亮选择注释掉*/
    HAL_GPIO_WritePin(led1_port,led1_pin,GPIO_PIN_SET);//1熄灭
    // HAL_GPIO_WritePin(led1_port, led1_pin, GPIO_PIN_RESET);//0熄灭
#else
    /*根据电路图看是高电平熄灭还是低电平熄灭选择注释掉*/ 
    GPIO_SetBits(led1_port,led1_pin);       //1熄灭
    // GPIO_ResetBits(led1_port,led1_pin);  //0熄灭
#endif
}   


//可参考以上格式修改或添加
/*添加完之后在下面的 led_on_pointer[] 和 led_off_pointer [] 数组里分别进行注册*/
//...

/

/*定义函数指针类型*/
typedef void(* led_function_pointer)(void);

//在这里的下面注册 led_on,只需函数名即可
static led_function_pointer led_on_pointer [] = 
{
    led1_on,

    //可参考以上格式修改或添加
	//...
	
};
//在这里的下面注册 led_off,只需函数名即可
static led_function_pointer led_off_pointer [] = 
{
    led1_off,

	//可参考以上格式修改或添加
	//...
	
};

/

下面的函数不用改动喔!!!!///
//led任务:对外的接口函数
//参数1:   led号,选择第几个led,这个是要按照上面的 函数指针数组里注册的顺序填写喔
//参数2:   led的状态,给1亮,给0灭
//返回值:  返回值是一个函数指针,指向一个 返回值为 void 类型指针、参数为 void 的函数
void (* p_led_task(unsigned char led_num, unsigned char led_sta))(void)
{
	 return (led_sta == 1) ?  (led_on_pointer[led_num]) : (led_off_pointer[led_num]);
}
/

//这个函数也不要动
//这个是直接操作GPIO点亮和熄灭灯,不使用指针
//参数1:   led号,选择第几个led,这个是要按照上面的 函数指针数组里注册的顺序填写喔
//参数2:   led的状态,给1亮,给0灭
//返回值:  无返回值
void v_led_task(unsigned char led_num, unsigned char led_sta)
{
#if HAL_Lib
    led_sta \
    ? \
    /*根据电路图看是高电平点亮还是低电平点亮选择注释掉*/
    //1点亮
    // HAL_GPIO_WritePin(led_cfg[led_num].Led_Port,led_cfg[led_num].Led_Pin,GPIO_PIN_SET)\
    //0点亮
    HAL_GPIO_WritePin(led_cfg[led_num].Led_Port,led_cfg[led_num].Led_Pin,GPIO_PIN_RESET)\
    :\
    /*根据电路图看是高电平点亮还是低电平点亮选择注释掉*/
    //1熄灭
    HAL_GPIO_WritePin(led_cfg[led_num].Led_Port,led_cfg[led_num].Led_Pin,GPIO_PIN_SET);\
    //0熄灭
    // HAL_GPIO_WritePin(led_cfg[led_num].Led_Port,led_cfg[led_num].Led_Pin,GPIO_PIN_RESET);

#else
    led_sta \
    ? \
    /*根据电路图看是高电平点亮还是低电平点亮选择注释掉*/
    //1点亮
    // GPIO_SetBits(led_cfg[led_num].Led_Port,led_cfg[led_num].Led_Pin)\
    //0点亮   
    GPIO_ResetBits(led_cfg[led_num].Led_Port,led_cfg[led_num].Led_Pin)\
    :\
    /*根据电路图看是高电平点亮还是低电平点亮选择注释掉*/
    //1熄灭
    GPIO_SetBits(led_cfg[led_num].Led_Port,led_cfg[led_num].Led_Pin);\
    //0熄灭   
    // GPIO_ResetBits(led_cfg[led_num].Led_Port,led_cfg[led_num].Led_Pin);
#endif
}

//LED初始化
void led_init(void)
{

#if HAL_Lib
#else
    /*只需要在上面注册,下面的东西不要动喔*/
    GPIO_InitTypeDef GPIO_InitStruct;
#endif
    led_function_pointer led_action;
    for(int i = 0; i<led_cfg_num; i++)
    {
#if HAL_Lib
#else
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA<< 		
							  ((led_cfg[i].Led_Port - GPIOA)>>10),  
								ENABLE);
		GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
		GPIO_InitStruct.GPIO_Pin=led_cfg[i].Led_Pin;
		GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
		GPIO_Init(led_cfg[i].Led_Port,&GPIO_InitStruct);
#endif
		// 熄灭所有的led
		led_action = p_led_task(i,0);
		led_action();
    }
}

//注册多少个LED就流水多少个LED
void led_test(void)
{
    led_function_pointer led_action;
    while(1)
    {
        for(int i = 0; i< led_cfg_num; i++)
        {
            led_action = p_led_task(i,1);
            led_action();
    #if HAL_Lib
            HAL_Delay(1000);
    #else
            delay_ms(1000);
    #endif        
            led_action = p_led_task(i,0);
            led_action();
    #if HAL_Lib
            HAL_Delay(1000);
    #else
            delay_ms(1000);
    #endif 
        }
    }    	
}

led.h 

#ifndef _LED_H_
#define _LED_H_

#if HAL_Lib
#include "stm32f1xx_hal.h"
#else
#include "system.h"
#include "delay.h"
#endif

/*需要配置的led的数量,这里不需要改喔*/
#define led_cfg_num sizeof(led_cfg)/sizeof(led_cfg[0])

可根据需求修改下方宏
#define led1_port   GPIOC                   //端口
#if HAL_Lib
#define led1_pin    GPIO_PIN_0              //引脚
#else
#define led1_pin    GPIO_Pin_0              //引脚
#endif


//可参考以上格式修改或添加
/*添加完之后在 led.c 里的 led_cfg[] 数组里进行注册*/
//...

/

//led 配置结构体
typedef struct
{
    GPIO_TypeDef *Led_Port; //端口
    uint16_t Led_Pin;       //引脚
}led_cfg_t;

//LED初始化
void led_init(void);
//LED任务:返回值是指针
void (* p_led_task(unsigned char led_num, unsigned char led_sta))(void);
//LED任务:直接操作GPIO,无返回值
void v_led_task(unsigned char led_num, unsigned char led_sta);
//LED测试:注册多少个LED就流水多少个LED
void led_test(void);

#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值