最近做的一個案子,需要用單片機的5個引腳來控制一塊5PIN的188數位管顯示
數位管資料如下:
數字1到5表示對應的數位管引腳,利用二極管的單向導通性來點亮單獨的LED
驅動程式如下:
__sbit PIN1 = PORTA:7;
__sbit PIN2 = PORTA:6;
__sbit PIN3 = PORTA:4;
__sbit PIN4 = PORTA:3;
__sbit PIN5 = PORTA:2;
uint8_t SEG;
uint8_t Data[3]={ 0,0,0};
uint8_t ch[11]={ 0X3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0};//顯示數字0~9
void Display(uint8_t data0,uint8_t data1,uint8_t data2);
void LED_Scan(void);
void isr(void) __interrupt(0)//中斷服務函數
{
if(INTFbits.T0IF)//1.02ms
{
LED_Scan();
INTF= (unsigned char)~(C_INT_TMR0); // Clear T0IF flag bit
}
}
void main(void)
{
//略······
while(1)
{
Display(1,0,0);
}
}
//數位管對應位置顯示數字
void Display(uint8_t data0,uint8_t data1,uint8_t data2)
{
Data[0]=ch[data0];
Data[1]=ch[data1];
Data[2]=ch[data2];
}
//16顆LED逐一掃描
//當用到其中任意兩個IO口的時候,需要将剩餘三個IO口設定為輸入模式,防止互相幹擾
void LED_Scan(void)
{
SEG++;if(SEG>16)SEG=1;
PIN1=PIN2=PIN3=PIN4=PIN5=0;
if(SEG== 1){IOSTA=0XE5;if(Data[0]&0x02)PIN3=1;else PIN3=0;PIN4=0;}//B1
if(SEG== 2){IOSTA=0X75;if(Data[0]&0x04)PIN2=1;else PIN2=0;PIN4=0;}//C1
if(SEG== 3){IOSTA=0X6D;if(Data[1]&0x01)PIN2=1;else PIN2=0;PIN3=0;}//A2
if(SEG== 4){IOSTA=0X6D;if(Data[1]&0x02)PIN3=1;else PIN3=0;PIN2=0;}//B2
if(SEG== 5){IOSTA=0XE5;if(Data[1]&0x04)PIN4=1;else PIN4=0;PIN3=0;}//C2
if(SEG== 6){IOSTA=0X75;if(Data[1]&0x08)PIN4=1;else PIN4=0;PIN2=0;}//D2
if(SEG== 7){IOSTA=0X79;if(Data[1]&0x10)PIN5=1;else PIN5=0;PIN2=0;}//E2
if(SEG== 8){IOSTA=0XE9;if(Data[1]&0x20)PIN5=1;else PIN5=0;PIN3=0;}//F2
if(SEG== 9){IOSTA=0XF1;if(Data[1]&0x40)PIN5=1;else PIN5=0;PIN4=0;}//G2
if(SEG==10){IOSTA=0X3D;if(Data[2]&0x01)PIN1=1;else PIN1=0;PIN2=0;}//A3
if(SEG==11){IOSTA=0X3D;if(Data[2]&0x02)PIN2=1;else PIN2=0;PIN1=0;}//B3
if(SEG==12){IOSTA=0XAD;if(Data[2]&0x04)PIN1=1;else PIN1=0;PIN3=0;}//C3
if(SEG==13){IOSTA=0XAD;if(Data[2]&0x08)PIN3=1;else PIN3=0;PIN1=0;}//D3
if(SEG==14){IOSTA=0XB5;if(Data[2]&0x10)PIN1=1;else PIN1=0;PIN4=0;}//E3
if(SEG==15){IOSTA=0XB5;if(Data[2]&0x20)PIN4=1;else PIN4=0;PIN1=0;}//F3
if(SEG==16){IOSTA=0XB9;if(Data[2]&0x40)PIN5=1;else PIN5=0;PIN1=0;}//G3
}
補更新另一種:
//-------------------------------------------------------------------
#define SEG1_IN IOSTA |= C_PA7_Input
#define SEG1_H IOSTA &= ~C_PA7_Input; PORTAbits.PA7 = 1
#define SEG1_L IOSTA &= ~C_PA7_Input; PORTAbits.PA7 = 0
#define SEG2_IN IOSTA |= C_PA6_Input
#define SEG2_H IOSTA &= ~C_PA6_Input; PORTAbits.PA6 = 1
#define SEG2_L IOSTA &= ~C_PA6_Input; PORTAbits.PA6 = 0
#define SEG3_IN IOSTA |= C_PA4_Input
#define SEG3_H IOSTA &= ~C_PA4_Input; PORTAbits.PA4 = 1
#define SEG3_L IOSTA &= ~C_PA4_Input; PORTAbits.PA4 = 0
#define SEG4_IN IOSTA |= C_PA3_Input
#define SEG4_H IOSTA &= ~C_PA3_Input; PORTAbits.PA3 = 1
#define SEG4_L IOSTA &= ~C_PA3_Input; PORTAbits.PA3 = 0
#define SEG5_IN IOSTA |= C_PA2_Input
#define SEG5_H IOSTA &= ~C_PA2_Input; PORTAbits.PA2 = 1
#define SEG5_L IOSTA &= ~C_PA2_Input; PORTAbits.PA2 = 0
#define SEG_A 0X01
#define SEG_B 0X02
#define SEG_C 0X04
#define SEG_D 0X08
#define SEG_E 0X10
#define SEG_F 0X20
#define SEG_G 0X40
typedef struct
{
unsigned char flag;
unsigned char tab[4];
}seg_t;
//-------------------------------------------------------------------
//清除顯示
void SEG_Clear(void)
{
SEG1_IN; SEG2_IN; SEG3_IN;
SEG4_IN; SEG5_IN;
}
//led正極為1腳~5腳
void San_SEG1(void)
{
if(seg.tab[2] & SEG_B) SEG2_L;
if(seg.tab[2] & SEG_D) SEG3_L;
if(seg.tab[2] & SEG_F) SEG4_L;
if(seg.tab[2] & SEG_G) SEG5_L;
}
void San_SEG2(void)
{
if(seg.tab[1] & SEG_B) SEG3_L;
if(seg.tab[1] & SEG_D) SEG4_L;
if(seg.tab[1] & SEG_E) SEG5_L;
if(seg.tab[2] & SEG_A) SEG1_L;
}
void San_SEG3(void)
{
if(seg.tab[1] & SEG_A) SEG2_L;
if(seg.tab[1] & SEG_C) SEG4_L;
if(seg.tab[1] & SEG_F) SEG5_L;
if(seg.tab[2] & SEG_C) SEG1_L;
}
void San_SEG4(void)
{
if(seg.tab[0] & SEG_B) SEG3_L;
if(seg.tab[0] & SEG_C) SEG2_L;
if(seg.tab[1] & SEG_G) SEG5_L;
if(seg.tab[2] & SEG_E) SEG1_L;
}
void San_SEG5(void)
{
if(seg.tab[3] & SEG_A) SEG2_L;
}
void Seg_Num_Cal(void) // 1ms掃描
{
static uint16_t cntt = 0;
cntt ++;
if(cntt >= 250) //250 ms重新整理一次資料
{
cntt = 0;
seg.tab[0] = seg_table[hec];
seg.tab[1] = seg_table[dec];
seg.tab[2] = seg_table[sec];
seg.tab[3] = seg_table[0];
}
}
//顯示函數
void Display_Decode(void)
{
static uint8_t cnt = 1;
SEG_Clear();
Seg_Num_Cal();
switch(cnt)
{
case 1: SEG1_H;San_SEG1();break;
case 2: SEG2_H;San_SEG2();break;
case 3: SEG3_H;San_SEG3();break;
case 4: SEG4_H;San_SEG4();break;
case 5: SEG5_H;San_SEG5();break;
default: break;
}
cnt = (cnt >= 6) ? 0 : cnt + 1;
}
運作效果如下:
好了,大功告成!!!