一、課程設計目的和任務 實習目的任務是培養學生運用有關課程的基礎理論和技能解決實際問題,進一步提高學生本專業必要的基本技能、方法和創新能力的重要環節之一。通過綜合實習要使學生受到設計方法的初步訓練,能用文字、圖形和現代設計方法簡要、系統、正確地表達設計成果。 利用點陣LED屏向右滾動顯示“KST”:熟悉Keil軟件和STC-ISP-v4.80軟件的使用,單片機實驗箱及其開發環境;查閱點陣LED屏的工作原理,如何獲取圖形,結合原理圖了解芯片如何驅動點陣LED屏工作,了解LED點陣的基本結構,學習LED點陣的掃描顯示方法。 二、分析與設計 1.設計任務分析: 為了吸引觀眾增強顯示效果,可以有多種顯示模式,最簡單的顯示模式是靜態顯示。這里所說的“靜態顯示模式”不同于靜態驅動方式。與靜態顯示模式相對應,就有各種動態顯示模式,它們所顯示的圖文都是能夠動的。按照圖文運動的特點又可以分為閃爍、平移、旋轉、縮放等多種顯示模式。產生不同顯示模式的方法,并不意味著一定要重新編寫顯示數據,可以通過一定的算法從原來的顯示數據直接生成。例如,按順序調整行號,可以使顯示圖文產生上下平移;而順序調整列顯示數據的位置,就可以達到左右平移的目的;同時調整行列順序,就能得到對角線平移的效果。其它模式的數據刷新,也可找到相應的算法。不過當算法太復雜,太浪費時間的話,也可以考慮預先生成刷新數據,存儲備用。刷新的時間控制,要考慮運動圖形文字的顯示效果。刷新太慢,動感不顯著;刷新太快了,中間過程看不清。一般刷新周期可控制在幾十毫秒范圍之內。 而本實驗用KST-51開發板的點陣顯示KST向右移動的顯示設計。由于只控制8*8點陣顯示屏,故不需要擴展單片機的I/O接口。考慮到P0口需要接上拉電阻,使得電路較為復雜,因此利用單片機的P1口來控制點陣的行,用P2口控制點陣的列。 2。 設計方案論證: 本次設計向右移動顯示需要利用二維數組來實現,算法基本上和上下移動相似。二維數組,他的使用也很簡單。它的聲明方式是: 數據類型 數組名[數組長度 1][數組長度 2]; 與一維數組類似,數據類型是全體元素的數據類型,數組名是標識符,數組長度 1 和數組長度 2 分別代表數組具有的行數和列數。數組元素的下標一律從 0 開始。 例如:unsigned char a[2][3];聲明了一個具有 2 行 3 列的無符號字符型的二維數組 a。 二維數組的數組元素總個數是兩個長度的乘積。二維數組在內存中存儲的時候,采用行優先的方式來存儲,即在內存中先存放第 0 行的元素,再存放第一行的元素......,同一行中再按照列順序存放,剛才定義的那個 a[2][3]的存放形式就如下表所示。 a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] 二維數組的初始化方法分兩種情況,數組元素的數量可以小于數組元素個數,沒有賦值的會自動給 0。當數組元素的數量等于數組個數的時候, 如下所示: unsigned char a[2][3] = {{1,2,3}, {4,5,6}}; 或者是 unsigned char a[2][3] = {1,2,3,4,5,6}; 當數組元素的數量小于數組個數的時候,如下所示: unsigned char a[2][3] = {{1,2}, {3,4}}; 等價于 unsigned char a[2][3] = {1,2,0,3,4,0}; 而反過來的寫法 unsigned char a[2][3] = {1,2,3,4}; 等價于 unsigned char a[2][3] = {{1,2,3}, {4,0,0}}; 此外,二維數組初始化的時候,行數可以省略,編譯系統會自動根據列數計算出行數,但是列數不能省略。 要進行橫向做KST向右移動的動畫,先把需要的圖片畫出來,再逐一取模,如下圖所示,這個圖形共有30張圖片,通過程序每250ms改變一張圖片,就可以做出來動畫效果了。因為橫向移動的圖片切換時的字模數據不是連續的,所以要對30張圖片分別取模。 3.硬件設計及原理圖: (1)LED點陣總體框圖:點陣電路大體上可以分成微機本身的硬件、顯示驅動電路、控制信號電路三部分。控制電路部分包括一個51CUP和一些外圍電路。點陣包括顯示屏體、以及它的行和列的各個驅動電路。此顯示電路采用掃描方式進行顯示時,每行有一個行驅動器,從第一行開始,按順序依次對各行進行掃描。另一方面,根據各列鎖存的數據點亮相應的LED。 (2)電路原理圖:點陣顯示模塊的硬件電路設計如下圖所示: (3)點陣的認識 一個數碼管是8個LED組成,同理,一個8*8的點陣就是由64個LED小燈組成。如下圖: 在上圖中大方框外側的就是點陣LED的引腳圖,左側的8個引腳是接的內部LED的陽極,上側的8個引腳接的是內部LED的陰極。那么如果把9引腳置成高電平,13引腳置成低電平的話,左上角的那個LED小燈就會亮了。特別注意,控制點陣左側引腳的74HC138是原理圖上的U4,8個引腳自上而下依次由U4的Y0~Y7輸出來控制。 從圖中(本圖的LED陣列采用共陰的接法)可以看出,8×8點陣共需要64個發光二極管組成,且每個發光二極管是放置在行線和列線的交叉點上。要實現顯示圖形或字體,只需考慮其顯示方式,通過編程控制各顯示點對應LED陽極和陰極端的電平,就可以有效的控制各顯示點的亮滅。當采用按行掃描按列控制的驅動方式時,LED顯示屏8行的同名列共用一套列驅動器。行驅動器一行的行線連接到電源的一端,列驅動器一列的列線連接到電源的另一端。應用時還應在各條行線或列線上接上限流電阻。掃描中控制電路將行線的1到 8輪流接通高電位,使連接到各該行的全部LED器件接通正電源,但具體那一個LED導通,還要看它的負電源是否接通,這就是列控制的任務了。當對應的某一列置0電平,則相應的二極管就亮;反之則不亮。例如:如果想使屏幕左上角LED點亮,左下角LED熄滅的話,在掃描到第一行時,第一列的電位就應該為低,而掃描到第八行時第一列的電位就應該為高。這樣行線上只管一行一行的輪流導通,列線上進行通斷控制,實現了行掃描列控制的驅動方式。 (4)8X8點陣共由64個發光二極管組成,且每個發光二極管是放置在行線和列線的交叉點上,當對應的某一列置0電平,某一行置1電平,則相應的二極管就亮;8X8點陣的列輸入為C0~C7,行輸入為R0~R7,它們通過驅動電路74HC138接至發光二極管的陰極和陽極。要顯示某一個字母,首先要設計該字母的點陣形狀,編好行(或列)點陣碼數據,然后在單片機的控制下對點陣進行逐行(或列)掃描。在人眼的暫存效應下我們會看到完整的字形,從而實現了字母在點陣顯示屏上的輸出。 4.程序流程圖和源代碼清單: 流程圖如下: 源代碼: #include <reg52.h> sbit ADDR0 = P1^0; sbit ADDR1 = P1^1; sbit ADDR2 = P1^2; sbit ADDR3 = P1^3; sbit ENLED = P1^4; unsigned char code image[30][8] = { {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //動畫幀1 {0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE}, //動畫幀2 {0xFD,0xFE,0xFF,0xFF,0xFF,0xFF,0xFE,0xFD}, //動畫幀3 {0xFB,0xFD,0xFE,0xFF,0xFF,0xFE,0xFD,0xFB}, //動畫幀4 {0xF7,0xFB,0xFD,0xFE,0xFE,0xFD,0xFB,0xF7}, //動畫幀5 {0xEF,0xF7,0xFB,0xFD,0xFC,0xFB,0xF7,0xEF}, //動畫幀6 {0xDE,0xEE,0xF6,0xFA,0xF8,0xF6,0xEE,0xDE}, //動畫幀7 {0xBD,0xDD,0xED,0xF5,0xF1,0xED,0xDD,0xBD}, //動畫幀8 {0x7B,0xBB,0xDB,0xEB,0xE3,0xDB,0xBB,0x7B}, //動畫幀9 {0xF7,0x76,0xB7,0xD7,0xC7,0xB6,0x76,0xF7}, //動畫幀10 {0xEE,0xED,0x6F,0xAF,0x8F,0x6D,0xED,0xEE}, //動畫幀11 {0xDC,0xDB,0xDF,0x5F,0x1C,0xDB,0xDB,0xDC}, //動畫幀12 {0xB8,0xB7,0xBF,0xBF,0x38,0xB7,0xB7,0xB8}, //動畫幀13 {0x70,0x6F,0x7F,0x7E,0x71,0x6F,0x6F,0x70}, //動畫幀14 {0xE1,0xDE,0xFE,0xFD,0xE3,0xDF,0xDE,0xE1}, //動畫幀15 {0xC3,0xBD,0xFD,0xFB,0xC7,0xBF,0xBD,0xC3}, //動畫幀16 {0x87,0x7B,0xFB,0xF7,0x8F,0x7F,0x7B,0x87}, //動畫幀17 {0x0E,0xF7,0xF7,0xEF,0x1F,0xFF,0xF7,0x0F}, //動畫幀18 {0x1C,0xEF,0xEF,0xDF,0x3F,0xFF,0xEF,0x1F}, //動畫幀19 {0x38,0xDE,0xDE,0xBE,0x7E,0xFE,0xDE,0x3E}, //動畫幀20 {0x70,0xBD,0xBD,0x7D,0xFD,0xFD,0xBD,0x7D}, //動畫幀21 {0xE0,0x7B,0x7B,0xFB,0xFB,0xFB,0x7B,0xFB}, //動畫幀22 {0xC1,0xF7,0xF7,0xF7,0xF7,0xF7,0xF7,0xF7}, //動畫幀23 {0x83,0xEF,0xEF,0xEF,0xEF,0xEF,0xEF,0xEF}, //動畫幀24 {0x07,0xDF,0xDF,0xDF,0xDF,0xDF,0xDF,0xDF}, //動畫幀25 {0x0F,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF,0xBF}, //動畫幀26 {0x1F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F}, //動畫幀27 {0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //動畫幀28 {0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //動畫幀29 {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //動畫幀30 }; void main() { EA = 1; //使能總中斷 ENLED = 0; //使能U4,選擇LED點陣 ADDR3 = 0; TMOD = 0x01; //設置T0為模式1 TH0 = 0xFC; //為T0賦初值0xFC67,定時1ms TL0 = 0x67; ET0 = 1; //使能T0中斷 TR0 = 1; //啟動T0 while (1); } / * 定時器0中斷服務函數 * / void InterruptTimer0() interrupt 1 { static unsigned char i = 0; //動態掃描的索引 static unsigned char tmr = 0; //250ms軟件定時器 static unsigned char index = 0; //圖片刷新索引 TH0 = 0xFC; //重新加載初值 TL0 = 0x67; //以下代碼完成LED點陣動態掃描刷新 P0 = 0xFF; //顯示消隱 switch (i) { case 0 :ADDR2 = 0;ADDR1 = 0;ADDR0 = 0; i++; P0 = image[index][0];break; case 1 :ADDR2 = 0;ADDR1 = 0;ADDR0 = 1; i++; P0 = image[index][1];break; case 2 :ADDR2 = 0;ADDR1 = 1;ADDR0 = 0; i++; P0 = image[index][2];break; case 3 :ADDR2 = 0;ADDR1 = 1;ADDR0 = 1; i++; P0 = image[index][3];break; case 4 :ADDR2 = 1;ADDR1 = 0;ADDR0 = 0; i++; P0 = image[index][4];break; case 5 :ADDR2 = 1;ADDR1 = 0;ADDR0 = 1; i++; P0 = image[index][5];break; case 6 :ADDR2 = 1;ADDR1 = 1;ADDR0 = 0; i++; P0 = image[index][6];break; case 7 :ADDR2 = 1;ADDR1 = 1;ADDR0 = 1; i=0; P0 = image[index][7];break; default:break; } //以下代碼完成每250ms改變一幀圖像 tmr++; if(tmr>=250) //達到250ms時改變一次圖片索引 { tmr = 0; index++; if(index >=30) //圖片索引達到30后歸零 { index = 0; } } } |