今天,偶忽然想起大二時學跑馬燈,當時一個個敲代碼最後運行出來跑馬燈的狀態,我現在都還記得,把代碼運行到實體上最後呈現的效果真是令人愉悅,話不多說,以下我將就跑馬燈製作流程跟大家分享一下。
1.題目:
跑馬燈
(1)基本需求
採用8254精決定時,LED的點亮法則為LED8-LED1,每個LED的點亮時間間隔由邏輯電平開關K1、K2與K3選擇。 K1的時間間隔為0.5S,K2的時間間隔為1.0S,K3的時間間隔為1.5S。當主機鍵盤按下任意鍵時停止示範。
(2)設計提示
採用8255的A口接LED燈,B口接邏輯電平開關K1、K2與K3 。在8254的中斷服務程序中完成對燈的控制,主程式偵測開關的變化,改變點亮LED燈的時間間隔。
(3)進一步設計需求
LED的點亮法則變成LED8-LED1-LED8
#2.分析:
#基本原理設計
步驟一:8255採用B口工作在方式0,進行輸入,獲取開關(註:為了便於進行課設操作,我們採用了K2, K1,K0以此來取代K3,K2,K1,實現的要求完全一致)K2K1K0的值,這裡會有三個值,分別是二進位編碼的100,010,001,即十進位的4,2,1,分別對應LED燈點亮的時間間隔1.5s,1.0s,0.5s。
#步驟二:8254採用工作方式三,產生一個固定頻率的方波,去不斷觸發中斷服務程序。在主程式中,取得8255的B口輸入值,根據輸入值給8254的計數器1寫入對應的初始值,在OUT1端就能得到一個固定頻率的方波訊號,這裡我們連接了一個K7所對應的燈,以此來進行驗證方波的產生以及通過燈閃爍的頻率可以大致判斷方波的頻率,來對應時間間隔1.5s,1.0s,0.5s。
#步驟三:8254產生的方波訊號輸出,連接到中斷介面IR10,用來利用方波訊號的頻率依照一定的時間間隔出發中斷服務程序。
步驟四:中斷服務程序依照8254的方波頻率,在一定的時間間隔內被載入執行。在中斷服務程序中實現對8255的A口輸出的改變,來控制LED7-LED0的閃爍變化,即實現跑馬燈。
#3.程式碼實作:
//****************************************************************************************************************** /* 实验接线: 8254: 片选信号CS接Y0;GATE0、GATE1级联接+5V;CLK0接1MHz;CLK1接OUT0; OUT1接k5(进行8254的方波显示); 8255: 片选信号CS接Y1;A口作为输出用排线接LED灯;PB0、PB1、PB2作为输入分别接K0、K1、K2; 中断: IR10接OUT1(中断控制程序控制LED灯的闪烁变化); */ //****************************************************************************************************************** //8255模块的设置 void init(void);//初始化 void ISR(void); int i=0,j=0; const unsigned short Port8255Base = 0x288; const unsigned char ControlWord8255 = 0x82; void init8255(void);// 8255初始化 //****************************************************************************************************************** //关于8254模块的设置 //通道0: 控制字00110110 -> 36H,即0x36,CLK0=1MHz,OUT0=0.01s,初值=F(clk)*T(out) 初始值:COUNT0=10000 //通道1: 控制字01110110 -> 76H,即0x76,CLK1=OUT0,初值=T1(out)/T1(clk) //当OUT1=0.5s,k3=0,k2=0,k0=1,1 初始值:COUNT1=50 //当OUT1=1.0s,k3=0,k2=1,k0=0,2 初始值:COUNT1=100 //当OUT1=1.5s,k3=1,k2=0,k0=0,4 初始值:COUNT1=150 void init8254(void);// 8254初始化 const unsigned short Port8254Base = 0x280, //计数器1端口地址为p8254Base+1,端口地址为p8254Base+3. counter0=10000; const unsigned char ControlWord8254ch0 = 0x36, ControlWord8254ch1 = 0x76; unsigned short counter1=100;//计数器初值 byte pData; unsigned char pdata=0x80; bool flag=true; //****************************************************************************************************************** //主函数 void main() { init(); init8254();// 8254初始化 init8255();//8255初始化 printf("\n start...\n"); while (!_kbhit()) { PortReadByte(Port8255Base + 1, &pData); //写入计数器1的初始值 if(pData==1){ //k0为1的情况,k2k1k0=001,即时间间隔为0.5秒 counter1=50; PortWriteByte(Port8254Base+1 , counter1%256); // 写计数器1计数初值低8位 PortWriteByte(Port8254Base+1 , counter1/256); // 写计数器1计数初值高8位 printf("=switch state:%x LED灯点亮间隔0.5秒=\n",pData); } if(pData==2){ //k1为1的情况,k2k1k0=010,即时间间隔为1.0秒 counter1=100; PortWriteByte(Port8254Base+1 , counter1%256); // 写计数器1计数初值低8位 PortWriteByte(Port8254Base+1 , counter1/256); // 写计数器1计数初值高8位 printf("=switch state:%x LED灯点亮间隔1.0秒=\n",pData); } if(pData==4){ //k2为1的情况,k2k1k0=100,即时间间隔为1.5秒 counter1=150; PortWriteByte(Port8254Base+1 , counter1%256); // 写计数器1计数初值低8位 PortWriteByte(Port8254Base+1 , counter1/256); // 写计数器1计数初值高8位 printf("=switch state:%x LED灯点亮间隔1.5秒=\n",pData); } sleep(3000);// delay 1s EnableIntr(); // 开中断,功能等效于汇编语言指令sti RegisterLocalISREx(ISR,10); // 加载中断服务程 printf("Wait for the switch state change...\n\n"); } _getch(); printf("\n Press any key over...\n"); //DisableIntr(); // 开中断,功能等效于汇编语言指令cli Cleanup(); } //中断服务程序,实现跑马灯的流水 void ISR(void) { if(flag) { _asm { ror pdata,1 //循环右移指令 } } else { _asm { rol pdata,1 //循环左移指令 } } j++; if(j==7) { flag = false; } if(j==14){ flag = true; j=0; } PortWriteByte(Port8255Base,pdata); } //机箱的初始化 void init(void) { if(!Startup()) // 加载实验平台I/O驱动程序 { printf("\n\n ERROR: Open Device Error!请打开实验箱电源\n"); _getch(); exit(0); // return to Windows } } //8254初始化 void init8254(void) { PortWriteByte(Port8254Base + 3, ControlWord8254ch0); // 写计数器0控制字 PortWriteByte(Port8254Base + 3, ControlWord8254ch1); // 写计数器1控制字 PortWriteByte(Port8254Base , counter0%256); // 写计数器0计数初值低8位 PortWriteByte(Port8254Base , counter0/256); // 写计数器0计数初值高8位 } //8255初始化 void init8255(void) { PortWriteByte(Port8255Base + 3, ControlWord8255); // 写8255控制字 PortWriteByte(Port8255Base,pdata); }登入後複製
【推薦課程:C影片教學】
以上是C語言筆記-基於C語言實現的流水跑馬燈的詳細內容。更多資訊請關注PHP中文網其他相關文章!