3位6脚数码管驱动

1.概述

        最近拿到的几个案子都是复用型的数码管,也是第一次遇到这种类型的,以后必然是常用的器件,毕竟可以省去很多单片机脚位,所以趁最近有空整理一下几个案子里使用的驱动方法。

        由于是数码管管脚是复用的,所以对于没有用到的管脚要设置为输入模式,并切换为高阻态,如果单片机没有高阻态功能,则关闭上下拉功能,否则会微导通,LED微亮。

        如果产品有低功耗要求,则可以在进入睡眠模式时开启上下拉,被唤醒后关闭上下拉,如果有高阻态功能无需如此。

        假设数码管为6脚,根据数码管管脚的数量我们可以知道最多可以电量6x(6-1)=30个LED。

2.驱动方式

2.1 变量定义

const unsigned char NumX_Tab[10] = { 0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F}; // 0-9
unsigned char Flag_LED_Show;	// 数码管片选
unsigned char Voltage_Unit_Buff;
unsigned char Voltage_Tens_Buff;
unsigned char Voltage_Hbit_Buff;  // 特殊位  
unsigned char Voltage_Num;	// 数码管显示电压百分百
unsigned char Voltage_Unit;	// 个位数
unsigned char Voltage_Tens;	// 十位数

2.2 电路图

2.3 宏定义

//LED灯
#define LED1	PORTB2
#define LED2	PORTB1
#define LED3	PORTB0
#define LED4	PORTA4
#define LED5	PORTA6
#define LED6	PORTA7
#define COM1	PORTB3
#define COM2	PORTB6
#define COM3	PORTB7

2.4 驱动程序

void LED_Show(void)
{    // 此函数每1MS进入一次
	Voltage_Unit = Voltage_Num % 10;
	Voltage_Tens = Voltage_Num / 10;
	if(Voltage_Num >= 99)
	{	// 显示最大为 99
		Voltage_Unit = 9;
		Voltage_Tens = 9;
	}
	Voltage_Unit_Buff = NumX_Tab[Voltage_Unit];
	Voltage_Tens_Buff = NumX_Tab[Voltage_Tens];
	PORTB |= 0XCF;  // 1100 1000 PB7 PB6 PB3 PB2 PB1 PB0高电平
	PORTA |= 0XD0 ;	// 1101 0000 PA7 PA6 PA4 高电平
	switch(Flag_LED_Show)
	{	// 共阳
		case 0: // A1 B1 C1 D1 E1 F1
				COM1 = 0;
				if(Voltage_Tens_Buff & 0X01)	// A1
					LED1 = 0;
				if(Voltage_Tens_Buff & 0X02)	// B1
					LED2 = 0;
				if(Voltage_Tens_Buff & 0X04)	// C1
					LED3 = 0;
				if(Voltage_Tens_Buff & 0X08)	// D1
					LED4 = 0;
				if(Voltage_Tens_Buff & 0X10)	// E1
					LED5 = 0;
				if(Voltage_Tens_Buff & 0X20)	// F1
					LED6 = 0;
				Flag_LED_Show++;
				break;
		case 1: // A2 B2 C2 D2 E2 F2
				COM2 = 0;
				if(Voltage_Unit_Buff & 0X01)	// A2
					LED1 = 0;
				if(Voltage_Unit_Buff & 0X02)	// B2
					LED2 = 0;
				if(Voltage_Unit_Buff & 0X04)	// C2
					LED3 = 0;
				if(Voltage_Unit_Buff & 0X08)	// D2
					LED4 = 0;
				if(Voltage_Unit_Buff & 0X10)	// E2
					LED5 = 0;
				if(Voltage_Unit_Buff & 0X20)	// F2
					LED6 = 0;
				Flag_LED_Show++;
				break;
		case 2: // A3 B3 C3 G1 G2
				COM3 = 0;
				if(Voltage_Hbit_Buff & 0X01)	// A3
					LED1 = 0;
				if(Voltage_Hbit_Buff & 0X02)	// B3
					LED2 = 0;
				if(Voltage_Hbit_Buff & 0X04)	// C3
					LED3 = 0;
				if(Voltage_Tens_Buff & 0X40)	// G1
					LED4 = 0;
				if(Voltage_Unit_Buff & 0X40)	// G2
					LED5 = 0;
				Flag_LED_Show = 0;
				break;
	}
	Voltage_Unit_Buff = 0;
	Voltage_Tens_Buff = 0;
	Voltage_Hbit_Buff = 0;

} 

3.驱动方式2

3.1 电路图

 3.2 驱动程序

void LED_Show(void)
{
	if((Flag_System_Mode)||(Flag_5V)||(Flag_Bat_State >= 2))
	{	// 运行 充电 发生事件可进
		Voltage_Unit = Voltage_Num % 10;
		Voltage_Tens = Voltage_Num / 10;
		if(Voltage_Num >= 100)
		{	// 显示最大为 100
			Voltage_Hbit_Buff |= 0X03;//百位 显示1
			Voltage_Unit = 0;
			Voltage_Tens = 0;
		}
		Voltage_Unit_Buff = NumX_Tab[Voltage_Unit];
		Voltage_Tens_Buff = NumX_Tab[Voltage_Tens];
		Voltage_Hbit_Buff |= 0X0C;//百分百与英文挡常亮
        TRISB = 0XEB;
		TRISA = 0X1F;    // 消隐
		switch(Flag_LED_Show)
		{	// 共阴
			case 0: // H1 H2 A1 B1 LE1
					TRISB1 = 0; LED1 = 0;
					if(Voltage_Hbit_Buff & 0X01)
					{	// H1
						TRISB7 = 0;
						LED2 = 1;
					}	
					if(Voltage_Hbit_Buff & 0X02)
					{	// H2
						TRISB0 = 0;
						LED3 = 1;
					}
					if(Voltage_Tens_Buff & 0X01)
					{	// A1
						TRISA4 = 0;	
						LED4 = 1;
					}
					if(Voltage_Tens_Buff & 0X02)
					{	// B1
						TRISA3 = 0;	
						LED5 = 1;
					}
                    Flag_LED_Show++;
					break;
			case 1: // C1 D1 E1 F1 LED2
					TRISB7 = 0; LED2 = 0;
					if(Voltage_Tens_Buff & 0X04)
					{	// C1
						TRISB1 = 0;
						LED1 = 1;
					}	
					if(Voltage_Tens_Buff & 0X08)
					{	// D1
						TRISB0 = 0;
						LED3 = 1;
					}
					if(Voltage_Tens_Buff & 0X10)
					{	// E1
						TRISA4 = 0;	
						LED4 = 1;
					}
					if(Voltage_Tens_Buff & 0X20)
					{	// F1
						TRISA3 = 0;	
						LED5 = 1;
					}
                    Flag_LED_Show++;
					break;
			case 2: // G1 A2 B2 C2 LED3
					TRISB0 = 0;LED3 = 0;
					if(Voltage_Tens_Buff & 0X40)
					{	// G1
						TRISB1 = 0;
						LED1 = 1;
					}	
					if(Voltage_Unit_Buff & 0X01)
					{	// A2
						TRISB7 = 0;
						LED2 = 1;
					}
					if(Voltage_Unit_Buff & 0X02)
					{	// B2
						TRISA4 = 0;	
						LED4 = 1;
					}
					if(Voltage_Unit_Buff & 0X04)
					{	// C2
						TRISA3 = 0;	
						LED5 = 1;
					}
                    Flag_LED_Show++;
					break;
			case 3: // D2 E2 F2 G2 LED4
					TRISA4 = 0;	LED4 = 0;
					if(Voltage_Unit_Buff & 0X08)
					{	// D2
						TRISB1 = 0;
						LED1 = 1;
					}	
					if(Voltage_Unit_Buff & 0X10)
					{	// E2
						TRISB7 = 0;
						LED2 = 1;
					}
					if(Voltage_Unit_Buff & 0X20)
					{	// F2
						TRISB0 = 0;
						LED3 = 1;	
					}
					if(Voltage_Unit_Buff & 0X40)
					{	// G2
						TRISA3 = 0;	
						LED5 = 1;
					}
                    Flag_LED_Show++;
					break;
			case 4: // H3 H4 H5 H6 LED5
					TRISA3 = 0;LED5 = 0;
					if(Voltage_Hbit_Buff & 0X04)
					{	// H3
						TRISB1 = 0;
						LED1 = 1;
					}	
					if(Voltage_Hbit_Buff & 0X08)
					{	// H4
						TRISB7 = 0;
						LED2 = 1;
					}
					if(Voltage_Hbit_Buff & 0X10)
					{	// H5
						TRISB0 = 0;	
						LED3 = 1;
					}
					if(Voltage_Hbit_Buff & 0X20)
					{	// H6
						TRISA4 = 0;	
						LED4 = 1;
					}
                    Flag_LED_Show = 0;
					break;
		}
		Voltage_Unit_Buff = 0;
		Voltage_Tens_Buff = 0;
		Voltage_Hbit_Buff = 0;
	}
} 

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以下是ESP32-C3控制TM1652驱动数码管的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" #define CLK_PIN GPIO_NUM_0 #define DIO_PIN GPIO_NUM_1 #define DIG1 0x68 #define DIG2 0x6a static void tm1652_write_byte(uint8_t data) { uint8_t i; gpio_set_direction(DIO_PIN, GPIO_MODE_OUTPUT); gpio_set_direction(CLK_PIN, GPIO_MODE_OUTPUT); for(i=0; i<8; i++) { gpio_set_level(CLK_PIN, 0); gpio_set_level(DIO_PIN, data & (1<<i)); gpio_set_level(CLK_PIN, 1); } } static void tm1652_display(uint8_t dig1, uint8_t dig2) { tm1652_write_byte(0x48); // Control command, write data to display register tm1652_write_byte(DIG1); // Write digit 1 tm1652_write_byte(dig1); tm1652_write_byte(DIG2); // Write digit 2 tm1652_write_byte(dig2); tm1652_write_byte(0x8f); // Control command, turn on display } void app_main() { gpio_pad_select_gpio(CLK_PIN); gpio_pad_select_gpio(DIO_PIN); uint8_t count = 0; while(1) { tm1652_display(count/10, count%10); count++; vTaskDelay(1000 / portTICK_PERIOD_MS); } } ``` 注释: 1. CLK_PIN和DIO_PIN分别对应TM1652的时钟和数据线引,可以根据实际连接的引进行修改。 2. DIG1和DIG2是TM1652内部控制寄存器中两个数码管的地址,分别为0x68和0x6a,不需要修改。 3. `tm1652_write_byte`函数用于向TM1652写入一个字节的数据,具体实现为模拟SPI协议,每次向DIO引写入一数据,然后拉高CLK引,这样就可以逐地向TM1652发送数据。在写入每个字节之前,需要先将DIO引和CLK引设置为输出模式。 4. `tm1652_display`函数用于向TM1652写入两个数字,具体实现为先向控制寄存器中写入控制命令,然后分别向两个数码管写入数据。最后再向控制寄存器中写入开启显示的命令。 5. 在`app_main`函数中,首先需要将CLK_PIN和DIO_PIN设置为GPIO模式,并且初始化一个计数器count。然后进入一个循环中,每隔1秒钟调用`tm1652_display`函数向TM1652写入count的十数和个数,然后将count加1。由于TM1652内部有扫描驱动电路,所以可以在两个数码管之间切换显示,从而实现动态显示的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值