實驗(四)6位數七字節顯示
History Key
- New content
Removed content
Recent Versions
Choose two versions to compare, or click the link to view it.
(教學教材內容保留所有版權~欲轉載請註明出處~謝謝)
實驗(四) 6位數7字節顯示單元
實驗目的:
本節在實現6位數7字節顯示單元模組。
實驗一:
7字節單8顯示上數
實驗二:
6位數顯示上數
實驗三:
6位數碼表設計,按下SW2則數字歸零,按下SW1啟動計數,再按下SW1停止計數。顯示範圍分鐘、秒數、百分之1秒
I/O腳位定義:
/// SEG_COM0 equ pf.0
/// SEG_COM1 equ pf.1
/// SEG_COM2 equ pf.2
/// SEG_COM3 equ pf.3
/// SEG_COM4 equ pf.4
/// SEG_COM5 equ pf.5
/// SEG_PORT equ ph;
模組函式規畫:
/// 單1個七字節
/// ======== START Public 函式 ========
void Initial_SEG7( void ); /// 初始化 IO
void SEG7_SetS1( void ); /// 七字節單一輸出
/// ======== END Public 函式 ========
/// 6位數的七字節
/// ======== START Public 函式 ========
void Initial_SEG7( void ); /// 初始化 IO
void SEG7_Control( void ); /// 七字節 6 個位數作掃描控制
void SEG7_SetS1( void ); /// 設定 S1 字節的值為 a,對應 8 BITS 腳位
void SEG7_SetS2( void ); /// 設定 S2 字節的值為 a,對應 8 BITS 腳位
void SEG7_SetS3( void ); /// 設定 S3 字節的值為 a,對應 8 BITS 腳位
void SEG7_SetS4( void ); /// 設定 S4 字節的值為 a,對應 8 BITS 腳位
void SEG7_SetS5( void ); /// 設定 S5 字節的值為 a,對應 8 BITS 腳位
void SEG7_SetS6( void ); /// 設定 S6 字節的值為 a,對應 8 BITS 腳位
/// ======== END Public 函式 ========
模組函式設計:
操作函式設計:...............略。
上列函式規畫有二種,前一種是只有單一個七字節顯示的時候的函式規畫方式,此時的七字節就如同8顆LED的顯示單元一樣,只是單純的設定LED埠的狀態,程式設計非常簡單。
第二種則是同時要顯示6位數的七字節時的函式規畫方式,此時由於硬體規畫是採同COM點掃描的方式來顯示6個七字節的內容(也必須如此,否則會需要大量的I/O腳位),因此我們需要一個控式函式來作COM點掃描的動作,也就是SEG7_Control()。
系統在每次叫用SEG7_Control()的時候,模組就要負責去切換到某一個COM點對七字節埠作輸出,並且把其它COM點清除,系統不斷的叫用控制函式,模組就不斷的進行COM點的切換,來達到掃描的目的。
這裡用到的技巧也是模組設計的時候經常會用到的方法,把模組要完成的工作,分階段來完成,藉著系統的調用來達到分時處理的目的,同樣的技巧也可以再擴充,把模組設計成類似狀態機,把系統調用當成一個GLOBAL的TIMER,每次的調用就會讓模組「運作起來」並且「流向」不同的狀態,有點OS的味道。
控制函式的實作:
控制函式也很容易實現(因為我們規畫的目標明確),只需要在不同的時間對不同的COM點作輸出即可。
void SEG7_Control( void ) /// 七字節掃描控制
{
SEG_COM0 = 1;
SEG_COM1 = 1;
SEG_COM2 = 1;
SEG_COM3 = 1;
SEG_COM4 = 1;
SEG_COM5 = 1;
switch( seg7_index )
{
case 0:
SEG_PORT = seg7_s1;
SEG_COM0 = 0;
break;
case 1:
SEG_PORT = seg7_s2;
SEG_COM1 = 0;
break;
case 2:
SEG_PORT = seg7_s3;
SEG_COM2 = 0;
break;
case 3:
SEG_PORT = seg7_s4;
SEG_COM3 = 0;
break;
case 4:
SEG_PORT = seg7_s5;
SEG_COM4 = 0;
break;
case 5:
SEG_PORT = seg7_s6;
SEG_COM5 = 0;
break;
}
if( seg7_index < MAX_SEG7_COM )
seg7_index++;
else
seg7_index = 0;
}
實驗實作:
實驗一:
7字節單8顯示上數。
略。
實驗二:
6位數顯示上數。
底下是系統主程序,其實就是定時去調用控制函式,也就是作七字節掃描。
void FPPA0 (void)
{
/// 初始化...略
while (1)
{ /// 多位數七字節控制 LOOP
SEG7_Control();
delay 250;
delay 250;
}
}
在這裡我們看到delay這個指令,目的在控制掃描頻率,掃描頻率不同會影響七字節顯示的亮度,太慢的掃描頻率亦可能會造成七字節閃爍的情形。
至於要顯示的內容,只要去呼叫SEG7_SetS1()~SEG7_SetS6() 作設定即可。
範例程式是很簡單的用一個timer中斷來累加一些變數,再把這些變數設定到各別對應的七字節至於timer中斷的設定方式請參考「FPPA教學簡報」第四章「FPPA程式設計」,C語言代碼如下:
void Initial_Timer()
{
/// 100= internal high RC, 11=(ClockSource/64)=4us/T, 111=bit15,(32768*Timer)
t16m = 0b10011111;
t16reset = 32768-2500; /// 2500*4us = 10000us = 10ms
stt16 t16reset ; /// Restart timer tick
}
void Initial_ISR()
{
intrq = 0b00000000; /// clear interrpt reqest register
inten = 0b00000100; /// bit-2: Timer16
engint; /// Enable Interrupt
}
這邊同時展示了FPPA查表指令的用法:
/// 使用組合語言... add a, la@Seg7DigitCode; mov lb@digitIndex, a; mov a, ha@Seg7DigitCode; mov hb@digitIndex, a; addc hb@digitIndex; ldtabl digitIndex;
/// 使用Mini-C語言... digitIndex = Seg7DigitCode + a; a = *digitIndex$L;
Seg7DigitCode: dc 0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110, 0b01101101, 0b01111101, 0b00100111, 0b01111111, 0b01101111;
Seg7DigitCode標記著資料的位址,也就是資料在ROM中的位址,程式執行的時候把一個指標指到這個位址,然後再加上一個OFFSET下標指到表中的某一筆資料。
顯然Mini-C的用法比較簡潔一點,不過要特別注意這並非傳統C的用。
實驗三:
6位數碼表設計,按下SW2則數字歸零,按下SW1啟動計數,再按下SW1停止計數。顯示範圍分鐘、秒數、百分之1秒。
這個實驗便能很完整的體驗出模組整合的優勢,系統設計師只要拿到這些己經設計好的模組「SW1」、「SW2」、「Seg76c」看一下各模組標頭檔(.h)的說明,就能很快的整合出系統所要求的功能,程式設計的時候就像是一個建築師,大架構出來了,再把各個輸入、輸出、剌激、反應的神經管線連接好就OK了。
同時我們也看到了FPPA多核的優勢,由於有多核可用,且一般的系統會整合到的模組其實也不多(當然也是要看系統複雜度),我們可以把各個模組的控制函式,直接分配給不同的核心來運行處理,簡化了整合的複雜度同時也提升了系統的穩定度,因此系統設計時要著眼的就只剩下模組之間的交互運作的邏輯問題以及核心間同步的問題。
void FPPA0 (void)
{
/// 初始化...略
while (1)
{ /// 多位數七字節控制 LOOP
SEG7_Control();
delay 250;
delay 250;
}
}
void FPPA1 (void)
{
while (1)
{ /// 按鈕控制 LOOP
SW1_Control();
SW2_Control();
}
}