在許多嵌入式系統中提供某些形式的顯示設備用來向用戶傳遞信息。顯示器可以有一個簡單的指示燈到一個顯示復雜圖形的液晶顯示器。例如:我們常用的顯示器件有:LED燈、數碼管、點陣屏、LCD屏等。
在此我們來分析一下如何使用7段LED數碼管。
1、LED顯示器。
發光二極管,或者稱為LED,是一個報道體設備。當電流如圖1-1所示通過它的時候,可以產生可見的光。LED發光的亮度與通過LED的電流強度成正比。常見的LED燈可以產生紅光、黃光、綠光、藍光。而紅色是我們常見的LED燈。
圖1-1
2、數碼管
數碼管是多個LED燈組成的一個顯示器件。如圖1-2所示。從圖中我們可以看出,一個數碼管是由A、B、C、D、E、F、G、DP 8個LED燈組成的。其中A-G用來顯示數據,DP用來表示小數點,通常我們稱這樣的數碼管為7段式數碼管。圖1-3表明了這樣的數碼管與微控制器的連接方式。從圖中我們可以看出控制一個數碼管需要8個GPIO端口。那么,我們試想一下,如果系統中有多個數碼管,那將會非常浪費我們的GPIO端口。那有沒有一個節省端口的方法來擴展LED燈呢。圖1-4描述了這種方法。

圖1-2 圖1-3
圖1-4
圖1-4使用16個端口擴展了8個數碼管。我們來看一下怎么使用這8個數碼管。從上面的描述我們知道,如果要點亮一個LED燈,只需要在數碼管的A引腳和12引腳之間加一個電壓就行了,但是那個端口接電源的正極呢?如果A端口需要接電源的正極,那么這個數碼管就被稱為共陽極數碼管,反之,則稱為共陰極數碼管。圖中描述的是共陽極數碼管。
3、數碼管的動態掃描程序。
接下來我們來看一下怎么使用這個8個數碼管。在這里我們使用動態掃描的方法。動態掃描即第一個數碼管顯示一段時間后第二數碼管顯示,第二個數碼管顯示一段時間后第三個數碼管顯示……依次顯示。如果這個掃描的速度足夠快的話,我們肉眼就感覺不到是在一個一個顯示,而是整體一塊顯示的。那么這個掃描速度多少合適呢?一般我們的整體掃描時間要不大于20ms。我們這里有8個數碼管,那么我們1個數碼管的掃描時間設定為2.5ms。
本章我們以顯示0-7這8個數字來使用數碼管。
軟件編寫:
#include "includes.h"
void main(void)
{
INT8U i;
DispInit();
Timer0Init();
for(i=0;i<DISP_N_DIG;i++)
{
DispHex(i,i);
DispPoint(i);
}
while(1)
{
;
}
}
以上是main文件的內容,DispInit()這個函數初始化了數碼管所使用的IO端口,并且關閉所有的數碼管顯示。Timer0Init()這個函數初始化了定時器,設置定時時間為2.5ms。我們這里使用定時器來定時掃描數碼管。DispHex(i,i)這個函數設置了再哪個數碼管上顯示什么數,此函數能夠顯示十六進制的0-F。DispPoint(i)這個函數實現了顯示點,參數為哪個數碼管的點。
DISP_N_DIG表明了系統中數碼管的數量,這是一個宏定義,需要用戶自己修改。
更多詳情咨詢:曹老師 QQ:2859780203
李工:TEL:18948782707
#include "includes.h"
/*
*********************************************************************************************************
* LOCAL VARIABLES
*********************************************************************************************************/
static INT8U DispDigMsk; /* Bit mask used to point to next digit to display */
static INT8U DispSegTbl[DISP_N_DIG]; /* Segment pattern table for each digit to display*/
static INT8U DispSegTblIx; /* Index into DispSegTbl[] for next digit to display */
/*
*********************************************************************************************************
* HEXADECIMAL to SEVEN-SEGMENT conversion table
* a
* ------
* f | | b
* | g |
* Note: The segments are mapped as follows: ------
* e | | c
* a b c d e f g h | d |
* -- -- -- -- -- -- -- -- ------ .h
* B0 B1 B2 B3 B4 B5 B6 B7
*********************************************************************************************************
*/
INT8U code DispHexToSegTbl[] = { /* HEXADECIMAL to SEVEN-SEGMENT conversion*/
0xC0, /* '0' */
0xF9, /* '1' */
0xA4, /* '2' */
0xB0, /* '3' */
0x99, /* '4' */
0x92, /* '5' */
0x82, /* '6' */
0xF8, /* '7' */
0x80, /* '8' */
0x90, /* '9' */
0x88, /* 'A' */
0x83, /* 'B', Actually displayed as 'b' */
0xC6, /* 'C' */
0xA1, /* 'D', Actually displayed as 'd' */
0x86, /* 'E' */
0x8E /* 'F' */
};
void DispClrScr (void);
void DispInit (void);
void DispStatClr (INT8U dig, INT8U numbit);
void DispStatSet (INT8U dig, INT8U numbit);
void DispOutDig (INT8U msk);
void DispOutSeg (INT8U seg);
void DispInitPort (void);
void DispHex(INT8U dig,INT8U number);
void DispPoint(INT8U dig);
/*$PAGE*/
/*
*********************************************************************************************************
* CLEAR THE DISPLAY
*
* Description: This function is called to clear the display.
* Arguments : none
* Returns : none
*********************************************************************************************************
*/
void DispClrScr (void)
{
INT8U i;
for (i = 0;i < DISP_N_DIG;i++)
{
/* Clear the screen by turning OFF all segments */
DispSegTbl = DISP_CRUSH_SEG;
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* DISPLAY DRIVER INITIALIZATION
*
* Description : This function initializes the display driver.
* Arguments : None.
* Returns : None.
*********************************************************************************************************
*/
void DispInit (void)
{
DispInitPort(); /* Initialize I/O ports used in display driver*/
DispDigMsk = (1<<(DISP_N_DIG-1));
DispSegTblIx = 0;
DispClrScr(); /* Clear the Display*/
}
/*$PAGE*/
/*
*********************************************************************************************************
* DISPLAY NEXT SEVEN-SEGMENT DIGIT
*
* Description: This function is called by DispMuxISR() to output the segments and select the next digit
* to be multiplexed. DispMuxHandler() is called by DispMuxISR() defined in LED_IA.ASM
* Arguments : none
* Returns : none
* Notes : - You MUST supply the code to clear the interrupt source. Note that with some
* microprocessors (i.e. Motorola's MC68HC11), you must clear the interrupt source before
* enabling interrupts.
*********************************************************************************************************
*/
void DispMuxHandler (void)
{
DispOutSeg(DISP_CRUSH_SEG); /*TurnOFFsegmentswhilechanging digits*/
DispOutDig(DispDigMsk); /* Select next digit to display */
DispOutSeg(DispSegTbl[DispSegTblIx]); /* Output digit's seven-segment pattern */
if (DispSegTblIx == (DISP_N_DIG - 1)) { /* Adjust index tonextseven-segmentpattern*/
DispSegTblIx = 0; /* Index into first segments pattern*/
DispDigMsk = (~(1<<(DISP_N_DIG-1)));/*0x80willselectthefirst seven-segment digit */
}
else
{
DispSegTblIx++;
DispDigMsk = ~DispDigMsk;
DispDigMsk >>= 1; /* Select next digit */
DispDigMsk = ~DispDigMsk;
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* CLEAR STATUS SEGMENT
*
* Description: This function is called to turn OFF a single segment on the display.
* Arguments : dig is the position of the digit where the segment appears (0..DISP_N_DIG-1)
* bit is the segment bit to turn OFF (0..7)
* Returns : none
*********************************************************************************************************
*/
void DispStatClr (INT8U dig, INT8U numbit)
{
DispSegTbl[dig] &= ~(1 << numbit);
}
/*
*********************************************************************************************************
* SET STATUS SEGMENT
*
* Description: This function is called to turn ON a single segment on the display.
* Arguments : dig is the position of the digit where the segment appears (0..DISP_N_DIG-1)
* bit is the segment bit to turn ON (0..7)
* Returns : none
*********************************************************************************************************
*/
void DispStatSet (INT8U dig, INT8U numbit)
{
DispSegTbl[dig] |= 1 << numbit;
}
/*$PAGE*/
/*
*********************************************************************************************************
* DISPLAY HEX NUMBER ON SEVEN-SEGMENT DISPLAY
*
* Description: This function is called to display hex number on the seven-segment display.
* Arguments : dig is the position of the first digit where the string will appear:
* 0 for the first seven-segment digit.
* 1 for the second seven-segment digit.
* . . . . . . .
* . . . . . . .
* DISP_N_SS - 1 is the last seven-segment digit.
* number is the number to display
* Returns : none
* Notes : - Not all ASCII characters can be displayed on a seven-segment display. Consult the
* ASCII to seven-segment conversion table DispASCIItoSegTbl[].
*********************************************************************************************************
*/
void DispHex(INT8U dig,INT8U number)
{
DispSegTbl[dig] = DispHexToSegTbl[number];
}
void DispPoint(INT8U dig)
{
DispStatClr(dig,7);
}
/*$PAGE*/
/*
*********************************************************************************************************
* I/O PORTS INITIALIZATION
*
* Description: This is called by DispInit() to initialize the output ports used in the LED multiplexing.
* Arguments : none
* Returns : none
* Notes : 74HC573 8 bit latches are used for both the segments and digits outputs.
*********************************************************************************************************
*/
void DispInitPort (void)
{
outp(DISP_PORT_SEG, DISP_CRUSH_SEG); /* Turn OFF segments*/
outp(DISP_PORT_DIG, DISP_CRUSH_DIG); /* Turn OFF digits*/
}
/*
*********************************************************************************************************
* DIGIT output
*
* Description: This function outputs the digit selector.
* Arguments : msk is the mask used to select the current digit.
* Returns : none
*********************************************************************************************************
*/
void DispOutDig (INT8U msk)
{
outp(DISP_PORT_DIG, msk);
}
/*
*********************************************************************************************************
* SEGMENTS output
*
* Description: This function outputs seven-segment patterns.
* Arguments : seg is the seven-segment pattern to output
* Returns : none
*********************************************************************************************************
*/
void DispOutSeg (INT8U seg)
{
outp(DISP_PORT_SEG, seg);
}
以上是smg.c文件中的內容。主要實現了數碼管的顯示,操作。
#include "includes.h"
//Init timer0 2.5ms
void Timer0Init(void)
{
TMOD |= 0x01;
TH0 = 0xec;
TL0 = 0x77;
TR0 = 1;
TF0 = 0;
EA = 1;
ET0 = 1;
}
void timer0() interrupt 1
{
EA = 0;
TH0=0xec;
TL0=0x77;
DispMuxHandler();
EA = 1;
}
以上是timer.c文件中的程序。系統使用定時器0定時2.5ms。當中斷到達時中斷服務函數調用DispMuxHandler()。在這個函數中把數碼管現存中的內容全部顯示到數碼管上。這個函數首先關閉所有的數碼管,然后選擇要顯示的數碼管,把要顯示的數據顯示到對應的IO口上。我們應用程序只需要改變現存中的內容就可以把數據顯示到數碼管上。
更多詳情咨詢:曹老師 QQ:2859780203
李工:TEL:18948782707
函數名稱 | 函數作用 | 使用者 | DispClrScr | 清屏數碼管 | 用戶 | DispInit | 數碼管顯示的初始話 | 用戶,上電后必須調用1次 | DispMuxHandler | 把數碼管顯存中的數據顯示到數碼管上 | 定時器中斷服務函數(用戶不能調用) | DispStatClr | 關閉某一個數碼管的顯示 | DispMuxHandler | DispStatSet | 開啟某一個數碼管的顯示 | DispMuxHandler | DispHex | 在某個數碼管上顯示十六進制數據 | 用戶 | DispPoint | 在某個數碼管上顯示點 | 用戶 | DispInitPort | 初始化數碼管占用的端口 | DispInit | DispOutDig | 選中某一位數碼管 | 定時器中斷服務函數(用戶不能調用) | DispOutSeg | 選中某一段數碼管 | 定時器中斷服務函數(用戶不能調用) |
|