3位6脚数码管的单片机例程

最近拿到了,只要用6个脚就能驱动

具体来说,原理是,两个脚一个脚为正,一个脚为负,就能点亮一段数码管。其他脚保持关闭状态

这样理论上可以实现6x5=30种点亮方式。3位数码管每位8个管脚加上一个小数点,刚好是27个灯

一次点亮一个灯,然后通过循环里一直切换,实现完整的显示
这里给一个数据手册的示意图

不过具体的引脚排列每个厂家都不一样,可以用万用表测出来。用红笔和黑笔接两个脚,某个灯管就亮了

管脚命名参考:

显示效果:

例程

使用方法:

c 复制代码
#include "Display_seg.h"
int main()
{
    SEG_Init();// 初始化引脚和变量
    while(1)
    {
        SEG_Update();// 刷新显示
      
        SEG_Display_Num(DIGIT_1, 1); // 第一位显示1
        SEG_Display_Num(DIGIT_2, 2);
        SEG_Display_Num(DIGIT_3, 3);      
    }
}

适配方法

注意每个单片机的函数不一样

#include "sc.h"换成自己单片机的头文件
#define SEG1_PIN RB6 // 引脚1: PB6 ...

引脚改为自己的引脚代码
#define SEG1_INPUT() TRISB6 = 1 ...

引脚方向改为自己的引脚方向设置函数

灯序不一样的还要改一下这里的排序
static const SegMap seg_map[] = {
{2, 3, SEG_A, DIGIT_1}, ...

**{2,3...**表示电流方向是2->3时,亮第一个管脚

代码

Display_seg.h

c 复制代码
#ifndef __SEG_DISPLAY_H
#define __SEG_DISPLAY_H

#include "sc.h"

//---------------------------------
// 用户自定义 数码管引脚
//---------------------------------

// 引脚定义(根据您的接线)
#define SEG1_PIN RB6 // 引脚1: PB6
#define SEG2_PIN RB5 // 引脚2: PB5
#define SEG3_PIN RB4 // 引脚3: PB4
#define SEG4_PIN RA3 // 引脚4: PA3
#define SEG5_PIN RA4 // 引脚5: PA4
#define SEG6_PIN RA5 // 引脚6: PA5

// 引脚方向
#define SEG1_INPUT()  TRISB6 = 1
#define SEG2_INPUT()  TRISB5 = 1
#define SEG3_INPUT()  TRISB4 = 1
#define SEG4_INPUT()  TRISA3 = 1
#define SEG5_INPUT()  TRISA4 = 1
#define SEG6_INPUT()  TRISA5 = 1
#define SEG1_OUTPUT() TRISB6 = 0
#define SEG2_OUTPUT() TRISB5 = 0
#define SEG3_OUTPUT() TRISB4 = 0
#define SEG4_OUTPUT() TRISA3 = 0
#define SEG5_OUTPUT() TRISA4 = 0
#define SEG6_OUTPUT() TRISA5 = 0

//---------------------------------

// 函数声明

void SEG_Init(void);    // 初始化数码管
void SEG_Clear(void);   // 清空显示

// 显示一位数字 
// 变量:(数码管,数字)
void SEG_Display_Num(unsigned char digit, unsigned char num);               
// 显示一个小数点
void SEG_Display_DP(unsigned char digit, unsigned char state);                     

// 刷新屏幕(需要在循环调用!!!重要)
void SEG_Update(void);   

// 使用示例:
/*
int main()
{
    SEG_Init();
    while(1)
    {
        SEG_Update();// 刷新显示
      
        SEG_Display_Num(DIGIT_1, 1); // 第一位显示1
        SEG_Display_Num(DIGIT_2, 2);
        SEG_Display_Num(DIGIT_3, 3);      
    }
}
*/


// 数码管编号
#define DIGIT_1 0
#define DIGIT_2 1
#define DIGIT_3 2

// 段码定义 (dp,g,f,e,d,c,b,a)
#define SEG_A 0x01
#define SEG_B 0x02
#define SEG_C 0x04
#define SEG_D 0x08
#define SEG_E 0x10
#define SEG_F 0x20
#define SEG_G 0x40
#define SEG_DP 0x80

// 数码管字段(A到G)
//   AAAAA
//  F     B
//  F     B
//   GGGGG
//  E     C
//  E     C
//   DDDDD  DP
//
//  数字0-9的字库
const unsigned char seg_code[] = {
    SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F,         // 0
    SEG_B | SEG_C,                                         // 1
    SEG_A | SEG_B | SEG_G | SEG_E | SEG_D,                 // 2
    SEG_A | SEG_B | SEG_G | SEG_C | SEG_D,                 // 3
    SEG_F | SEG_G | SEG_B | SEG_C,                         // 4
    SEG_A | SEG_F | SEG_G | SEG_C | SEG_D,                 // 5
    SEG_A | SEG_F | SEG_G | SEG_E | SEG_C | SEG_D,         // 6
    SEG_A | SEG_B | SEG_C,                                 // 7
    SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G, // 8
    SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G,         // 9

    SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // A   [10]
    SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,         // b   [11]
    SEG_A | SEG_D | SEG_E | SEG_F,                 // C   [12]
    SEG_B | SEG_C | SEG_D | SEG_E | SEG_G,         // d   [13]
    SEG_A | SEG_D | SEG_E | SEG_F | SEG_G,         // E   [14]
    SEG_A | SEG_E | SEG_F | SEG_G,                 // F   [15]
    SEG_B | SEG_C | SEG_E | SEG_F | SEG_G,         // H   [16]
    SEG_D | SEG_E | SEG_F,                         // L   [17]
    SEG_A | SEG_B | SEG_E | SEG_F | SEG_G,         // P   [18]
    SEG_E | SEG_G,                                 // r   [19]
    SEG_G                                          // -   [20]
};
#define SEG_CODE_SIZE (sizeof(seg_code) / sizeof(unsigned char))

#endif

Display_seg.c

c 复制代码
#include "Display_seg.h"
#include <stdint.h>

// 显示缓冲区(3位数码管)
static unsigned char seg_buffer[3] = {0, 0, 0};

// 当前扫描的数码管
static unsigned char current_digit = 0;

// 引脚配置表
// 格式: {阳极引脚, 阴极引脚, 段码位}
// 需要根据实际数码管内部连接关系填写
typedef struct
{
    unsigned char anode;   // 高电平引脚 (1-6)
    unsigned char cathode; // 低电平引脚 (1-6)
    unsigned char segment; // 段码
    unsigned char digit;   // 数码管位 (0-2)
} SegMap;

// 这里需要根据实际接线测试并修改
// 每个LED由两个引脚控制:一个阳极,一个阴极
static const SegMap seg_map[] = {
    // 第1位数码管
    {2, 3, SEG_A, DIGIT_1},  // A1: PB6->PB5
    {2, 4, SEG_B, DIGIT_1},  // B1: PB5->PB4
    {5, 2, SEG_C, DIGIT_1},  // C1: PB4->PA3
    {2, 6, SEG_D, DIGIT_1},  // D1: PA3->PA4
    {2, 5, SEG_E, DIGIT_1},  // E1: PA4->PA5
    {3, 2, SEG_F, DIGIT_1},  // F1: PA5->PB6
    {4, 2, SEG_G, DIGIT_1},  // G1: PB6->PB4
    {2, 1, SEG_DP, DIGIT_1}, // DP1: PB5->PA3

    // 第2位数码管
    {5, 4, SEG_A, DIGIT_2},  // A2: PB4->PA4
    {3, 5, SEG_B, DIGIT_2},  // B2: PA3->PA5
    {4, 5, SEG_C, DIGIT_2},  // C2: PA4->PB6
    {3, 4, SEG_D, DIGIT_2},  // D2: PA5->PB5
    {6, 3, SEG_E, DIGIT_2},  // E2: PB6->PA3
    {4, 3, SEG_F, DIGIT_2},  // F2: PB5->PA4
    {5, 3, SEG_G, DIGIT_2},  // G2: PB4->PA5
    {3, 1, SEG_DP, DIGIT_2}, // DP2: PA3->PB6

    // 第3位数码管
    {1, 6, SEG_A, DIGIT_3},  // A3: PA4->PB5
    {3, 6, SEG_B, DIGIT_3},  // B3: PA5->PB4
    {5, 6, SEG_C, DIGIT_3},  // C3: PB6->PA4
    {6, 4, SEG_D, DIGIT_3},  // D3: PB5->PA5
    {4, 6, SEG_E, DIGIT_3},  // E3: PB4->PB6
    {6, 5, SEG_F, DIGIT_3},  // F3: PA3->PB5
    {1, 5, SEG_G, DIGIT_3},  // G3: PA4->PB4
    {6, 4, SEG_DP, DIGIT_3}, // DP3: PA5->PA3
};
#define SEG_MAP_SIZE (sizeof(seg_map) / sizeof(SegMap))

// 初始化数码管
void SEG_Init(void)
{
    // 初始化所有引脚为输入高阻态
    TRISA |= 0b00111000; // RB4,RB5,RB6 -> 输入
    WPUA |= 0b00111000;  // 上拉电阻

    TRISB |= 0b01110000; // RB4,RB5,RB6 -> 输入
    WPUB |= 0b01110000;  // 上拉电阻
    
    // 初始化显示缓冲区
    seg_buffer[0] = 0;
    seg_buffer[1] = 0;
    seg_buffer[2] = 0;

    current_digit = 0;
}

// 清除显示
void SEG_Clear(void)
{
    // 初始化所有引脚为输入高阻态
    TRISA |= 0b00111000; // RB4,RB5,RB6 -> 输入
    WPUA |= 0b00111000;  // 上拉电阻

    TRISB |= 0b01110000; // RB4,RB5,RB6 -> 输入
    WPUB |= 0b01110000;  // 上拉电阻
}

// 操控6个引脚状态 (0:低电平, 1:高电平, 其他:高阻态)
static void set_pin(unsigned char pin, unsigned char state)
{
    switch (pin)
    {
    case 1:
        if (state == 1)
        {
            SEG1_OUTPUT();
            SEG1_PIN = 1;
        }
        else if (state == 0)
        {
            SEG1_OUTPUT();
            SEG1_PIN = 0;
        }
        else
        { // 高阻态
            SEG1_INPUT();
            SEG1_PIN = 0;
        }
        break;
    case 2:
        if (state == 1)
        {
            SEG2_OUTPUT();
            SEG2_PIN = 1;
        }
        else if (state == 0)
        {
            SEG2_OUTPUT();
            SEG2_PIN = 0;
        }
        else
        {
            SEG2_INPUT();
            SEG2_PIN = 0;
        }
        break;
    case 3:
        if (state == 1)
        {
            SEG3_OUTPUT();
            SEG3_PIN = 1;
        }
        else if (state == 0)
        {
            SEG3_OUTPUT();
            SEG3_PIN = 0;
        }
        else
        {
            SEG3_INPUT();
            SEG3_PIN = 0;
        }
        break;
    case 4:
        if (state == 1)
        {
            SEG4_OUTPUT();
            SEG4_PIN = 1;
        }
        else if (state == 0)
        {
            SEG4_OUTPUT();
            SEG4_PIN = 0;
        }
        else
        {
            SEG4_INPUT();
            SEG4_PIN = 0;
        }
        break;
    case 5:
        if (state == 1)
        {
            SEG5_OUTPUT();
            SEG5_PIN = 1;
        }
        else if (state == 0)
        {
            SEG5_OUTPUT();
            SEG5_PIN = 0;
        }
        else
        {
            SEG5_INPUT();
            SEG5_PIN = 0;
        }
        break;
    case 6:
        if (state == 1)
        {
            SEG6_OUTPUT();
            SEG6_PIN = 1;
        }
        else if (state == 0)
        {
            SEG6_OUTPUT();
            SEG6_PIN = 0;
        }
        else
        {
            SEG6_INPUT();
            SEG6_PIN = 0;
        }
        break;
    }
}


// 显示一位数字
void SEG_Display_Num(unsigned char digit, unsigned char num)
{
    if (digit < 3 && num < 10)
    {
        seg_buffer[digit] = seg_code[num];
    }
}

// 显示一个小数点
void SEG_Display_DP(unsigned char digit, unsigned char state)
{
    if (digit < 3)
    {
        if (state == 1)
        {
            seg_buffer[digit] |= SEG_DP;
        }
        else
        {
            seg_buffer[digit] &= ~SEG_DP;
        }
    }
}

// 更新显示(需要在循环调用才能显示 !!!)
void SEG_Update(void)
{
    // 一次更新一位数码管
    static unsigned char seg_num = 0;

    const SegMap *map = &seg_map[seg_num];
    // 检查该段是否需要点亮
    if (seg_buffer[map->digit] & map->segment)
    {
        // 点亮这个LED
        SEG_Clear();
        set_pin(map->anode, 1);   // 阳极
        set_pin(map->cathode, 0); // 阴极
    }
    else
    {
        // LED不需要时关闭 //注意:不加关闭会导致显示亮度不均
        SEG_Clear();
    }

    seg_num = (seg_num + 1) % SEG_MAP_SIZE;
}
相关推荐
锻炼²5 小时前
USB 设备/配置/接口/端点/描述符 和 HID类请求详解
stm32·usb·hid·全速传输·sof包·中断传输
不脱发的程序猿6 小时前
嵌入式开发中C++内存泄漏的场景与解决办法
单片机·嵌入式硬件·嵌入式
小何code6 小时前
STM32入门教程,第10课(下),Keil调试模式
stm32·单片机·嵌入式硬件
Jason_zhao_MR6 小时前
V2G 实战:SECC GreenPHY 通信开发方案
嵌入式硬件·物联网·嵌入式·边缘计算
Y1rong9 小时前
STM32之中断
stm32·单片机·嵌入式硬件
先知后行。9 小时前
STM32F103的启动过程
stm32·单片机·嵌入式硬件
idcardwang10 小时前
xl9555-IO拓展芯片
stm32·单片机·嵌入式硬件
Y1rong10 小时前
STM32之EXTI
stm32·单片机·嵌入式硬件
兆龙电子单片机设计10 小时前
【STM32项目开源】STM32单片机智能语音家居控制系统
stm32·单片机·嵌入式硬件·物联网·开源·自动化
意法半导体STM3211 小时前
【官方原创】SAU对NSC分区的影响 LAT1578
stm32·单片机·嵌入式硬件·mcu·信息安全·trustzone·stm32开发