188数码管轮询扫描

前言

最近用到了188数码管,总结一下。

188数码管,用5个IO,在不借助外部驱动芯片的情况下,可以点亮20个灯。188数码管广泛应用于电子烟、充电器、充电宝、DVD、高级音响、工业设备控制面板、医疗器械等多个领域,满足不同设备和场景的需求。

有纰漏请指出,转载请说明。

学习交流请发邮件 1280253714@qq.com。

原理讲解

参考自文章 188数码管驱动程序(简洁)_188数码管电路图-CSDN博客

讲解非常到位,移植也很简单

这里我再给出数码管的顶层应用示例,即开、关、闪烁 

代码

LED.H 

#ifndef LED_H
#define LED_H
#include "SYS.h"

void LED_Init(void);
void Display_tube(void);


typedef enum {
   	eLedOff = 0,
   	eLedOn,
   	eLedIntermittent,
} LedSta_S;

typedef struct {
   	u16 period;    	//闪烁的周期
   	u16 time;  	   	//闪烁的次数
   	u16 cnt1;  	   	//临时计数1
   	u16 cnt2;  	   	//临时计数2
   	LedSta_S sta;
} LED_S;

extern LED_S stLed;
void LedSet(LedSta_S sta, u16 period, u16 time);
void LedLoopTask(void);

#endif

 

LED.C

#include "led.h"

 
/************************************************************************************/
void LED_Init(void)//初始化IO口
{
    PIN1_IN();//把单片机IO口配置为输入模式
    PIN2_IN();
    PIN3_IN();
    PIN4_IN();
    PIN5_IN();
}
 
/********************************熄灭所有数码管***********************************/
void Set_AllPin_INPUT(void)
{
    PIN1_IN();
    PIN2_IN();
    PIN3_IN();
    PIN4_IN();
    PIN5_IN();
}
 
u16 display_sram=0;
 
void Display_Scan1(void)
{
    PIN1_L();//拉低Pin1
    if(display_sram&0x8000)
        PIN2_H();
    if(display_sram&0x4000)
        PIN3_H();
    if(display_sram&0x2000)
        PIN4_H();
    if(display_sram&0x1000)
        PIN5_H();
}
void Display_Scan2(void)
{
    PIN2_L();
    if(display_sram&0x0800)
        PIN1_H();
    if(display_sram&0x0400)
        PIN3_H();
    if(display_sram&0x0200)
        PIN4_H();
    if(display_sram&0x0100)
        PIN5_H();
}
void Display_Scan3(void)
{
    PIN3_L();
    if(display_sram&0x0080)
        PIN1_H();
    if(display_sram&0x0040)
        PIN2_H();
    if(display_sram&0x0020)
        PIN4_H();
    if(display_sram&0x0010)
        PIN5_H();
}
void Display_Scan4(void)
{
    PIN4_L();
    if(display_sram&0x0008)
        PIN1_H();
    if(display_sram&0x0004)
        PIN2_H();
    if(display_sram&0x0002)
        PIN3_H();
    if(display_sram&0x0001)
        PIN5_H();
}
void Display_Scan5(void)
{
    PIN5_L();
    if(stSys.chargingFlag) {
   	   	PIN2_H();
        PIN3_H();
   	} else {
        PIN2_H();
   	}
}


/****************************显示函数***********************************/
 
//放在定时器中断函数,5ms运行一次,扫描一轮需要4*5ms=20ms,
//也就是50Hz的刷新频率,如果感觉闪烁,可以4ms运行。
void Display_tube(void)
{
   	u16 Segment[3][11]={
      {0x0000,0x0006,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},//百位
      {0x0770,0x0420,0x0741,0x0661,0x0431,0x0271,0x0371,0x0460,0x0771,0x0671,0x0000},//十位
      {0xE888,0x8080,0xD808,0xD880,0xB080,0x7880,0x7888,0x8880,0xF888,0xF880,0x0000} //个位
   	}; 	
    static u8 case_cnt = 0;//逐行扫描
   
    Set_AllPin_INPUT();//消影作用
    //display_sram=0x84A6;//111
   	//display_sram=0xDF49;//022
   	//display_sram=0xE888;//0
    display_sram=Segment[0][stSys.tube_bai] | Segment[1][stSys.tube_shi] | Segment[2][0];//显示百位,十位,个位
    switch(case_cnt)
    {
      case 0x00:Display_Scan1();case_cnt++;break;
      case 0x01:Display_Scan2();case_cnt++;break;
      case 0x02:Display_Scan3();case_cnt++;break;
      case 0x03:Display_Scan4();case_cnt++;break;
      case 0x04:Display_Scan5();case_cnt=0;break;
      default:case_cnt=0;break;
    }
}

LED_S stLed;

void LedSet(LedSta_S sta, u16 period, u16 time)
{
   	stLed.period   	= period;
   	stLed.time 	   	= time;
   	stLed.sta  	   	= sta;
   	stLed.cnt1 	   	= 0;
   	stLed.cnt2 	   	= 0;
}

//此函数放在主循环,
void LedLoopTask(void)
{  	  
    static u8 tubeTaskCnt = 0;
   	tubeTaskCnt++;
   	if (tubeTaskCnt <= 2) {
   	   	return;
   	}
    tubeTaskCnt = 0;
   	
   	switch ( stLed.sta )
   	{
   	   	case eLedOn:
   	   	   	Display_tube();
   	   	   	break;
   	   	case eLedOff:
   	   	   	Set_AllPin_INPUT();
   	   	   	break;
   	   	case eLedIntermittent:
   	   	   	if(stLed.cnt1 < (stLed.period/2)){
   	   	   	   	Set_AllPin_INPUT();
   	   	   	   	stLed.cnt1++;
   	   	   	} else if(stLed.cnt1 < stLed.period){
   	   	   	   	Display_tube();
   	   	   	   	stLed.cnt1++;
   	   	   	} else {
   	   	   	   	stLed.cnt1 = 0;
   	   	   	   	stLed.cnt2++;
   	   	   	   	if (stLed.cnt2 >= stLed.time) {
   	   	   	   	   	stLed.cnt2 = 0;	   	
                    stLed.sta = eLedOff;   	
   	   	   	   	} 
   	   	   	}  	   	   	   	   	   	   	
   	   	   	break; 	
   	}
}

函数调用

/********************************************
*  	@函数名   	SetLedSta
*  	@描述	设置Led灯闪状态
*  	@参数	无
*  	@返回值   	无
*  	@注意	无
********************************************/
void SetLedSta(void)
{
   	if (stSys.ledUpdateFlag == 0)
   	   	return;
   	stSys.ledUpdateFlag = 0;

   	switch (stSys.sta.now)
   	{
   	   	case eStaOverLoad:
   	   	case eStaLowVolt:
   	   	   	LedSet(eLedIntermittent,320,5);
   	   	   	break;
   	   	case eStaRun:
   	   	case eStaOffChging:
   	   	   	LedSet(eLedOn,0,0);
   	   	   	break;
   	   	case eStaCalib:
   	   	   	LedSet(eLedIntermittent,320,6);
   	   	   	break;
   	   	default:
   	   	   	LedSet(eLedOff,0,0);
   	   	   	break;
   	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值