張桂銘
摘 要:本項目教學難點是:1、定時器的應用;2、時、分、秒如何計數及怎樣顯示在數碼管上。本例沒有應用時鐘芯片,而是利用51系列單片機的定時器T1的自動重裝的方式1功能實現了精確的1ms和1s的定時基準的產生,其中1ms為最基本的定時時基,用于6位共陰動態LED的掃描刷新之外,還通過sCounter軟計數變量用于1000次的1ms計數產生1s 精確的秒定時時基,用于基本計數時鐘源。本例采用云龍單片機實驗板及C語言編程實現。
關鍵詞:數字電子鐘;精確定時;數碼管動態掃描;時鐘顯示的原理
在中職生單片機教學中需要突破的教學難點很多,而且涉及C語言編程,電子元件及模塊的應用,電路原理等多項問題,相對于中職生來說,在興趣的培養教學方面和簡單易懂的原則教學問題上都有著較大的挑戰,是比較值得鉆研的教學難題,固此在這闡述一下我在教學中遇到的問題,為進一步探討和簡化中職生單片機教法吸取經驗。
本例學生用到的實驗板原理圖如下:
一、數碼管圖塊
二、單片機圖塊
三、數碼管段選和位選控制的鎖存器圖塊
實例中單片機晶振選擇的頻工作頻率為12MHz,定時器的最小計數時間為1us,調試參考程序如下:
#include
sfr P0M1 = 0x95; //--- 新增的功能寄存器地址聲明 ---
sfr P0M0 = 0x96;
unsigned char code LEDSEG[] =
{0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00,};//--- 顯示0~9,A~F筆段代碼表 ---
unsigned char code LEDDIG[] =
{ 0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,};
unsigned char LEDBuffer[6];//--- 定義的顯示緩沖區 ---
unsigned char LEDPointer; //--- 定義的掃描計數變量 ---
unsigned int sCount; //--- 定義的秒計數器變量 ---
unsigned char Second; //--- 定義的秒變量 ---
unsigned char Minute; //--- 定義的分變量 ---
unsigned char Hour; //--- 定義的時變量 ---
void main(void)
{
P0M1 = 0x00; //--- 配置P5端口的P0.0~P0.7為推挽輸出模式 ---
P0M0 = 0xFF;
TMOD = 0x10; //--- 配置T1為定時模式,工作于方式1,16位裝載模式 ---
TH1 = (65536 - 1000) / 256; //--- 初始化T1定時1mS ---
TL1 = (65536 - 1000) % 256;
TR1 = 1; //--- 啟動T1工作 ---
ET1 = 1; //--- 使能T1中斷 ---
EA = 1; //--- CPU開中斷 ---
while(1)
{
}
}
sbit dula=P2^6;
sbit wela=P2^7;
//--------------------------------------------------------------------------------------
//--- 定時器T1溢出中斷服務程序 ---
void T1_ISR(void) interrupt 3
{
TH1 = (65536 - 1000) / 256; //--- 初始化T1定時1mS ---
TL1 = (65536 - 1000) % 256;
dula=1;
P0 = LEDSEG[LEDBuffer[LEDPointer]];//數碼管顯示段選碼
dula=0;
wela=1; //--- 顯示數字 ---
P0 = LEDDIG[LEDPointer];
wela=0; //--- 數碼管的位選段選擇 ---
LEDPointer++; //--- 動態掃描計數變量加1 ---
if(sizeof(LEDBuffer)==LEDPointer)LEDPointer = 0; //--- 所有數碼管掃描完,計數歸0 ---
sCount ++; //--- 秒計數變量加1 ---
if(1000 == sCount)
//--- 定時1秒時間到 ---
{
sCount = 0; //--- 秒計數變量清0
Second ++; //--- 秒變量加1 ---
if(60 == Second //--- 計滿60秒 ---
{
Second = 0; //--- 秒變量清0 ---
Minute ++; //--- 分變量加1 ---
if(60 == Minute)//--- 分計滿60 ---
{
Minute = 0; //--- 分變量清0 ---
Hour ++; //--- 時變量加1 ---
if(24 == Hour)
Hour = 0;
//--- 時計滿24則時變量清0 ---
}
}
LEDBuffer[5] = Second % 10;
//--- 秒變量裝顯示緩沖區 ---
LEDBuffer[4] = Second / 10;
LEDBuffer[3] = Minute % 10;
//--- 分變量裝顯示緩沖區 ---
LEDBuffer[2] = Minute / 10;
LEDBuffer[1] = Hour % 10;
//--- 時變量裝顯示緩沖區 ---
LEDBuffer[0] = Hour / 10;
}
}
其中定時器中斷初始化程序應完成如下工作:
1.對TMOD賦值,以確定T0和T1的工作方式。
2.計算初值,并將其寫入TH0、TL0或TH1、TL1。
3.使TR0或TR1置位,啟動定時/計數器定時或計數。
4.中斷方式時,則對IE賦值,開放中斷。
5.開總中斷。
TMOD = 0x10; //---對TMOD賦值,配置使用定時器T1,工作于方式1,因為單片機使用12MHz 晶振,機器周期為1us。
TH1 = (65536 - 1000) / 256; //定時器裝初值,1000us=1ms
TL1 = (65536 - 1000) % 256;
TR1 = 1; //--- 啟動定時器T1
ET1 = 1; //--- 使能定時器T1中斷
EA = 1; //--- CPU開中斷(開總中斷)
以上是定時器初始化在程序的編寫上的5個步驟, 在C語言程序的編寫中是按這5個對應的步驟實現的,其中對特殊功能寄存器的設置及特殊功能寄存器中相應位的開啟請注意查閱相關知識點。例于對TMOD的賦值
是對上面表格的各位的設置實現的。而開定時器是對下表TCON寄存器TR1的設置。
因此關于單片機定時器的應用我本人認為還要利用多媒體投影,邊復習前面的內容,邊編寫相應的程序,否則學生也許越聽越感覺困難,談不上突破這一難點了。
關于數字時鐘的時、分、秒如何計數并顯示在數碼管上也是本例的難點,例 LEDBuffer[5] = Second % 10;
LEDBuffer[4] = Second / 10;
//--- 秒變量裝顯示緩沖區 ---,是因為這是最后兩個數碼管,LEDBuffer[4]是秒的十分位,LEDBuffer[5]是秒的個位,所以個位要求余,十分位要求模得以實現。可讓學生反復實訓調試讓該難點得到突破。
單片機原理與應用是對中職學生來說是比較深奧的學科,需要反得實踐,反得學習編程和調試,并要結合電子器件的工作原理一步步學習,才能突破一個個難點,從而使知識技能獲得一定的進階。
參考文獻:
[1]MCS-51單片機C語言編程100例 孫安青編著;2、云龍單片機 網絡教程.