四格电量指示灯--查理复用法,可扩展至64个电量灯

程序特点:

1.运用查理复用大法,用最少的管脚点最多的指示灯,N个管脚可以点亮N*(N-1)个灯

2.使用表驱动设计模式,可移植性和扩展性极佳,只需要在数组末端增加元素。

3.演示程序是四格电量灯,实现开机跑马灯自检,放电常亮,充电闪灯,充满全亮。

#include "LED188.c"

cpp 复制代码
#include "LED188.h" 

void LED1_IN(void)  { LED1_GPORT->MODER &= ~(0x03 << 2); }  
void LED2_IN(void)  { LED2_GPORT->MODER &= ~(0x03 << 0); }  
void LED3_IN(void)  { LED3_GPORT->MODER &= ~(0x03 << 8); }   
 
void LED1_OUT(void) { LED1_GPORT->MODER |=  (0x01 << 2); }  
void LED2_OUT(void) { LED2_GPORT->MODER |=  (0x01 << 0); }  
void LED3_OUT(void) { LED3_GPORT->MODER |=  (0x01 << 8); }   

void LED1_H(void)		{LED1_GPORT->BSRR 	= LED1_GPIN;}
void LED2_H(void)		{LED2_GPORT->BSRR 	= LED2_GPIN;}
void LED3_H(void)		{LED3_GPORT->BSRR 	= LED3_GPIN;}

void LED1_L(void)		{LED1_GPORT->BRR  	= LED1_GPIN;}
void LED2_L(void)		{LED2_GPORT->BRR  	= LED2_GPIN;}
void LED3_L(void)		{LED3_GPORT->BRR  	= LED3_GPIN;}

typedef void (*gpio_func_t)(void);

static const gpio_func_t pin_set_input[] 	= {LED1_IN,	LED2_IN, LED3_IN};
static const gpio_func_t pin_set_output[]   = {LED1_OUT,LED2_OUT,LED3_OUT};
static const gpio_func_t pin_set_high[] 	= {LED1_H,	LED2_H,	 LED3_H};
static const gpio_func_t pin_set_low[] 		= {LED1_L,	LED2_L,	 LED3_L};

static inline void pin_output_h(u8 pin){pin_set_high[pin-1]();pin_set_output[pin-1]();}
static inline void pin_output_l(u8 pin){pin_set_low[pin-1]();pin_set_output[pin-1]();}
static inline void pin_input(u8 pin)   {pin_set_input[pin-1]();}

uc8 bit_mask[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

static void set_all_pins_low(void)
{
	for(u8 i=1;i<(LED_PIN_NUM+1);i++)
		pin_output_l(i);
}
static void set_all_pins_in(void)
{
	for(u8 i=1;i<(LED_PIN_NUM+1);i++)
		pin_input(i);
}

const LED_SCANTABLE_t LED_ScanTable[]=
{
    {2,1},//2=pin2低电平,1=pin1高电平
    {3,1},
    {1,2},
    {3,2},
};

union uint8_uo dp_scan_led;

void Display_Tube(void)
{
    static u8 slot = 0;
    if (!Disp_data.B_EN) 
    {
		set_all_pins_low();
		return;
    }
	set_all_pins_in();
		
    const LED_SCANTABLE_t *pslot=&LED_ScanTable[slot];
		
    if(dp_scan_led.byte & bit_mask[slot])
    {
		pin_output_l(pslot->Lpin);
		pin_output_h(pslot->Hpin);
	}
	if (++slot >= LED_SEG_NUM) slot = 0;
}

uc8 led_paoma_table[9]={
0x00,//0
0x01,//1
0x03,//2
0x07,//3
0x0F,//4
0x1F,//5
0x3F,//5
0x7F,//6
0xFF,//5
};

uc8 led_flow_table[9]={
0x00,//0
0x01,//1
0x02,//2
0x04,//3
0x08,//4
0x10,//5
0x20,//6
0x40,//7
0x80 //8
};

DisplayData Disp_data;

void LED_DCHG_Display(u8 soc)
{
	dp_scan_led.byte&=0x01;
	if(led_paoma_table[soc])
		dp_scan_led.byte=led_paoma_table[soc];
	else
		dp_scan_led.Bit.b0=!dp_scan_led.Bit.b0;
}

void LED_CHG_Display(u8 soc)
{
	static bool B_TOG=0;
	static union uint8_uo dp_scan_led_Q;
	dp_scan_led.byte&=0x00;
	B_TOG=!B_TOG;
	
	dp_scan_led.byte=led_paoma_table[soc];
	if(soc>0)
		dp_scan_led_Q.byte=led_paoma_table[soc-1];
	else
		dp_scan_led_Q.byte=led_paoma_table[1];
	dp_scan_led.byte=(B_TOG>0)? dp_scan_led.byte:dp_scan_led_Q.byte;
}

bool LED_FLOW_Display(void)
{
	static u8 i=0;
	if(i++>=LED_SEG_NUM) 
	{
		dp_scan_led.byte=0;
		return 1;
	}
	else
	{
		dp_scan_led.byte=led_flow_table[i];
		return 0;
	}
}

u8 soc_grade[6]={10,25,50,75,99,100};
u8 SocGrade_calculate(u8 soc)
{
	u8 i=0;
	for(i=0;i<6;i++)
		if(soc<soc_grade[i])
			break;
	return i;
}

void Dispdata_Init(void)
{
	Disp_data.B_JC	  =1;
	Disp_data.init_cnt=1;
	Disp_data.B_EN	  =1;
	Disp_data.B_CHGING=0;
	Disp_data.B_ERROR =0;
}

void Refresh_188Data(void)
{
	static u8 B_end;
	
	if(!Disp_data.B_JC)
		return;
	Disp_data.B_JC=0;
	
	Disp_data.B_FCHG  =0;
	Disp_data.B_CHGING=1;
	Disp_data.SOC=SocGrade_calculate(R_bat_data.SOC);
	
	if(Disp_data.B_ERROR)
		return;
	if(Disp_data.init_cnt)
	{
		B_end=LED_FLOW_Display();
		if(B_end)
			Disp_data.init_cnt=0;
	}
	else
	{
		if(Disp_data.B_CHGING)
			LED_CHG_Display(Disp_data.SOC);
		else
			LED_DCHG_Display(Disp_data.SOC);
	}
}

#include "LED188.h"

cpp 复制代码
#ifndef LED188_H
#define LED188_H
#include "user_define.h"
#include "gpio.h"

#define LED_PIN_NUM (sizeof(pin_set_input) / sizeof(pin_set_input[0]))
#define LED_SEG_NUM (sizeof(LED_ScanTable) / sizeof(LED_ScanTable[0]))
	
typedef struct LED_SCANTABLE_t
{
	u8  Lpin;
	u8	Hpin;
} LED_SCANTABLE_t;

struct bit8_t
{
    u8 b0  :1;
	u8 b1  :1;
	u8 b2  :1;
	u8 b3  :1;
	u8 b4  :1;
	u8 b5  :1;
	u8 b6  :1;
	u8 b7  :1;
};
union uint8_uo
{
	u8 byte;
 	struct bit8_t Bit;
};

typedef struct DisplayData
{
	u8 B_JC			:1;
	u8 B_EN			:1;
	u8 B_FCHG		:1;
	u8 B_CHGING	    :1;
	u8 B_TOG	 	:1;
	u8 B_ERROR      :1;
	u8 LowC_cnt;
	u8 LowC_mask_cnt;
	u8 SOC;
	u8 init_cnt;
	u8 display_tim;
}DisplayData;

extern DisplayData Disp_data;
extern void Refresh_188Data(void);
extern void Dispdata_Init(void);
extern void Display_Tube(void);
#endif