前言
最近用到了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; //临时计数1u16 cnt2; //临时计数2LedSta_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();//拉低Pin1if(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;//0display_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;}
}