tpgf 发表于 2024-5-17 14:58

中颖SH79F9476 的LED驱动笔记

中颖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; // seg1~seg16
      pled++;                        // 将数组的内容按顺序填充到RAM2中,真正刷新SEG显示亮度duty的地方
    }

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



将当前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 = 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; // 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 = ComSegDutyBuf; //
    }

    _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啊
页: [1]
查看完整版本: 中颖SH79F9476 的LED驱动笔记