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;
}
相关推荐
Big_潘大师5 小时前
STM32串口中断
stm32·单片机·嵌入式硬件
1+2单片机电子设计6 小时前
基于 STM32 的网络授权时钟系统设计与实现
开发语言·stm32·单片机·嵌入式硬件·php·51单片机
大聪明-PLUS6 小时前
如何修补 Linux 内核:完整指南
linux·嵌入式·arm·smarc
TEC_INO7 小时前
STM32_3:EXTI和NVIC
stm32·单片机·嵌入式硬件
大聪明-PLUS7 小时前
Docker 内部机制:深入剖析
linux·嵌入式·arm·smarc
LCG米7 小时前
基于STM32F4和LVGL的智能灯光控制系统开发实战
stm32·单片机·嵌入式硬件
Shawn_CH7 小时前
Linux kmsg详解
嵌入式
歌者長門8 小时前
STM32DAC输出遇到的问题
stm32·单片机·嵌入式硬件
辰哥单片机设计8 小时前
STM32项目分享:智能头盔
stm32·单片机·嵌入式硬件