在单片机应用中,数码管是经常用的是器件之一.如果把一个简单的单片机系统看成是一台电脑,那么数码管就相当于一台电脑的显示器.现用一个2位半的数码管做个范例,循环显示0-199,稍作改造就可以做成一个计算器.使用8pin数码管,采用扫描方式驱动,4*4,正好16段.单片机使用pms152,不多说上代码.
实际显示效果
#include "extern.h"
BIT COM1 :PB.0;/*Pin8*/
BIT COM2 :PB.1;/*Pin1*/
BIT COM3 :PB.2;/*Pin6*/
BIT COM4 :PB.3;/*Pin3*/
BIT SEG1 :PB.4;/*Pin7*/
BIT SEG2 :PB.5;/*Pin5*/
BIT SEG3 :PB.6;/*Pin4*/
BIT SEG4 :PB.7;/*Pin2*/
/*显示变量区域*/
byte ucLcdComVoltSw;
byte ucHun;
byte ucTen;
byte ucOne;
bit SB2:ucHun.1;
bit SC2:ucHun.2;
bit SA0:ucTen.0;
bit SB0:ucTen.1;
bit SC0:ucTen.2;
bit SD0:ucTen.3;
bit SE0:ucTen.4;
bit SF0:ucTen.5;
bit SG0:ucTen.6;
bit SH0:ucTen.7;
bit SA1:ucOne.0;
bit SB1:ucOne.1;
bit SC1:ucOne.2;
bit SD1:ucOne.3;
bit SE1:ucOne.4;
bit SF1:ucOne.5;
bit SG1:ucOne.6;
bit SH1:ucOne.7;
/*系统时钟变量*/
bit FLAG_NMS;/*定时时间是否到了cinit*/
word usSystick;
BYTE count;/* count区*/
word T16COUNTER;/*定时器初始化cinit*/
word usMsTmr;
BYTE ucVoltChgTmr;
BYTE ucVoltPerc;
/*系统变量*/
word point;
/*算法变量*/
BYTE div_src, div_val, div_res;
void Byte_Div_Byte (void)
{ // div_src[B] / div_val[B] = div_src[B] * div_val[B] + div_res[B]
BYTE div_cnt;
div_cnt = 0;
div_res = 0;
A = -div_val;
div_src <<= 1;
do
{
slc div_res;
div_cnt++;
div_res += A;
if (!CF) div_res -= A;
div_src <<<= 1;
} while (! div_cnt.3);
}
/* 共阳led表,共阴取反即可*/
void ReadLedTab ( void )
{
_pcadd
{
ret 0x3f;/*0*/
ret 0x06;/*1*/
ret 0x5b;/*2*/
ret 0x4f;/*3*/
ret 0x66;/*4*/
ret 0x6d;/*5*/
ret 0x7d;/*6*/
ret 0x07;/*7*/
ret 0x7f;/*8*/
ret 0x6f;/*9*/
}
}
/***************************************/
void TIME16_Init(void)
{
/*计数值清零*/
T16COUNTER =488;
/*ms标记reset*/
FLAG_NMS =0;
/*使能定时器*/
INTEN.T16=1;
/*关中断*/
INTRQ = 0;
STT16 T16COUNTER;
/*计算方法16M/*/
$ T16M IHRC,/1,BIT11;
}
/*显示百分比*/
void DispVoltPerc(void)
{
byte ucTemp;
if(ucVoltPerc>99&&ucVoltPerc<200)
{
/*表示显示1*/
ucHun=0x00;
}
else
{
ucHun=0xff;
}
/*把电压值变成0-99之间的值*/
div_src=ucVoltPerc;
div_val=100;
Byte_Div_Byte();
div_src=div_res;
div_val=10;
Byte_Div_Byte();
/*10 位*/
A=(div_src+1);
ReadLedTab();
/*保存当前值*/
ucTemp=A;
/*输出为0*/
if(ucTemp==0x3f)
{
/*最高位为1*/
if(!ucHun)
{
/*显示十位*/
ucTen=~ucTemp;
}
/*十位为0,且最高位为0*/
else
{
/*十位不显示*/
ucTen=0xff;
}
}
else
{
ucTen=~ucTemp;
}
/*个位*/
A=div_res+1;
ReadLedTab();
ucOne=~A;
}
void AppInit(void)
{
ucVoltChgTmr=0;
ucVoltPerc=0;
}
void FPPA0 ( void )
{
/* SYSCLK=2MHz, one cycles =0.5 us */
.ADJUST_IC SYSCLK=IHRC/8, IHRC=16MHz, VDD=3.9v;
WORD usTmp;
TIME16_Init();
/*全亮2s,查看数码管是否连接OK*/
$ COM1 out,high;
$ COM2 out,high;
$ COM3 out,high;
$ COM4 out,high;
$ SEG1 out,low;
$ SEG2 out,low;
$ SEG3 out,low;
$ SEG4 out,low;
usTmp=200;
while(usTmp--)
{
.delay 20000;
wdreset; //复位看门狗定时器
}
/*关闭显示*/
COM1=0;
COM2=0;
COM3=0;
COM4=0;
SEG1=0;
SEG2=0;
SEG3=0;
SEG4=0;
AppInit();
ucVoltPerc=0;
engint;
while ( 1 )
{
if(FLAG_NMS)
{
usMsTmr++;
/*300ms更新一次*/
if(usMsTmr>300)
{
/*数字范围0-199*/
ucVoltPerc++;
if(ucVoltPerc>199)
{
ucVoltPerc=0;
}
usMsTmr=0;
}
FLAG_NMS=0;
}
/*数码管显示*/
DispVoltPerc();
}
}
void IntFlashLed(void)
{
ucLcdComVoltSw++;
if(ucLcdComVoltSw>3)
{
ucLcdComVoltSw=0;
}
switch(ucLcdComVoltSw)
{
case 0:
SEG1=1;
SEG2=1;
SEG3=1;
SEG4=1;
#if 1
COM1=1;
COM2=0;
COM3=0;
COM4=0;
#endif
if(SA0)
{
SEG1=1;
}
else
{
SEG1=0;
}
if(SB0)
{
SEG2=1;
}
else
{
SEG2=0;
}
if(SC0)
{
SEG3=1;
}
else
{
SEG3=0;
}
if(SD0)
{
SEG4=1;
}
else
{
SEG4=0;
}
break;
case 1:
SEG1=1;
SEG2=1;
SEG3=1;
SEG4=1;
#if 0
COM1=1;
COM2=0;
COM3=1;
COM4=1;
#endif
#if 1
COM1=0;
COM2=1;
COM3=0;
COM4=0;
#endif
if(SF0)
{
SEG1=1;
}
else
{
SEG1=0;
}
if(SG0)
{
SEG2=1;
}
else
{
SEG2=0;
}
if(SE0)
{
SEG3=1;
}
else
{
SEG3=0;
}
if(SB2)
{
SEG4=1;
}
else
{
SEG4=0;
}
break;
case 2:
SEG1=1;
SEG2=1;
SEG3=1;
SEG4=1;
#if 0
COM1=1;
COM2=1;
COM3=0;
COM4=1;
#endif
#if 1
COM1=0;
COM2=0;
COM3=1;
COM4=0;
#endif
if(SA1)
{
SEG1=1;
}
else
{
SEG1=0;
}
if(SB1)
{
SEG2=1;
}
else
{
SEG2=0;
}
if(SC1)
{
SEG3=1;
}
else
{
SEG3=0;
}
if(SD1)
{
SEG4=1;
}
else
{
SEG4=0;
}
break;
case 3:
SEG1=1;
SEG2=1;
SEG3=1;
SEG4=1;
#if 0
COM1=1;
COM2=1;
COM3=1;
COM4=0;
#endif
#if 1
COM1=0;
COM2=0;
COM3=0;
COM4=1;
#endif
if(SF1)
{
SEG1=1;
}
else
{
SEG1=0;
}
if(SG1)
{
SEG2=1;
}
else
{
SEG2=0;
}
if(SE1)
{
SEG3=1;
}
else
{
SEG3=0;
}
if(SC2)
{
SEG4=1;
}
else
{
SEG4=0;
}
break;
default:
break;
}
}
void Interrupt ( void )
{
pushaf;
if ( Intrq.T16 )
{
Intrq.T16 = 0;
STT16 T16COUNTER;
IntFlashLed();
if ( count>0 )
{
count--;
}
else
{
count = 9;
/*1ms*/
FLAG_NMS= 1;
}
}
popaf;
}