用51做的16*16點陣顯示螢幕(ptotues模擬)
阿新 • • 發佈:2018-12-19
第一次寫部落格,來試試水。正好前幾天搞一個微控制器的模擬拿來分享
16*16的點陣顯示屏,按下開始按鍵後,在顯示屏上輪流顯示“字串1”字樣。再次按下開始按鍵後,顯示屏上無任何顯示。按下切換後能顯示“字串2”字樣等(可以設計很多切換字串)。且啟動消隱的過程顯示清晰無異樣。
/* ***************************************************** */ // 作 者:lk 系統時鐘 : 11.0592MHZ // 版 本:V1.2 生成日期 : 2018-12-01 // 簡單描述 : 用8255和74ls154驅動16*16點陣, // 字幕軟體:Copyleft採用縱向取模,位元組倒序,字型:宋體12 //switch按鍵切換字元組,start按鍵用來啟動和關閉點陣顯示。 /* ***************************************************** */ #include<reg51.h> #include<intrins.h> #include<absacc.h> #define uchar unsigned char #define uint unsigned int //PA,BP,PC埠地址及命令定義 按鍵定義 #define PA XBYTE[0x0000] #define PB XBYTE[0x0001] #define PC XBYTE[0x0002] #define COM XBYTE[0x0003] sbit sz_anji = P3^3; //切換按鍵 sbit ks_anji = P3^2; //開關按鍵 sbit switch_154 = P3^0; //74ls154譯碼開關 uchar shuzu=0; //當前陣列號 uchar BR=0; //跳出訊號 uint qh=0; //切換陣列按鍵變數 uchar dz_start = 0; //啟動標誌位 uchar data Row_Data[32]; //傳送4片LED屏資料 uchar code Word_Set1[][32]= //待顯示文字的點陣 { {/*-- 文字: 電 --*/ /*-- 宋體12; 此字型下對應的點陣為:寬x高=16x16 --*/ 0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x88,0xF8,0x00,0x00,0x00, 0x00,0x00,0x1F,0x08,0x08,0x08,0x08,0x7F,0x88,0x88,0x88,0x88,0x9F,0x80,0xF0,0x00}, {/*-- 文字: 信 --*/ /*-- 宋體12; 此字型下對應的點陣為:寬x高=16x16 --*/ 0x00,0x80,0x60,0xF8,0x07,0x00,0x04,0x24,0x24,0x25,0x26,0x24,0x24,0x24,0x04,0x00, 0x01,0x00,0x00,0xFF,0x00,0x00,0x00,0xF9,0x49,0x49,0x49,0x49,0x49,0xF9,0x00,0x00}, /*省略一部分字元程式碼*/}; void delay(uint x) //延時函式 { uchar i; while(x--) for(i=0; i<120; i++); } void clear(void) //清屏函式 { switch_154 = 1; //關閉列譯碼器 PA = 0xff; //清零上8行資料 PB = 0xff; //清零下8行資料 switch_154 = 0; //開啟列譯碼器 } void switch_sz(uint xh) //切換按鍵判斷函式 { uint x; for(x=0;x<xh;xh++) { if(!sz_anji) { delay(10); //按鍵消抖 if(!sz_anji) { TR0 = 0; //關閉定時器不再重新整理 clear(); //消隱 qh++; shuzu=qh%3; //獲取當前陣列號 BR=1; while(!sz_anji); //按鍵彈起後 } } } } //定時器0中斷,在主程式的延時時期內以1ms的間隔動態顯示每列資料 void led_disply_control() interrupt 1 { uchar i; TH0 = ~1000/256; TL0 = ~1000%256; switch_154 = 1; //關閉列譯碼器 i = (P1+1) & 0X0F; //列號遞增 PA = ~Row_Data[i]; //傳送上8行資料 PB = ~Row_Data[i+16]; //傳送下8行資料 P1 = i; //列譯碼 switch_154 = 0; //開啟列譯碼器 } //按鍵外部中斷處理程式 void Key_Down() interrupt 0 { TR0 = 0; //關閉定時器重新整理 EX0 = 0; //關閉外部中斷 delay(10); //按鍵消抖 if(!ks_anji) //按鍵按下 dz_start = !dz_start; //改變啟動狀態位 TR0 = 1; //開啟定時器繼續重新整理 EX0 = 1; //開啟外部中斷 } void main () { uchar i,K; //重新整理變數 uchar qs,mw; //陣列起始,末尾位 //8255工作方式選擇PA,PB均輸出,工作方式0 COM = 0x80; TMOD = 0x01; TH0 = ~1000/256; TL0 = ~1000%256; IT0 = 1; //下降沿觸發 IE = 0x83; P1 = 0xFF; sz_anji = 1; while(1) { if(dz_start) //是否start { BR=0; switch(shuzu) //陣列起始和末尾值 { case 0: qs=0; mw=5; break; case 1: qs=5; mw=13; break; case 2: qs=13; mw=15; break; default: qs=0; mw=5; break; } for(K=qs;K<mw;K++) //顯示一串字元 { if(BR) break; //如果按鍵切換了就跳出重取緩衝值 for(i=0;i<32;i++) Row_Data[i]=Word_Set1[K][i]; //裝入一個字元的緩衝值 while(!dz_start) //啟動定時器顯示時檢測start按鍵,無start一直在這; clear(); //點陣消隱,緩衝裝空值 TR0 = 1; //使能定時器中斷 switch_sz(300); //按鍵一直在判斷,大約耗時0.5s。此時定時器重新整理一個字元 TR0 = 0; P2=0xff; //點陣消隱 } } } }
註釋寫的很清楚了,只是程式碼是由原來一個8*8的靜態輸出的程式碼改的沒花多少重新搞重新整理演算法(之前實驗的動態重新整理protues跑起來會卡)
下面是protues硬體圖: