STM32 矩阵式LED的实现方式与思路

*

一、写在前面
——以下内容皆为原创,转载请注明


电路如下图所示
这里写图片描述
一个4x3的矩阵式LED,行分别由GPIOB.6 GPIOB.5 GPIOB.4 GPIOB.3控制
列分别由GPIOB.9 GPIOB.8 GPIOB.7控制
需要达到达到显示效果:
1、全部点亮
2、点亮D2 D4 D6 D8 D10 D12
3、点亮D2 D8 D10 D12
4、点亮D4 D6 D10 D12
5、点亮D10
上面五种效果都需要当对应按键按下时,对应的LED熄灭,抬手后重新点亮
于是乎MODE2就有了7种效果
1、MODE2全亮
2、MODE2熄灭D2
3、MODE2熄灭D4
4、MODE2熄灭D6
5、MODE2熄灭D8
6、MODE2熄灭D10
7、MODE2熄灭D12
我将以MODE2 的显示效果来说明。
我当时首先想到的就是采用单点点亮的方式去刷新来达到显示效果;
对于MODE2来说需要6个步骤
点亮 D2 –>点亮D4–>点亮D6–>点亮D8–>点亮D10–>点亮D12;
测试出来的效果是能满足要求;但是问题 在于,系统需要做其他任务(典型性的裸奔前后台系统),就会导致始终都是最后一个显示的亮度很高—亮度不均匀;
最后确定,采用定时器中断去执行这个点亮LED的任务;这样就能解决亮度不均匀的问题;
在决定用定时器去做这个事情的时候,我就决定不再采用单个点亮的方式去实现,而是采用一次点亮一列,这样所有的效果都会只需要3次就能完成;
部分代码如下:

     switch(Pres)
    {
            case 0://MODE2 全亮
            {
                GPIOB->ODR &= 0xFFFFFC07;               
                GPIOB->ODR |= 0x000001A8;//点亮第一列

                GPIOB->ODR &= 0xFFFFFC07;   
                GPIOB->ODR |= 0x000002D0;//点亮第二列

                GPIOB->ODR &= 0xFFFFFC07;
                GPIOB->ODR |= 0x00000328;//点亮第三列

                GPIOB->ODR &= 0xFFFFFC07;//熄灭所有 
                break;
            }
}

这段代码是MODE2全部点亮的操作;但是这样的实现方式问题很大;
刚开始测试,似乎满足了我所有的需求;于是按照这种方式将后面其他MODE的代码全部写出;
测试代码的时候问题就来了,这个亮度太低了;
最开始我以为是频率不够,导致LED的实际占空比太低了;于是尝试提升占空比;结果发现并没有什么用;又尝试了降低限流电阻,也没有什么用
问题出在哪里呢?
想不到,就用示波器看,发现点亮LED的脉冲实在是小的可怜;
现在在回头看这段代码

     switch(Pres)
    {
            case 0://MODE2 全亮
            {
                GPIOB->ODR &= 0xFFFFFC07;               
                GPIOB->ODR |= 0x000001A8;//点亮第一列

                GPIOB->ODR &= 0xFFFFFC07;   
                GPIOB->ODR |= 0x000002D0;//点亮第二列

                GPIOB->ODR &= 0xFFFFFC07;
                GPIOB->ODR |= 0x00000328;//点亮第三列

                GPIOB->ODR &= 0xFFFFFC07;//熄灭所有 //问题就在这里
                break;
            }
}

每次点亮一列LED之后下一步就是把这一列熄灭;时间太短了;
那应该怎么延长?
我首先想到的就是延时,但是这种想法简直就是愚蠢之极;
因为是在中断服务函数中处理做这个事情,而且这个中断在系统中触发的频率很 高,这样就会导致主函数中的任务就会经常响应很慢;
最后,我决定中断服务函数中,每次只显示一列;显示下一列的时候才把上一列的状态清除,这样每一列的电平置位的时间就是一个中断周期,并且每一列都一样;
下面附上MODE2的全部代码

static void LED_Show_Two(uint8_t Pres,uint8_t Cnt)
{
    switch(Pres)
    {
            case 0://MODE2 全亮
            {
                GPIOB->ODR &= 0xFFFFFC07;               
                switch(Cnt)
                {
                    case 0:
                    {
                        GPIOB->ODR |= 0x000001A8;
                        break;
                    }
                    case 1:
                    {
                        GPIOB->ODR |= 0x000002D0;
                        break;
                    }
                    case 2:
                    {
                        GPIOB->ODR |= 0x00000328;
                        break;
                    }
                    default:break;
                }
                break;
            }
            case 2: //MODE3 2键按下
            {
                GPIOB->ODR &= 0xFFFFFC07;               
                switch(Cnt)
                {
                    case 0:
                    {
                        GPIOB->ODR |= 0x000001A8;
                        break;
                    }
                    case 1:
                    {
                        GPIOB->ODR |= 0x00000290;
                        break;
                    }
                    case 2:
                    {
                        GPIOB->ODR |= 0x00000328;
                        break;
                    }
                    default:break;
                }
                break;
            }
            case 4://MODE2 4键按下
            {
                GPIOB->ODR &= 0xFFFFFC07;               
                switch(Cnt)
                {
                    case 0:
                    {
                        GPIOB->ODR |= 0x00000188;
                        break;
                    }
                    case 1:
                    {
                        GPIOB->ODR |= 0x000002D0;
                        break;
                    }
                    case 2:
                    {
                        GPIOB->ODR |= 0x00000328;
                        break;
                    }
                    default:break;
                }
                break;
            }
            case 6://MODE2 6键按下
            {
                GPIOB->ODR &= 0xFFFFFC07;               
                switch(Cnt)
                {
                    case 0:
                    {
                        GPIOB->ODR |= 0x000001A8;
                        break;
                    }
                    case 1:
                    {
                        GPIOB->ODR |= 0x000002D0;
                        break;
                    }
                    case 2:
                    {
                        GPIOB->ODR |= 0x00000308;
                        break;
                    }
                    default:break;
                }
                break;
            }
            case 8://MODE2 8键按下
            {
                GPIOB->ODR &= 0xFFFFFC07;               
                switch(Cnt)
                {
                    case 0:
                    {
                        GPIOB->ODR |= 0x000001A8;
                        break;
                    }
                    case 1:
                    {
                        GPIOB->ODR |= 0x000002C0;
                        break;
                    }
                    case 2:
                    {
                        GPIOB->ODR |= 0x00000328;
                        break;
                    }
                    default:break;
                }
                break;
            }
            case 10:
            {
                GPIOB->ODR &= 0xFFFFFC07;               
                switch(Cnt)
                {
                    case 0:
                    {
                        GPIOB->ODR |= 0x000001A0;
                        break;
                    }
                    case 1:
                    {
                        GPIOB->ODR |= 0x000002D0;
                        break;
                    }
                    case 2:
                    {
                        GPIOB->ODR |= 0x00000328;
                    }
                    default:break;
                }
                break;
            }
            case 12:
            {
                GPIOB->ODR &= 0xFFFFFC07;               
                switch(Cnt)
                {
                    case 0:
                    {
                        GPIOB->ODR |= 0x000001A8;
                        break;
                    }
                    case 1:
                    {
                        GPIOB->ODR |= 0x000002D0;
                        break;
                    }
                    case 2:
                    {
                        GPIOB->ODR |= 0x00000320;
                        break;
                    }
                    default:break;
                }
                break;
            }
            default:break;
  }
}

到这里,我所需要的功能都实现了,但是有个问题,代码太长了;至于怎么优化,我还没找到方法
*

发布了13 篇原创文章 · 获赞 13 · 访问量 9947

猜你喜欢

转载自blog.csdn.net/qq_25920091/article/details/78753905
今日推荐