打印
[其它]

基于AT32(STM32)单片机的模块化代码之——Led代码模块化

[复制链接]
659|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
有何不可0365|  楼主 | 2022-12-31 22:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
基于AT32(STM32)单片机的模块化代码之——Led代码模块化
上个文章讲了按键的模块化代码,这个文章贴一下我写的led灯部分的模块化代码,其实大同小异,按键和led灯都是gpio口的应用,不同的是用于按键的gpio口方向为输入方向,用于led灯的gpio口的方向为输出方向

1.环境介绍
平台:AT32F415单片机,雅特力公司的AT32系列单片机其实跟STM32系列单片机大同小异,包括库函数等基本都是一样的,所以这款代码无论是AT32还是STM32都是适用的。
开发环境:MDK V5 for arm

使用特权

评论回复
评论
有何不可0365 2022-12-31 22:53 回复TA
———————————————— 版权声明:本文为CSDN博主「大白哦」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_39932620/article/details/107299155 
沙发
有何不可0365|  楼主 | 2022-12-31 22:54 | 只看该作者
.代码模块化思路
2.1在led.h文件中定义枚举类型,枚举应用到的led灯
//枚举led灯
typedef enum
{
        LED1_W,
        LED1_O,
       
        LED2_W,
        LED2_O,
       
        LED3_W,
        LED3_O,
       
        LED4_W,
        LED4_O,
       
        LED5_W,
        LED5_O,
       
        LED6_W,
        LED6_O,
               
        LED7_W,
        NUM_LED
}ENUM_LED;

使用特权

评论回复
板凳
有何不可0365|  楼主 | 2022-12-31 22:55 | 只看该作者
将枚举的led与其实际应该进行映射
//将led灯与其标识的功能对应上,电热毯项目
#define LED_POWER     LED7_W

//区域1各级led对应
#define LED_Z1L1_W           LED1_W
#define LED_Z1L1_O           LED1_O
#define LED_Z1L2_W           LED2_W
#define LED_Z1L2_O           LED2_O
#define LED_Z1L3_W      LED3_W
#define LED_Z1L3_O      LED3_O

//区域2各级led对应
#define LED_Z2L1_W          LED4_W
#define LED_Z2L1_O          LED4_O
#define LED_Z2L2_W          LED5_W
#define LED_Z2L2_O          LED5_O
#define LED_Z2L3_W          LED6_W
#define LED_Z2L3_O          LED6_O

使用特权

评论回复
地板
有何不可0365|  楼主 | 2022-12-31 22:56 | 只看该作者
这样,当在app逻辑层需要对哪个led灯进行操作时,直接用LED_POWER这些实际用途的宏定义操作,如果某些个led灯在后续改版中功能进行了互换,只需要在功能映射宏定义这边做一下修改,其它其它地方都不用动,方便又省事。

使用特权

评论回复
5
有何不可0365|  楼主 | 2022-12-31 22:56 | 只看该作者
在led.c文件中定义数个全局变量,用来作为配置功能,或者存储功能等用途

使用特权

评论回复
6
有何不可0365|  楼主 | 2022-12-31 22:57 | 只看该作者
//根据项目中实际的led灯与引脚的对应关系进行配置
GPIO_Type* gs_LedPort[NUM_LED] = {GPIOA,GPIOC,GPIOA,GPIOC,GPIOB,GPIOD,
                                                                GPIOC,GPIOA,GPIOA,GPIOF,GPIOF,GPIOC};
u16 gu16_LedPins[NUM_LED] = {GPIO_Pins_8,GPIO_Pins_9,GPIO_Pins_15,GPIO_Pins_12,GPIO_Pins_3,GPIO_Pins_2,
                                                        GPIO_Pins_4,GPIO_Pins_7,GPIO_Pins_6,GPIO_Pins_5,GPIO_Pins_4,GPIO_Pins_14

使用特权

评论回复
7
有何不可0365|  楼主 | 2022-12-31 22:57 | 只看该作者
例如我用PC14用做显示电源的指示灯,那么我就将对应的gs_LedPort[LED_POWER]=GPIOC,
gu16_LedPins[LED_POWER]=GPIO_Pins_14;

使用特权

评论回复
8
有何不可0365|  楼主 | 2022-12-31 22:58 | 只看该作者
实现几个具体的功能函数
1.点亮单个led灯函数
void LED_ON(ENUM_LED LEDx)
{
        GPIO_ResetBits(gs_LedPort[LEDx],gu16_LedPins[LEDx]); //根据实际电路进行配置
}

使用特权

评论回复
9
有何不可0365|  楼主 | 2022-12-31 22:59 | 只看该作者
关闭单个led灯的函数
void LED_OFF(ENUM_LED LEDx)
{
        GPIO_SetBits(gs_LedPort[LEDx],gu16_LedPins[LEDx]);//根据实际电路进行配置
}

使用特权

评论回复
10
有何不可0365|  楼主 | 2022-12-31 23:00 | 只看该作者
需要根据实际电路设计对对应的gpio口赋低电平或者高电平。例如当对应的gpio为低电平时,led亮,就在LED_ON()函数中调用将gpio设置为低电平的函数。

使用特权

评论回复
11
有何不可0365|  楼主 | 2022-12-31 23:00 | 只看该作者
led模块初始化函数
void LED_Init()
{
        ENUM_LED i;       
        GPIO_InitType GPIOType;
       
        //led灯引脚循环初始化
        for (i = 0; i < NUM_LED; i++)
        {
                GPIO_StructInit(&GPIOType);
                GPIOType.GPIO_Pins = gu16_LedPins[i];
                GPIOType.GPIO_Mode = GPIO_Mode_OUT_PP; //模式设置为推挽输出模式
                GPIOType.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
                GPIO_Init(gs_LedPort[i],&GPIOType);

                LED_OFF(i);//先关闭led灯
        }       
}

使用特权

评论回复
12
有何不可0365|  楼主 | 2022-12-31 23:01 | 只看该作者
这几个基础函数写好了以后基本就完成了,后面就是根据实际的app部分的逻辑,自行再调用就可以,例如我自己项目中用到的当发生某个系统动作时更新led状态函数:

使用特权

评论回复
13
有何不可0365|  楼主 | 2022-12-31 23:02 | 只看该作者
void LED_UpdatSysLed(u8 act)
{
        act = (ENUM_SYSACT)act;
               
        switch (act)
        {
                case SYS_ACTTURNON: //开机动作时led灯更新
                        LED_ON(LED_POWER);
                        LED_UpdatPowerOnLed();
                        break;
                                       
                case SYS_ACTTURNOFF: //关机动作时led灯更新
                        LED_OFF(LED_POWER);
                        LED_UpdatPowerDownLed();
                        break;
                       
                        case SYS_ACTRECOVE:
                        break;
                       
                default:
                        break;
        }

}

使用特权

评论回复
14
有何不可0365|  楼主 | 2022-12-31 23:03 | 只看该作者
其它,分享一个简单的呼吸灯的函数
//亮度变化方向
#define DIR_UP      1
#define DIR_DOWN     2

//灯光亮度调节的最大最低档位,
#define ADJLEV_MAX     200
#define ADJLEV_MIN    20
//led从暗到最亮的一个周期,单位ms
#define LED_BREATHCRCLE  3000

void Led_Breath()
{
        u32 curTim=Tim_GetT2MSTime();
        static u32 lastStepTim=0;
        static u8 dir=0;
        static u16 curLev=0;

        //每次进入呼吸模式都从最暗开始变化,该if语句只有在每次第一次进入呼吸模式时才会执行
        if(!gu8_LedBreath**)
        {
                dir=DIR_UP;
                curLev=ADJLEV_MIN;
                gu8_LedBreath**=1;
        }
       
        //每隔固定时间就更新一次pwm占空比,实现灯光亮度变化
        if(curTim-lastStepTim>=(LED_BREATHCRCLE/ADJLEV_MAX))
        {
                if(dir==DIR_UP)
                {
                        curLev++;
                        //lev到顶时重置变化方向为向下
                        if(curLev>=ADJLEV_MAX)
                        {
                                dir=DIR_DOWN;
                                curLev=ADJLEV_MAX;
                        }
                }
                else if(curLev==DIR_DOWN)
                {
                        curLev--;
                        //lev触底时重置变化方向为向上
                        if(curLev<=ADJLEV_MIN)
                        {
                                dir=DIR_UP;
                                curLev=ADJLEV_MIN;
                        }
                }
                PWM_SetDutyCycl(PWM_ZONE2,(curLev/2));//设置pwm占空比的函数,自行实现
                lastStepTim=curTim;
        }       
}

使用特权

评论回复
15
有何不可0365|  楼主 | 2022-12-31 23:04 | 只看该作者
呼吸灯的原理其实很简单,led要想点亮,那么就要led正确的一端是高电平,另一端是低电平,led就会点亮,并且在电压符合led参数的情况下,两端的电压差越高,那么led越亮。所谓的呼吸灯,就是led先从暗到亮,再从亮到暗的一个循环过程。那么这个要怎么实现呢,就需要将单片机控制的led灯的一端设置为pwm引脚,然后通过调节pwm的占空比,实现调节led灯的亮度。这样在一次由亮到暗的过程中,每个一段时间,按照比例去调一下占空比,就能实现灯光越来越暗。

使用特权

评论回复
16
有何不可0365|  楼主 | 2022-12-31 23:08 | 只看该作者
另外还想再提一点的是,我上面写的呼吸灯的代码,每次调节led灯的pwm占空比的时间是相等的,都是
(LED_BREATHCRCLE/ADJLEV_MAX),前阵子做的一个小项目中,因为单片机硬件资源的限制,以及灯光比较亮等原因,呼吸灯过程中,每次在灯关暗区的时候,人眼能够明显察觉到灯关在变暗的过程中会有闪烁情况,后来想了一个办法,那就是根据当前的调节的步骤数,动态变化每步的调节时间,在暗区时就让两步之间的时间间越来越小,在俺去的时候就让两步之间的时间间隔越来越大,因为人眼对暗这个过程敏感,所以这样处理一下,让俺去的时候变得越来越快,这样暗区时间就会缩小很多,人眼就不会觉得暗区灯光变化时会有闪烁情况。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

38

主题

702

帖子

0

粉丝