合泰单片机 | HT66F3195 | 个人库开发过程 | 【7】GPIO - 驱动非矩阵多个LED

LED驱动方式

LED驱动方式目前接触的就几个,最基础的两个灌电流和源电流驱动,然后是矩阵LED,数码管其实也算是矩阵的一种。
我之前一直在想一个问题,有没有一种方法可以在一个地方统一管理这些IO引脚呢?于是就有了之前GPIO口里面预留的三个函数,可以用一个for循环同时控制刷新多个灯,适用性可能不是很强,只是突然想到的一个东西不想浪费掉这些灵感,记录下来说不定后续有更好的方法优化一下。

流水灯驱动

假设现在板子上有3个灯,或者不用假设🤓之前设计的这个开发板就是预留了6个LED,其中3个是高电平驱动另外3个是低电平驱动,没有内置电路,通过引出排针,可以用任意IO口接到这上面来驱动LED。
我要实现流水灯的话,每次只亮1颗LED,从左到右,到了尽头再换一个方向继续,循环。
可以随便挑6个GPIO引脚:(先提前说好,如果接的仿真芯片,非常不推荐接PA0和PA2🤒如果PA0和PA2有变动的话直接中断仿真的)

  1. PA1
  2. PB2
  3. PB5
  4. PC3
  5. PA6
  6. PB4

前面三个接高电平驱动的LED,后面三个接低电平驱动的LED。

对应的任务结构体:

typedef struct
{
    unsigned char Status;
}LED_Task;

目前也没有特殊的需求,先用一个变量记录当前灯状态这种。合泰的编译器支持bit变量的,但是不支持把bit变量放到结构体里面。
如果后面有心情的话,可以做一个流水灯带拖尾的效果,就是相当于把前面讲的那个时基模拟PWM拿过来改一下。

还有一个,同样规格的灯需要在头文件记录一下数目,后面多个地方会用到:

#define Normal_LED_Num  6

LED的GPIO映射关系

先定义一个常量的二维数组,这样子就可以很快能查到并且修改对应的映射关系。

#define LED_1         	0
#define LED_2       	1
#define LED_3        	2
#define LED_4			3
#define LED_5			4
#define LED_6			5
const unsigned char LED_Map[Normal_LED_Num][3] = 
{
    {LED_1,     GPIOA,      Pin1,},
    {LED_2,     GPIOB,      Pin2,},
    {LED_3,     GPIOB,      Pin5,},
    {LED_4,     GPIOC,      Pin3,},
    {LED_5,     GPIOA,      Pin6,},
    {LED_6,     GPIOB,      Pin4,},
};

其实仔细一看会发现,这个二维数组的第0个参数其实可有可无,加上只是为了方便对电路图。

初始化

LED_Task LED[Normal_LED_Num];
unsigned char LED_Move_Status;
bit LED_Director;

void LED_Init()
{
    unsigned char i;
    for(i = 0; i < Normal_LED_Num; i++)
    {
        GPIO_Map_Control(LED_Map[i][GPIO_Map_Group], LED_Map[i][GPIO_Map_Pin], IO_Output);
        if(i < 3)
        	GPIO_Map_Write(LED_Map[i][GPIO_Map_Group], LED_Map[i][GPIO_Map_Pin], IO_Low);
        else
        	GPIO_Map_Write(LED_Map[i][GPIO_Map_Group], LED_Map[i][GPIO_Map_Pin], IO_High);
    }
    LED_Move_Status = 0x01;
    LED_Director = 1;
}

灯状态刷新

这个灯效对速度没有要求,所以可以放置在下面位置刷新之后,马上跟一个灯状态刷新。

void LED_Display()
{
    unsigned char i;
    unsigned char index = 0x01;

    for(i = 0; i < Normal_LED_Num; i++)
    {
        LED[i].Status = !!(LED_Move_Status & index);
        if(LED[i].Status != 0)
        {
            if(i < 3)
            {
                GPIO_Map_Write(LED_Map[i][GPIO_Map_Group], LED_Map[i][GPIO_Map_Pin], IO_High);
            }
            else
            {
                GPIO_Map_Write(LED_Map[i][GPIO_Map_Group], LED_Map[i][GPIO_Map_Pin], IO_Low);
            }
        }
        else
        {
            if(i < 3)
            {
                GPIO_Map_Write(LED_Map[i][GPIO_Map_Group], LED_Map[i][GPIO_Map_Pin], IO_Low);
            }
            else
            {
                GPIO_Map_Write(LED_Map[i][GPIO_Map_Group], LED_Map[i][GPIO_Map_Pin], IO_High);
            }
        }
        index <<= 1;
    }
}

位置刷新

这个可以ms~s级别来刷新这个状态。主要是操作一个变量,到了边界之后就换一个方向。

void LED_Dir_Update()
{
    if(LED_Director == 1)   /* 右 */
    {
        if(LED_Move_Status == 0x01)
        {
            LED_Director = 0;
            LED_Move_Status <<= 1;
        }
        else
        {
            LED_Move_Status >>= 1;
        }
    }
    else                    /* 左 */
    {
        if(LED_Move_Status == 0x20)
        {
            LED_Director = 1;
            LED_Move_Status >>= 1;
        }
        else
        {
            LED_Move_Status <<= 1;
        }
    }

    if(LED_Move_Status > 0x20)
        LED_Move_Status = 0x01;
	
    LED_Display();
}

效果

暂时不知道怎么上传😂

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>