问答

汇集网友智慧,解决技术难题

21ic问答首页 - 9脚6位数码管如何驱动

AC 数码 数码管 电压 电流

9脚6位数码管如何驱动

liaochunlong2024-09-02
本帖最后由 tyw 于 2024-9-2 14:49 编辑

9脚6位数码管如何驱动,前三位显示电流,后三位显示电压,不知道如何写段码 00.jpg
回答 +关注 9
5623人浏览 8人回答问题 分享 举报
8 个回答
  • 本帖最后由 宏达工 于 2025-8-26 15:49 编辑


    // 引脚定义
    sbit LED1 = P3^4;  // LED1脚(位选信号)
    sbit LED2 = P3^5;  // LED2脚(位选信号)
    sbit LED3 = P3^6;  // LED3脚(位选信号)
    sbit LED4 = P3^7;  // LED4脚(位选信号)
    sbit LED5 = P1^5;  // LED5脚(位选信号)
    sbit LED6 = P1^6;  // LED6脚(位选信号)
    sbit LED7 = P1^7;  // LED7脚(位选信号)
    sbit LED8 = P5^4;  // 段选信号
    sbit LED9 = P3^3;  // 段选信号

    // 共阴数码管段码表 (0-9, A-F, 熄灭)
    // 格式: 位码[dp, g, f, e, d, c, b, a]
    unsigned char code SEG_TABLE[17] = {
        0x3F, // 0: 00111111
        0x06, // 1: 00000110
        0x5B, // 2: 01011011
        0x4F, // 3: 01001111
        0x66, // 4: 01100110
        0x6D, // 5: 01101101
        0x7D, // 6: 01111101
        0x07, // 7: 00000111
        0x7F, // 8: 01111111
        0x6F, // 9: 01101111
        0x77, // A: 01110111
        0x7C, // B: 01111100
        0x39, // C: 00111001
        0x5E, // D: 01011110
        0x79, // E: 01111001
        0x71, // F: 01110001
        0x00  // 熄灭
    };

    // ADC相关定义
    #define ADC_POWER   0x80    // ADC电源控制位
    #define ADC_FLAG    0x10    // ADC完成标志
    #define ADC_START   0x08    // ADC开始控制位

    // 函数声明
    void closeAllDigits();
    void delay_ms(unsigned int ms);
    void setSegments(unsigned char digit, unsigned char segCode);
    void displayDigit(unsigned char digit, unsigned char num, bit dot);
    void displayNumber(unsigned long num, unsigned char digits, unsigned char dotPos);
    void init();
    void InitADC();
    unsigned int ReadADC(unsigned char ch);
    unsigned int GetAverageADC(unsigned char ch, unsigned char times);
    float CalculateVoltage(unsigned int adcValue);
    float CalculateCurrent(unsigned int adcValue);
    void DisplayVoltage(float voltage);
    void DisplayCurrent(float current);

    // 关闭所有数码管
    void closeAllDigits() {
        // 所有公共端置高电平(共阴数码管,高电平关闭)
        LED1 = 1;  // com1 (dig1的公共端)
        LED2 = 1;  // com2 (dig2的公共端)
        LED3 = 1;  // com3 (dig3的公共端)
        LED4 = 1;  // com4 (dig4的公共端)
        LED5 = 1;  // com5 (dig5的公共端)
        LED6 = 1;  // com6 (dig6的公共端)
        LED7 = 1;  // com7 (dig7的公共端)
    }

    // 延时函数,用于数码管刷新
    void delay_ms(unsigned int ms) {
        unsigned int i, j;
        for(i = 0; i < ms; i++)
            for(j = 0; j < 120; j++);
    }

    // 短延时,用于ADC转换
    void delay_us(unsigned int us) {
        while(us--) {
            _nop_();_nop_();_nop_();_nop_();
            _nop_();_nop_();_nop_();_nop_();
        }
    }

    // 设置段码,根据不同数码管的引脚定义
    void setSegments(unsigned char digit, unsigned char segCode) {
        // 先关闭所有段码引脚
        LED1 = 0;
        LED2 = 0;
        LED3 = 0;
        LED4 = 0;
        LED5 = 0;
        LED6 = 0;
        LED7 = 0;
        LED8 = 0;
        LED9 = 0;
       
        // 根据不同数码管设置相应的段码
        switch(digit) {
            case 1:  // dig1
                LED2 = (segCode & 0x01) ? 1 : 0;  // a1 (bit0)
                LED3 = (segCode & 0x02) ? 1 : 0;  // b1 (bit1)
                LED4 = (segCode & 0x04) ? 1 : 0;  // c1 (bit2)
                LED5 = (segCode & 0x08) ? 1 : 0;  // d1 (bit3)
                LED6 = (segCode & 0x10) ? 1 : 0;  // e1 (bit4)
                LED7 = (segCode & 0x20) ? 1 : 0;  // f1 (bit5)
                LED8 = (segCode & 0x40) ? 1 : 0;  // g1 (bit6)
                LED9 = (segCode & 0x80) ? 1 : 0;  // dp1 (bit7)
                break;
                
            case 2:  // dig2
                LED1 = (segCode & 0x01) ? 1 : 0;  // a2 (bit0)
                LED3 = (segCode & 0x02) ? 1 : 0;  // b2 (bit1)
                LED4 = (segCode & 0x04) ? 1 : 0;  // c2 (bit2)
                LED5 = (segCode & 0x08) ? 1 : 0;  // d2 (bit3)
                LED6 = (segCode & 0x10) ? 1 : 0;  // e2 (bit4)
                LED7 = (segCode & 0x20) ? 1 : 0;  // f2 (bit5)
                LED8 = (segCode & 0x40) ? 1 : 0;  // g2 (bit6)
                LED9 = (segCode & 0x80) ? 1 : 0;  // dp2 (bit7)
                break;
                
            case 3:  // dig3
                LED1 = (segCode & 0x01) ? 1 : 0;  // a3 (bit0)
                LED2 = (segCode & 0x02) ? 1 : 0;  // b3 (bit1)
                LED4 = (segCode & 0x04) ? 1 : 0;  // c3 (bit2)
                LED5 = (segCode & 0x08) ? 1 : 0;  // d3 (bit3)
                LED6 = (segCode & 0x10) ? 1 : 0;  // e3 (bit4)
                LED7 = (segCode & 0x20) ? 1 : 0;  // f3 (bit5)
                LED8 = (segCode & 0x40) ? 1 : 0;  // g3 (bit6)
                LED9 = (segCode & 0x80) ? 1 : 0;  // dp3 (bit7)
                break;
                
            case 4:  // dig4
                LED1 = (segCode & 0x01) ? 1 : 0;  // a4 (bit0)
                LED2 = (segCode & 0x02) ? 1 : 0;  // b4 (bit1)
                LED3 = (segCode & 0x04) ? 1 : 0;  // c4 (bit2)
                LED5 = (segCode & 0x08) ? 1 : 0;  // d4 (bit3)
                LED6 = (segCode & 0x10) ? 1 : 0;  // e4 (bit4)
                LED7 = (segCode & 0x20) ? 1 : 0;  // f4 (bit5)
                LED8 = (segCode & 0x40) ? 1 : 0;  // g4 (bit6)
                LED9 = (segCode & 0x80) ? 1 : 0;  // dp4 (bit7)
                break;
                
            case 5:  // dig5
                LED1 = (segCode & 0x01) ? 1 : 0;  // a5 (bit0)
                LED2 = (segCode & 0x02) ? 1 : 0;  // b5 (bit1)
                LED3 = (segCode & 0x04) ? 1 : 0;  // c5 (bit2)
                LED4 = (segCode & 0x08) ? 1 : 0;  // d5 (bit3)
                LED6 = (segCode & 0x10) ? 1 : 0;  // e5 (bit4)
                LED7 = (segCode & 0x20) ? 1 : 0;  // f5 (bit5)
                LED8 = (segCode & 0x40) ? 1 : 0;  // g5 (bit6)
                LED9 = (segCode & 0x80) ? 1 : 0;  // dp5 (bit7)
                break;
                
            case 6:  // dig6
                LED1 = (segCode & 0x01) ? 1 : 0;  // a6 (bit0)
                LED2 = (segCode & 0x02) ? 1 : 0;  // b6 (bit1)
                LED3 = (segCode & 0x04) ? 1 : 0;  // c6 (bit2)
                LED4 = (segCode & 0x08) ? 1 : 0;  // d6 (bit3)
                LED5 = (segCode & 0x10) ? 1 : 0;  // e6 (bit4)
                LED7 = (segCode & 0x20) ? 1 : 0;  // f6 (bit5)
                LED8 = (segCode & 0x40) ? 1 : 0;  // g6 (bit6)
                LED9 = (segCode & 0x80) ? 1 : 0;  // dp6 (bit7)
                break;
                
            case 7:  // dig7
                LED1 = (segCode & 0x01) ? 1 : 0;  // a7 (bit0)
                LED2 = (segCode & 0x02) ? 1 : 0;  // b7 (bit1)
                break;
        }
    }

    // 显示单个数码管
    void displayDigit(unsigned char digit, unsigned char num, bit dot) {
        unsigned char segCode;
       
        // 关闭所有数码管,防止串扰
        closeAllDigits();
       
        // 获取段码并设置小数点
        segCode = SEG_TABLE[num];
        if(dot) segCode |= 0x80;  // 设置小数点
       
        // 设置段码
        setSegments(digit, segCode);
       
        // 打开对应的数码管公共端(共阴,低电平有效)
        switch(digit) {
            case 1: LED1 = 0; break;  // com1
            case 2: LED2 = 0; break;  // com2
            case 3: LED3 = 0; break;  // com3
            case 4: LED4 = 0; break;  // com4
            case 5: LED5 = 0; break;  // com5
            case 6: LED6 = 0; break;  // com6
            case 7: LED7 = 0; break;  // com7
        }
       
        // 短暂延时,保持显示
        delay_ms(1);
    }
  • 建议楼主先看看8位流水灯的程序  然后这个就明白了
  • 先选位再选段,扫描速率可以根据位数错开,毕竟前面的位数变化最慢。
  • 这种数码管是为了节省IO才这样设计的,驱动也不难,IO必须可以设置为推挽输出和高阻,假如用共阴扫描,则其中一个IO推挽输出低电平,其余IO要显示的就推挽输出高,不显示的就高阻。
    楼主的9脚最多可以驱动9个数码管(带小数点),6个数码管8脚就可以了。这种数码管曾经用的比较多,比如充电宝、无线话筒。
  • 这个端口复用的数码管比较点亮比较复杂点,不过原理还是一样的
  • 为啥数码管这么乱的 那你先把第一位点亮 然后第二位
  • 你这种数码管只能用单片机程序扫描控制。
  • 数码管就是通过循环扫描的方式显示的,如果条件可以最好用一个数码管驱动芯片,IO口控制闪烁不太好控制

您需要登录后才可以回复 登录 | 注册