中颖SH79F9476 的LED驱动笔记

本文详细介绍了中颖SH79F9476单片机的LED驱动特性,包括使用RAM表的两种驱动模式,呼吸灯控制方法,以及如何通过COM控制LED显示。文章还着重讨论了解决鬼影现象的方法,通过调整中断处理和刷新策略优化了LED驱动程序。
摘要由CSDN通过智能技术生成

中颖SH79F9476 的LED驱动笔记

image-20240412150643793

我的理解:

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

image-20240411161120165

需要呼吸灯效果的,只能选择模式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);
}

消除鬼影后,最后程序的效果就是这样啦!

可留言发原理图~

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值