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;
}
相关推荐
十月的皮皮11 小时前
stm20260720-从新手 C 到量产 STM32 工程:程序设计推导指南
c语言·开发语言·stm32·stm32cubemx·hal库
开发笔记-阿牛11 小时前
解析一款有意思的产品||CK6159A语音芯片设计的儿童专注力训练机-舒尔特玩具
stm32·单片机·嵌入式硬件·音频
搞全栈小苏13 小时前
SIMetrix_simplis8.4安装教程——附安装包
stm32·单片机·嵌入式硬件·电力电子
qq_5739678214 小时前
STM32控制器
stm32·单片机·嵌入式硬件
某林21215 小时前
履带小车底盘stm32F103RCT6开发
人工智能·stm32·单片机·嵌入式硬件·架构·人机交互·ros2
做萤石二次开发的哈哈17 小时前
萤石 ERTC Windows SDK 包含哪些类型定义?
stm32·单片机·嵌入式硬件
亿道电子Emdoor17 小时前
【Aitium】PCB导出DXF文件出现eDuplicateRecordName报错
stm32·单片机·嵌入式硬件·altium
巴巴媛6661 天前
STM32学习笔记【38.DHT11实验】
笔记·stm32·学习
深圳市泰凌微电子1 天前
HK航顺 HK32F407RGT7替STM32F405RGT6 微控制器32位MCU
stm32·单片机·嵌入式硬件
K成长日志1 天前
BLE链路层空口包--LE Uncoded PHY
物联网·嵌入式·蓝牙·iot·ble·无线·通信