打印
[家电应用]

中颖SH79F9476 的LED驱动笔记

[复制链接]
598|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-5-17 14:58 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
中颖SH79F9476 的LED驱动笔记



我的理解:

就是运用该芯片内部的LED驱动器的RAM表,有2种不同的驱动方式。



需要呼吸灯效果的,只能选择模式1:单次扫描,使用RAM2 的表

通过软件选择当前要扫描的COM(单COM),启动扫描,该COM扫描结束后,表示该次扫描结束;COM扫描期间,

SEG01/SEG02中每个bit位控制一个SEG,当该bit位为0时,该SEG口状态由IO控制;当该bit位为1时,该SEG口输出恒流。

该次扫描结束后,LED驱动器对应的中断标志位COMIF位置1,LED停止扫描。

SEG的输出宽度有两种控制方式

方式1:SEG的输出周期宽度与COM的宽度一样(当COM_CON的BIT5=0时)

方式2:SEG的输出周期宽度由RAM2控制(当COM_CON的BIT5=1时)

COM输出结束中断处理函数中,设置:

    for (led_isr_seg = 0; led_isr_seg < 16; led_isr_seg++)
    {
        *pled = RcomDuty[led_isr_seg]; // seg1~seg16
        pled++;                        // 将数组的内容按顺序填充到RAM2中,真正刷新SEG显示亮度duty的地方
    }

    COM_CON |= 0x88; // GO
    for (led_isr_seg = 0; led_isr_seg < 16; led_isr_seg++)
    {                                                                    // 加载下一帧
        RcomDuty[led_isr_seg] = ComSegDutyBuf[led_isr_com][led_isr_seg]; //
    }



将当前COM口的16个SEG数据通过赋值刷新到RAM2的表中,实现硬件的LED刷新。

准备下一个COM的16个SEG数据。

在主循环中修改这个8*16个ComSegDutyBuf数组的内容即可。

出现鬼影啦!

猜想:可能是因为正反推的原因,导致会有给占空比赋值是0时候,产生“鬼影”。

因此需要调整刷新的程序结构。

调整后的部分代码如下:

void isr_LEDMC(void) interrupt 8
{

    unsigned char geWei = 0;
    unsigned char shiWei = 0;
    unsigned char baiWei = 0;
    _push_(INSCON);

    INSCON &= 0xBF;                   // 选择特殊功能寄存器页0
    p_seg_duty = R_ledDATA_RAM_ADDR2; // SEG1duty地址 赋值给指针变量
                                      //    COM_CON &= 0xB0;    //清除 COM 输出结束中断标志位
    COM_CON &= 0x38;                  // 清除 COM 输出结束中断标志位
    led_isr_com++;

    //-----------------------------------------------------------------------------------------
    if (100 != battery_level) // 处理电量显示
    {
        geWei = battery_level % 10;
        shiWei = battery_level / 10;
        baiWei = 0;
    }
    else
    {
        geWei = 0;
        shiWei = 0;
        baiWei = 1;
    }
    //-----------------------------------------------------------------------------------------
    switch (led_isr_com)
    {
    case 1:           // COM1
#if (LEDCOMIO & 0x01) // 保证条件是1
        COM_CON |= 0x00;
        SEG01 = 0; // 选择 SEG1-8
        SEG02 = 0; // 选择 SEG9-16

        SEG01 = 0xFF;         // 选择 SEG1-8
        SEG02 = 0xFF;         // 选择 SEG9-16
        duan(0, shiWei, 250); // com1 显示"8"
        break;
#else
        led_isr_com++;
#endif
    case 2: // COM2
#if (LEDCOMIO & 0x02)
        COM_CON |= 0x01;
        SEG01 = 0; // 选择 SEG1-8
        SEG02 = 0; // 选择 SEG9-16

        SEG01 = 0xFF;        // 选择 SEG1-8
        SEG02 = 0xFF;        // 选择 SEG9-16
        duan(1, geWei, 250); // com2 显示"8"
        break;
#else
        led_isr_com++;
#endif
    case 3: // COM3
#if (LEDCOMIO & 0x04)
        COM_CON |= 0x02;
        SEG01 = 0; // 选择 SEG1-8
        SEG02 = 0; // 选择 SEG9-16

        SEG01 = 0xFF;                // 选择 SEG1-8
        SEG02 = 0xFF;                // 选择 SEG9-16
        scanOne(baiWei, 250);        // com3 显示"1"
        scanLowPower(lowpower);      // com3 显示低电量灯
        ComSegDutyBuf[2][14] = 0xFF; // 显示 "%"
        break;
#else
        led_isr_com++;
#endif
    case 4: // COM4
#if (LEDCOMIO & 0x08)
        COM_CON |= 0x03;
        SEG01 = 0; // 选择 SEG1-8
        SEG02 = 0; // 选择 SEG9-16

        SEG01 = 0xFF; // 选择 SEG1-8
        SEG02 = 0xFF; // 选择 SEG9-16
        scanD1(flag_d1);
        scanD2(flag_d2);
        scanD3(flag_d3);
        scanD4(flag_d4);
        scanD5(flag_d5);
        scanD6(flag_d6);
        scanD7(flag_d7);
        scanD8(flag_d8);
        break;
#else
        led_isr_com++;
#endif
    case 5: // COM5
#if (LEDCOMIO & 0x10)
        COM_CON |= 0x04;
        SEG01 = 0; // 选择 SEG1-8
        SEG02 = 0; // 选择 SEG9-16

        SEG01 = 0xFF; // 选择 SEG1-8
        SEG02 = 0xFF; // 选择 SEG9-16
        scanD11(flag_d11);
        scanD12(flag_d12);
        scanD14(flag_d14);
        scanD18(flag_d18);
        break;
#else
        led_isr_com++;
#endif
    case 6: // COM6
#if (LEDCOMIO & 0x20)
        COM_CON |= 0x05;
        SEG01 = 0; // 选择 SEG1-8
        SEG02 = 0; // 选择 SEG9-16

        SEG01 = 0xFF; // 选择 SEG1-8
        SEG02 = 0xFF; // 选择 SEG9-16
        scanD19(flag_d19);
        scanD21(flag_d21);
        scanD22(flag_d22);
        scanD23(flag_d23);
        break;
#else
        led_isr_com++;
#endif
    case 7: // COM7
#if (LEDCOMIO & 0x40)
        COM_CON |= 0x06;
        SEG01 = 0; // 选择 SEG1-8
        SEG02 = 0; // 选择 SEG9-16

        SEG01 = 0xFF; // 选择 SEG1-8
        SEG02 = 0xFF; // 选择 SEG9-16
        scanD24(flag_d24);
        scanD25(flag_d25);
        scanD69(flag_d69);
        scanD70(flag_d70);
        break;
#else
        led_isr_com++;
#endif
    case 8: // COM8
#if (LEDCOMIO & 0x80)
        COM_CON |= 0x07;
        SEG01 = 0; // 选择 SEG1-8
        SEG02 = 0; // 选择 SEG9-16

        SEG01 = 0xFF; // 选择 SEG1-8
        SEG02 = 0xFF; // 选择 SEG9-16
#endif
        led_isr_com = 0;
        break;
    }

    for (led_isr_seg = 0; led_isr_seg < 16; led_isr_seg++)
    {
        *p_seg_duty = SegDuty[led_isr_seg]; // seg1~seg16
        p_seg_duty++;                       // 将数组的内容按顺序填充到RAM2中,真正刷新SEG显示亮度duty的地方
    }

    COM_CON |= 0x88; // GO
    for (led_isr_seg = 0; led_isr_seg < 16; led_isr_seg++)
    {                                                                   // 加载下一帧
        SegDuty[led_isr_seg] = ComSegDutyBuf[led_isr_com][led_isr_seg]; //
    }

    _pop_(INSCON);
}



消除鬼影后,最后程序的效果就是这样啦!(视频链接)
https://www.bilibili.com/video/BV1Gi421f7w8?t=5.7

可留言发原理图~


中颖单片机驱动洗地机LED面板
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/zhao_zilong/article/details/137684662

使用特权

评论回复
沙发
亚瑟| | 2024-5-24 22:00 | 只看该作者
最多驱动多少个led啊

使用特权

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

本版积分规则

1433

主题

14211

帖子

8

粉丝