中微芯片SC8P052,5脚两位数码管驱动代码
摘要:本文介绍了一种仅需5个IO引脚即可驱动两个7段数码管的极简驱动方案。该方案采用复用IO技术,通过状态机扫描方式实现0-99的数字显示,包含完整的段码映射表和初始化/显示控制函数。特点包括代码结构清晰、便于移植,支持动态数字切换(如65→55→45循环显示),适合MCU引脚资源紧张的场景。驱动通过1ms定时器中断进行扫描刷新,有效降低了硬件资源占用。
·
本工程实现了一个极简、通用的88数码管 7 段数码管驱动,适用于 MCU 引脚资源紧张、需要复用 IO 的场景。
特点:
✔ 仅需 5 个 IO 就能驱动两个数码管
✔ 支持 0~99 任意数字显示
✔ 代码结构清晰,便于移植
✔ 有完整段码映射、扫描状态机
数码管引脚对应表

数码管实物图

不多说直接上代码-V-
里面的gpio.h,delay.h可以查看我之前发布的文章哦
1.digit.c
#include "digit.h" // 数码管相关头文件
#include "gpio.h" // GPIO 头文件
#include <stdint.h> // 标准整数类型
#include <sc.h> // 单片机相关头文件
#include "delay.h" // 延时函数
// 定义数码管使用的 GPIO 引脚
#define LED1 RB4
#define LED2 RB5
#define LED3 RB2
#define LED4 RB1
#define LED5 RB0
#define HIGH 1 // 高电平
#define LOW 0 // 低电平
// 数码管段码表(0~9),显示0->001111111
uint8_t digit_table[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//--------------------------------------------------
// 数码管初始化
//--------------------------------------------------
void Digite_Init(void)
{
DIG_PowerOFF(); // 默认关闭显示
}
//--------------------------------------------------
// 清屏(所有引脚设为浮空输入)
//--------------------------------------------------
void DIG_Reset(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.Pull = GPIO_NOPULL; // 浮空输入
GPIO_Init(GPIOB, &GPIO_InitStructure); // 初始化 GPIOB 引脚
}
//--------------------------------------------------
// 控制某个 LED 引脚输出高/低电平
//--------------------------------------------------
void DIG_LEDx_Control(DIG_PIN_t ledx, uint8_t level)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; // 设置为推挽输出
// 选择要配置的引脚
switch(ledx)
{
case 1: GPIO_InitStructure.Pin = GPIO_PIN_4; break;
case 2: GPIO_InitStructure.Pin = GPIO_PIN_5; break;
case 3: GPIO_InitStructure.Pin = GPIO_PIN_2; break;
case 4: GPIO_InitStructure.Pin = GPIO_PIN_1; break;
case 5: GPIO_InitStructure.Pin = GPIO_PIN_0; break;
}
GPIO_Init(GPIOB, &GPIO_InitStructure); 初始化 GPIOB 引脚
// 设置输出电平
switch(ledx)
{
case 1: LED1 = level; break;
case 2: LED2 = level; break;
case 3: LED3 = level; break;
case 4: LED4 = level; break;
case 5: LED5 = level; break;
}
}
//--------------------------------------------------
// //显示左边数码管引脚1,是低电平的段码
//--------------------------------------------------
void DIG1_1L(uint8_t data_ten)
{
DIG_LEDx_Control(DIG_PIN1, LOW); // 设置为共阴脚
if(digit_table[data_ten] & 0x01) DIG_LEDx_Control(DIG_PIN2, HIGH);
if(digit_table[data_ten] & 0x02) DIG_LEDx_Control(DIG_PIN3, HIGH);
if(digit_table[data_ten] & 0x04) DIG_LEDx_Control(DIG_PIN4, HIGH);
if(digit_table[data_ten] & 0x08) DIG_LEDx_Control(DIG_PIN5, HIGH);
}
//--------------------------------------------------
// //显示左边数码管引脚2,是低电平的段码
//--------------------------------------------------
void DIG1_2L(uint8_t data_ten)
{
DIG_LEDx_Control(DIG_PIN2, LOW);
if(digit_table[data_ten] & 0x10) DIG_LEDx_Control(DIG_PIN1, HIGH);
if(digit_table[data_ten] & 0x20) DIG_LEDx_Control(DIG_PIN3, HIGH);
if(digit_table[data_ten] & 0x40) DIG_LEDx_Control(DIG_PIN4, HIGH);
}
//--------------------------------------------------
//显示右边数码管引脚2,是低电平的段码
//--------------------------------------------------
void DIG2_2L(uint8_t data_bit)
{
DIG_LEDx_Control(DIG_PIN2, LOW);
if(digit_table[data_bit] & 0x01) DIG_LEDx_Control(DIG_PIN5, HIGH);
}
//--------------------------------------------------
// //显示左边数码管引脚3,是低电平的段码
//--------------------------------------------------
void DIG2_3L(uint8_t data_bit)
{
DIG_LEDx_Control(DIG_PIN3, LOW);
if(digit_table[data_bit] & 0x02) DIG_LEDx_Control(DIG_PIN1, HIGH);
if(digit_table[data_bit] & 0x04) DIG_LEDx_Control(DIG_PIN2, HIGH);
if(digit_table[data_bit] & 0x08) DIG_LEDx_Control(DIG_PIN4, HIGH);
if(digit_table[data_bit] & 0x10) DIG_LEDx_Control(DIG_PIN5, HIGH);
}
//--------------------------------------------------
//显示左边数码管引脚4,是低电平的段码
//--------------------------------------------------
void DIG2_4L(uint8_t data_bit)
{
DIG_LEDx_Control(DIG_PIN4, LOW);
if(digit_table[data_bit] & 0x20) DIG_LEDx_Control(DIG_PIN1, HIGH);
if(digit_table[data_bit] & 0x40) DIG_LEDx_Control(DIG_PIN2, HIGH);
}
//==================================================
// 变量定义区
//==================================================
uint8_t scan_cnt = 0; // 扫描计数器
bit digite_display_flag; // 显示开关标志
uint8_t display_value; // 显示的数字
uint8_t tens; // 十位
uint8_t ones; // 个位
//--------------------------------------------------
// 数码管扫描
//--------------------------------------------------
void Digite_Display(void)
{
if(digite_display_flag)
{
DIG_Reset();
tens = display_value / 10;
ones = display_value % 10;
switch(scan_cnt)
{
case 0: DIG1_1L(tens); scan_cnt++; break;
case 1: DIG1_2L(tens); scan_cnt++; break;
case 2: DIG2_2L(ones); scan_cnt++; break;
case 3: DIG2_3L(ones); scan_cnt++; break;
case 4: DIG2_4L(ones); scan_cnt = 0; break;
default: scan_cnt = 0; break;
}
}
}
//==================================================
// 显示固定数字的接口(给外部调用)
//==================================================
void Display_45(void){ display_value = 45; digite_display_flag = 1; }
void Display_55(void){ display_value = 55; digite_display_flag = 1; }
void Display_65(void){ display_value = 65; digite_display_flag = 1; }
void Display_88(void){ display_value = 88; digite_display_flag = 1; }
// 关闭显示
void Digite_Display_OFF(void)
{
digite_display_flag = 0;
DIG_Reset();
display_value = 0;
}
//==================================================
// 状态机:循环显示 65 → 55 → 45
//==================================================
uint8_t digNumState = 0;
void Digite_Switch(void)
{
if(digNumState == 0)
{
Display_65();
digNumState = 1;
}
else if(digNumState == 1)
{
Display_55();
digNumState = 2;
}
else
{
Display_45();
digNumState = 0;
}
}
// 开机默认显示 65
void DIG_PowerON(void)
{
Display_65();
digNumState = 1;
}
// 关机清除显示
void DIG_PowerOFF(void)
{
Digite_Display_OFF();
digNumState = 0;
}
2.digit.h
#ifndef _DIGIT_H_
#define _DIGIT_H_
#include <stdint.h>
// 定义数码管,引脚编号的枚举类型
typedef enum
{
DIG_PIN1 = 1, // 枚举成员1,对应原宏定义1
DIG_PIN2, // 自动+1,对应2
DIG_PIN3, // 自动+1,对应3
DIG_PIN4, // 自动+1,对应4
DIG_PIN5 // 自动+1,对应5
} DIG_PIN_t; // 枚举类型名
void Digite_Init(void);//数码管初始化
void DIG_Reset(void);//清屏
// 函数作用:控制指定编号的LED输出高或低电平
// 参数 ledx:要控制的LED编号
// 参数 level:输出电平,1为高电平,0为低电平
void DIG_LEDx_Control(DIG_PIN_t ledx, uint8_t level);
void Digite_Display(void);
void Display_45(void);
void Display_55(void);
void Display_65(void);
void Display_88(void);
void Digite_Display_OFF(void);
void Digite_Switch(void);
// 开机初始化灯状态,只亮红灯
void DIG_PowerON(void);
// 关机时关闭所有灯
void DIG_PowerOFF(void);
#endif
3.把这个函数Digite_Display();放到定时器里面,我设置的是1ms扫描一次。
/***********************************************
函数名称:Interrupt
函数功能:中断服务
入口参数:无
出口参数:无
备注:只能有一个中断服务函数,1ms进入一次
************************************************/
void interrupt Interrupt(void)
{
if(TMR2IF)
{
TMR2IF = 0;
Digite_Display();//数码管扫描
}
}
4.数码管显示65
void main(void)
{
Init_System();//系统初始化
Display_65();//显示65
while(1)
{
asm("nop"); // 空操作指令
}
}
5.真实拍摄图片

欢迎关注,更多精彩内容将持续更新,感谢您的支持!
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)