数码管:3位6脚的数码管分析和编码

▪ 基本简介

一个1位数码管共有8段:ABCDEFG+小数点,如下图:

按照我们常规的设计方案一个 IO 口控制一个段,一个1位数码管那么就需要8个IO。当然我们也可以使用扩展 IO 芯片(例如 74HC164、74HC595),那么这种方案就占用单片机2~3个IO和一个扩展IO芯片。

 

现在我们需要控制一个3位的数码管:

  • 采用IO口直控:那么需要单片机 IO 口24个
  • 采用扩展 IO 芯片控制:那么需要单片机 IO 口 2~3 个

 

但是市面上有些 3 位的数码管只有 6 个接口,如下图:

 

这种元件就不是我们常规的控制方法了,这种是基于 查理复用算法 封装的数码管,只需要 6 个IO就能控制 3位数码管(3*8 个LED灯)。所以在使用这个元件时,你需要先了解查理复用算法,具体请参考我的《复用 IO 口:查理复用算法(Charlieplexing)》文章,或者直接百度搜索查看:查理复用算法(Charlieplexing)。

 

 

▪ 原理分析

不同厂家对于3位6脚的数码管可能设计不同的电路和针脚定义,具体咨询购买的厂家或其数据手册。这里我们取其中一种作为例子讲解,其数据手册图如下:

 

根据上面的数据手册,我们画出其对应的原理图,如下:

如上图所示,同时基于查理复用算法,我们可以分析出:

  • 数码管2脚高电平,3脚低电平,其余脚高阻态;那么 1A 会被点亮(Dig.1 数码管的第一个二极管灯亮)
  • 数码管1脚高电平,4脚低电平,其余脚高阻态;那么 DP2 会被点亮(Dig.2 数码管的小数点二极管灯亮)
  • .....

 

 

▪ 实现代码

以上代码基于 STM8 库函数:

 

/* -------------------------------------------------- */
// ● 全局变量
/* -------------------------------------------------- */

/**
 * 数码管基础变量
 */

// 数字和数码管段映射表
// 数组下标即为数字(0~9),数组的值即为数码管8个段的状态值(ABCDEFG+DP 八个段用采用一个字节表示)
// 例如要显示数字 0,那么需要点亮 ABCDEF 这七个段,那么对应的就是 1111110+0 = 0xFC
short GV_DigitronNumsMapSegs[10] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xE6};


/* -------------------------------------------------- */
// ● 函数主体
/* -------------------------------------------------- */

/**
 * 取数码管针脚编号对应芯片上的针脚号
 *
 * @param short number  数码管针脚编号
 * @return GPIO_Pin_TypeDef  无效参数时返回 GPIO_PIN_ALL
 */
GPIO_Pin_TypeDef DIGITRON_GetPin( short number )
{
    // 适配针脚
    if( number == 1 ) return GPIO_PIN_1;
    if( number == 2 ) return GPIO_PIN_3;
    if( number == 3 ) return GPIO_PIN_5;
    if( number == 4 ) return GPIO_PIN_0;
    if( number == 5 ) return GPIO_PIN_2;
    if( number == 6 ) return GPIO_PIN_7;

    // 无效返回
    return GPIO_PIN_ALL;
}

/**
 * 获取数码管针脚编号对应芯片上的端口号
 *
 * @param short number  数码管针脚编号
 * @return GPIO_TypeDef*  无效参数时返回 0
 */
GPIO_TypeDef* DIGITRON_GetPort( short number )
{
    // 适配端口
    if( number == 1 ) return GPIOA;
    if( number == 2 ) return GPIOA;
    if( number == 3 ) return GPIOA;
    if( number == 4 ) return GPIOH;
    if( number == 5 ) return GPIOH;
    if( number == 6 ) return GPIOF;

    // 无效返回
    return (GPIO_TypeDef*)0x0000;
}

/**
 * 显示数码管重置
 */
void DIGITRON_ShowReset()
{
    // 初始化
    int num;
    
    // 全部拉低电平
    // 必须拉低,不然会有拖影
    for( num = 1; num <= 6; num++ ){
        GPIO_WriteLow(DIGITRON_GetPort(num), DIGITRON_GetPin(num));
    }
    
    // 全部初始化为高阻态
    for( num = 1; num <= 6; num++ ){
        GPIO_Init(DIGITRON_GetPort(num), DIGITRON_GetPin(num), GPIO_MODE_OUT_OD_LOW_SLOW);
        GPIO_DeInit(DIGITRON_GetPort(num));
    }
}

/**
 * 显示数码管的段
 *
 * @param short unit  数码管位号(即第几个数码管)
 * @param char  seg   数码管对应 A~H 二极管(8段+小数点)
 */
void DIGITRON_ShowUnitSeg( short unit, char seg )
{
    if( unit == 1 ){
        if( seg == 'A' ) DIGITRON_ShowUnitSegCore(3,2);
        if( seg == 'B' ) DIGITRON_ShowUnitSegCore(4,2);
        if( seg == 'C' ) DIGITRON_ShowUnitSegCore(2,5);
        if( seg == 'D' ) DIGITRON_ShowUnitSegCore(6,2);
        if( seg == 'E' ) DIGITRON_ShowUnitSegCore(5,2);
        if( seg == 'F' ) DIGITRON_ShowUnitSegCore(2,3);
        if( seg == 'G' ) DIGITRON_ShowUnitSegCore(2,4);
    }

    if( unit == 2 ){
        if( seg == 'A' ) DIGITRON_ShowUnitSegCore(4,5);      
        if( seg == 'B' ) DIGITRON_ShowUnitSegCore(5,3);
        if( seg == 'C' ) DIGITRON_ShowUnitSegCore(5,4);
        if( seg == 'D' ) DIGITRON_ShowUnitSegCore(4,3);
        if( seg == 'E' ) DIGITRON_ShowUnitSegCore(3,6);
        if( seg == 'F' ) DIGITRON_ShowUnitSegCore(3,4);
        if( seg == 'G' ) DIGITRON_ShowUnitSegCore(3,5);
        if( seg == 'H' ) DIGITRON_ShowUnitSegCore(1,4);  // 数据手册中的 DP2
    }
    

    if( unit == 3 ){
        if( seg == 'A' ) DIGITRON_ShowUnitSegCore(6,1);      
        if( seg == 'B' ) DIGITRON_ShowUnitSegCore(6,3);
        if( seg == 'C' ) DIGITRON_ShowUnitSegCore(6,5);
        if( seg == 'D' ) DIGITRON_ShowUnitSegCore(4,6);
        if( seg == 'E' ) DIGITRON_ShowUnitSegCore(6,4);
        if( seg == 'F' ) DIGITRON_ShowUnitSegCore(5,6);
        if( seg == 'G' ) DIGITRON_ShowUnitSegCore(5,1);
    }
}

/**
 * 显示数码管的段 - 核心(设置针脚)
 * 该函数主要设置针脚的高低电平,以便使数码管的段显示
 *
 * @param short highPinNum  数码管针脚编号(设置为高电平的针脚)
 * @param short lowPinNum   数码管针脚编号(设置为低电平的针脚)
 */
void DIGITRON_ShowUnitSegCore( short highPinNum, short lowPinNum )
{
    // 重置
    DIGITRON_ShowReset();
    
    // 初始化为推挽输出
    GPIO_Init(DIGITRON_GetPort(lowPinNum), DIGITRON_GetPin(lowPinNum), GPIO_MODE_OUT_PP_LOW_SLOW);
    GPIO_Init(DIGITRON_GetPort(highPinNum), DIGITRON_GetPin(highPinNum), GPIO_MODE_OUT_PP_LOW_SLOW);
    
    // 设置高低电平
    GPIO_WriteLow(DIGITRON_GetPort(lowPinNum), DIGITRON_GetPin(lowPinNum)); 
    GPIO_WriteHigh(DIGITRON_GetPort(highPinNum), DIGITRON_GetPin(highPinNum)); 
}

/**
 * 显示数码管值(单管的值)
 *
 * @param short unit  数码管位号(即第几个数码管)
 * @param short num   0-9 数字
 * @param short dot   小数点
 */
void DIGITRON_ShowUnitNum( short unit, short number, short dot )
{
    // 初始化
    short numSegs = GV_DigitronNumsMapSegs[number];

    // 显示小数点
    if( dot > 0 ) DIGITRON_ShowUnitSeg(unit, 'H');
    
    // 显示数字
    if( (numSegs&0x80) == 0x80 ) DIGITRON_ShowUnitSeg(unit, 'A');  // & 1000 0000
    if( (numSegs&0x40) == 0x40 ) DIGITRON_ShowUnitSeg(unit, 'B');  // & 0100 0000
    if( (numSegs&0x20) == 0x20 ) DIGITRON_ShowUnitSeg(unit, 'C');  // & 0010 0000
    if( (numSegs&0x10) == 0x10 ) DIGITRON_ShowUnitSeg(unit, 'D');  // & 0001 0000
    if( (numSegs&0x08) == 0x08 ) DIGITRON_ShowUnitSeg(unit, 'E');  // & 0000 1000
    if( (numSegs&0x04) == 0x04 ) DIGITRON_ShowUnitSeg(unit, 'F');  // & 0000 0100
    if( (numSegs&0x02) == 0x02 ) DIGITRON_ShowUnitSeg(unit, 'G');  // & 0000 0010
}

/**
 * 显示数码管值
 *
 * @param float numval  要显示的数值
 */
void DIGITRON_Show( float numval )
{
    // 初始化
    float num;

    // 数字范围:0~99
    if( numval >= 0 && numval <= 99 ){
        num = numval/10;
        DIGITRON_ShowUnitNum(1, (int)num, 0);
        
        num = (int)numval%10;
        DIGITRON_ShowUnitNum(2, (int)num, 1);
        
        num = (int)(numval*10)%10;
        DIGITRON_ShowUnitNum(3, (int)num, 0);
    }
    
    // 数字范围:其他
    else{
        DIGITRON_ShowUnitNum(1, 9, 0);
        DIGITRON_ShowUnitNum(2, 9, 0);
        DIGITRON_ShowUnitNum(3, 9, 0);
    }
}

 

 

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值