Funpack5-2 - 用EV41C56A开发板实现触摸控制LED亮度
该项目使用了EV41C56A开发板,实现了触摸控制LED亮度的设计,它的主要功能为:触摸、短按、长按和LED调光。
标签
触摸
Funpack5-2
EV41C56A开发板
--小灰灰--
更新2026-06-15
7

项目介绍

本项目用Microchip的EV41C56A开发板,实现了软件模拟PWM来控制LED亮度控制功能。支持短按按键控制LED 开或者关、长按按键实现亮度双向线性平滑调节(灭→最亮→灭循环),且调光过程无闪烁、无跳变,满足人机交互的流畅性与视觉舒适性要求。

硬件介绍

本项目仅使用 EV41C56A 开发板板载硬件资源,核心硬件如下:

  1. PIC32CMLS00 32 位单片机:项目主控核心,内核:Cortex-M23,主频:48HMz,Flash / SRAM:512 / 64 KB。
  2. 板载LED:默认连接单片机指定的GPIO引脚,作为PWM调光执行器件,通过不同占空比的电平信号实现亮度调节;
  3. 板载触摸按键:用于输入短按 / 长按控制指令,连接单片机GPIO引脚;
  4. 电源电路:板载USB供电电路,为单片机及外设提供稳定的工作电压。

image.png

方案框图和项目设计思路介绍

image.png

主循环软件模拟 PWM 核心原理

无定时器中断,通过主循环 for 循环遍历 255 个周期计数实现 PWM 波形:定义 PWM 周期为 255 级,亮度值 0~255 对应占空比 0%~100%;循环中判断计数值与亮度值,控制 LED GPIO 电平输出,纯软件实现调光。

触摸按键状态识别逻辑

软件计数消抖 + 长按阈值判断:

  • 消抖:连续 50 次检测到触摸,判定为按键稳定按下;
  • 短按:触摸按下时长<1000 次计数并释放,切换 LED 开关;
  • 长按:触摸按下时长 ≥ 1000 次计数,触发连续亮度调节。

亮度双向循环调节逻辑

亮度范围:0(灭)~255(最亮),通过方向标志位dir控制:

  • 递增:亮度从 0→255,到达最大值自动切换为递减;
  • 递减:亮度从 255→0,到达最小值自动切换为递增;
  • 长按每 10 次计数刷新一次亮度,保证调光平滑。

短按开关逻辑

短按触摸按键:LED 开启则直接熄灭(亮度 0);LED 关闭则直接点亮为最亮(255),并重置调光方向为递增。

软件流程图及关键代码介绍

开发工具链:

  • MPLAB X IDE:代码编辑、编译、下载与在线调试;
  • XC32 C 编译器:PIC32 系列单片机专用编译器;
  • MPLAB Code Configurator (MCC):图形化初始化 GPIO、触摸驱动;

软件流程图:

image.png

 #define LONG_PRESS_TRIGGER  1000
 #define BRIGHT_MAX         255
 #define BRIGHT_MIN         0
 #define PWM_FULL_CYCLE     255
 #define CHANGE_DELAY       10
 ​
 int main ( void )
 {
     uint32_t msp_ns = *((uint32_t *)(TZ_START_NS));
     volatile funcptr_void NonSecure_ResetHandler;
 ​
     /* Initialize all modules */
     SYS_Initialize ( NULL );
 ​
     if (msp_ns != 0xFFFFFFFF)
    {
         __TZ_set_MSP_NS(msp_ns);
         NonSecure_ResetHandler = (funcptr_void)(*((uint32_t *)((TZ_START_NS) + 4U)));
         NonSecure_ResetHandler();
    }
 ​
     uint8_t key_state = 0;
     uint8_t prev_key_state = 0;
     uint32_t press_cnt = 0;
     uint8_t  led_enable = 0;
     uint8_t  brightness = 0;
     uint8_t  dir = 1;
     uint32_t slow_cnt = 0;
     uint8_t  short_press_flag = 0;
     uint8_t  debounce_cnt = 0;
 ​
     while ( 1 )
    {
         touch_process();
         prev_key_state = key_state;
         key_state = get_sensor_state(0) & 0x80;
 ​
         if(key_state)
        {
             if(debounce_cnt < 255) debounce_cnt++;
        }
         else
        {
             debounce_cnt = 0;
        }
         
         uint8_t key_stable = (debounce_cnt > 50) ? 0x80 : 0x00;
         static uint8_t prev_key_stable = 0;
 ​
         if(key_stable && !prev_key_stable)
        {
             press_cnt = 0;
             short_press_flag = 0;
        }
 ​
         if(key_stable)
        {
             press_cnt++;
 ​
             if(press_cnt >= LONG_PRESS_TRIGGER)
            {
                 short_press_flag = 1;
                 slow_cnt++;
                 if(slow_cnt >= CHANGE_DELAY)
                {
                     slow_cnt = 0;
 ​
                     if(dir == 1)
                    {
                         brightness++;
                         if(brightness >= BRIGHT_MAX)
                        {
                             brightness = BRIGHT_MAX;
                             dir = 0;
                        }
                    }
                     else
                    {
                         brightness--;
                         if(brightness <= BRIGHT_MIN)
                        {
                             brightness = BRIGHT_MIN;
                             dir = 1;
                        }
                    }
 ​
                     led_enable = (brightness > 0) ? 1 : 0;
                }
            }
        }
         else if(prev_key_stable)
        {
             if(short_press_flag == 0 && press_cnt > 0 && press_cnt < LONG_PRESS_TRIGGER)
            {
                 led_enable = !led_enable;
                 
                 if(led_enable)
                {
                     brightness = BRIGHT_MAX;
                }
                 else
                {
                     brightness = BRIGHT_MIN;
                     dir = 1;
                }
            }
 ​
             press_cnt = 0;
             slow_cnt = 0;
             short_press_flag = 0;
        }
         
         prev_key_stable = key_stable;
 ​
         if(led_enable)
        {
             for(uint32_t i=0; i<PWM_FULL_CYCLE; i++)
            {
                 if(i < brightness)
                {
                     LED1_Set();
                }
                 else
                {
                     LED1_Clear();
                }
            }
        }
         else
        {
             LED1_Clear();
        }
    }
 ​
     return EXIT_FAILURE;
 }

功能展示图及说明

初始状态:开发板上电,LED1 熄灭,亮度值为 0;

短按触摸:LED1 立即点亮为最亮状态;再次短按,LED1 熄灭,开关响应灵敏;

长按递增调光:长按触摸保持,LED 亮度从 0 平滑递增至 255(最亮);

长按递减调光:亮度到达最亮后继续长按,自动从 255 平滑递减至 0;

循环调光:持续长按,LED 重复「灭→最亮→灭」平滑循环,无闪烁、无跳变。

image.png

image.png

项目中遇到的难题及解决方法

难题 1:LED所接的如何输出PWM

配置TTC0中只有Channel0~3,但是在配置Pin这里是TCC0的通道5,不知道是啥原因

image.png

难题 2:GPIO 模拟 PWM 出现 LED 闪烁

  • 原因:PWM 频率过低(<50Hz),人眼感知到电平闪烁;亮度步长过大,调节跳变明显。
  • 解决方法:将 PWM 频率设为 100Hz,亮度调节步长设为 1%,缩短长按刷新间隔至 10ms,彻底消除闪烁。

难题 3:短按 / 长按误触发

  • 原因:无按键消抖,按键机械抖动导致检测错误;长按阈值设置不合理。
  • 解决方法:增加 10ms 软件消抖,长按阈值设为 500ms,通过静态变量记录按键状态,精准区分指令。

心得体会

通过本次基于 EV41C56A 开发板的 LED 调光项目,我对Microchip这个芯片的使用了有了比较基础的认知和开发经验

附件下载
Funpack5-2_code.zip
团队介绍
个人
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号