最后補(bǔ)充一些總結(jié)性的東西:
失敗:這次比賽看起來我們是敗在那臺(tái)刻板機(jī)上面。但實(shí)際這只是一方面而已,我們更多敗在時(shí)間的分配不合理、早期合作的積極性不足以及功底不夠之上。
所得:這次比賽,算是一次很好的鍛煉了。我們從接手一個(gè)項(xiàng)目開始到設(shè)計(jì)方案到元器件的選用到程序的設(shè)計(jì)再到硬件和軟件的調(diào)試(未能全部調(diào)試,因?yàn)榘遄佣紱]做出來,只在另一個(gè)開發(fā)板上調(diào)試了部分程序),這都是很好的項(xiàng)目經(jīng)驗(yàn)!我在這二十幾天里也給自己補(bǔ)充了不少的模電數(shù)電知識(shí)....我認(rèn)為得獎(jiǎng)并不是我們最需要的,我們最需要的是使自己的水平得到提高。
展望:我們這個(gè)小組從原來的1個(gè)人變成兩個(gè)人,再變成4個(gè)人,現(xiàn)在又多了3個(gè)(可惜原來的兩個(gè):周勛、永慶好像學(xué)不下去了)。剩下的童鞋們還有:宇曦、曉光、文迪、志安、當(dāng)然還有我也是...志安是最新加入的。希望大家能好好發(fā)展!以后有什么項(xiàng)目什么比賽都能好好配合! 光有程序,沒有硬件連接的示意難以看懂呢:先上圖
LED驅(qū)動(dòng)板PCB:
////////////////////////////////////文件 myself.h/////////////////////////////////////////////////////////////// #include<reg52.h> #define writting 0x01 //寫字 #define erasure 0x00 //擦除 #define key_enter 1 //確定 #define key_esc 2 //退出/取消 #define key_words_modle 3 //多字連寫 #define key_light_level 4 //屏幕亮度級(jí)別 #define key_sleep_time 5 //超時(shí)待機(jī)時(shí)間設(shè)定 #define key_fanxian 6 //反顯操作 #define key_cachu 7 //擦除操作 #define key_tuoyi 8 //對(duì)象拖移 #define key_all_screen_del 9 //整屏擦除 #define key_tuoyi_quxiao 10 //對(duì)象拖移內(nèi)容選定后取消 #define key_crease 11 //數(shù)據(jù)加一(待機(jī)時(shí)間、亮度級(jí)別) #define key_decrease 12 //數(shù)據(jù)減一 //24M晶振 #define _TH0_TL0_ (65536 - 50000) #define HI (_TH0_TL0_ / 256) //給高8位賦值 #define LO (_TH0_TL0_ % 256) //給低8位賦值 #define M 40 //(2000/50)1秒要50個(gè)中斷的累計(jì) typedef char (*size)[4]; //把size定義為一個(gè)指向32X4的二維數(shù)組首地址的類型 typedef unsigned char uchar; extern size point[4]; extern uchar LED_CODE[5][4]; extern uchar LED_ROW,LED_LINE; extern uchar ROW_TEMP; extern uchar KEYS; extern uchar li_level; extern uchar N; extern uchar men_lig; extern uchar sleepmin; extern uchar min,sec; extern uchar xdata LEDDATA0[32][4],LEDDATA1[32][4],LEDDATA2[32][4],LEDDATA3[32][4],LEDDATA4[32][4]; void LED_GAI(uchar obj_mem[32][4],uchar opera,uchar LED_ROW,uchar LED_LINE ); void one_word(uchar dat_addr[32][4],uchar caozuo); void sys_init(); void one_word(uchar dat_addr[32][4],uchar caozuo); uchar getkey(); void lightlev(uchar showing[32][4]); void sleeptim(uchar showing[32][4]); void fanxian(uchar LEDDATA[32][4]); void delay_us(int us); void LEDcachu(uchar LEDDATA[32][4]); void obj_move(uchar led_data[32][4]); void fourwords(); void fou_show(); void dis_play(uchar show_obj[32][4]); void del_all(uchar obj[32][4]); void shu_ma_g(); //void daiji(); void digital_show(uchar row,uchar line); void output(); void input(uchar word); void saomiao(); void light(); //void input(uchar word);; ////////////////////////////////////END/////////////////////////////////////////////////////////////// ////////////////////////////////////文件 main.c/////////////////////////////////////////////////////////////// //************************************************************************* //作品:LED書寫點(diǎn)陣顯示屏 //作者:陳宇曦 黃曉光 唐敏健 //時(shí)間:2010/04~2010/05 //主控器:IAP12C5A62S2(STC12系列) //晶振:24MHZ //功能模塊分析: // 系統(tǒng)共有4個(gè)功能模塊: // 1、點(diǎn)亮與畫亮 (即寫字功能、開機(jī)默認(rèn)) // 2、多字連寫 // 3、自動(dòng)調(diào)光功能 // 4、超時(shí)待機(jī)功能 // 而對(duì)上述功能的 操作 有: // 1、反顯(可對(duì)于功能1和功能2模塊操作) // 2、整屏擦除(可對(duì)于功能1和功能2模塊操作) // 3、光筆擦除(可對(duì)于功能1和功能2模塊操作) // 4、對(duì)象拖移(可對(duì)于功能1和功能2模塊操作) // 5、寫字存儲(chǔ)(可對(duì)于功能1和功能2模塊操作)PS:由于時(shí)間問題, // 而且這個(gè)功能題目沒要求,暫先擱置 // 6、自動(dòng)調(diào)光參數(shù)設(shè)置,即調(diào)整使用者喜好的屏幕亮度級(jí)別, // 而同時(shí),系統(tǒng)會(huì)在這個(gè)級(jí)別內(nèi)對(duì)LED屏根據(jù)環(huán)境光強(qiáng)的變化而自動(dòng)調(diào)光 // 7、超時(shí)待機(jī)時(shí)間設(shè)定 // //聯(lián)系人:唐敏健(15014225360/380467850@qq.com) // //**************************************************************************** #include"myself.h" #include<reg52.h> #include<intrins.h> uchar LED_CODE[5][4]= /*LED燈的列編碼,每個(gè)LED燈的編碼為5位數(shù)據(jù)(0到2^5),每次要給32列LED燈同步輸出1位數(shù)據(jù),共5次。*/ { /*這些數(shù)據(jù)由于操作頻率高,故把它們定義在內(nèi)部RAM中*/ 0X00,0X00,0XFF,0XFF, 0X00,0XFF,0X00,0XFF, 0X0F,0X0F,0X0F,0X0F, 0X33,0X33,0X33,0X33, 0X55,0X55,0X55,0X55 }; uchar LED_ROW,LED_LINE,N; //存放當(dāng)前光筆坐標(biāo)的全局變量,系統(tǒng)初始化時(shí)把它設(shè)為99(任意一個(gè)大于32的數(shù)) uchar ROW_TEMP; //掃描時(shí)行坐標(biāo)的”臨時(shí)變量“(全局變量),以便進(jìn)入中斷后,LED_ROW=ROW_TEMP,保存起來 uchar KEYS=0; //存儲(chǔ)按下的按鍵編號(hào),初始化為0, uchar li_level=10; uchar men_lig=10; uchar min=0,sec=0; uchar sleepmin=5; //默認(rèn)超時(shí)5分鐘待機(jī) //sbit pen_key=P3^3; //光筆按鍵P3^3是INT0,所以要在初始化階段關(guān)閉外部中斷0 //sbit OUT_EN =P1^7; uchar xdata LEDDATA0[32][4],LEDDATA1[32][4],LEDDATA2[32][4],LEDDATA3[32][4],LEDDATA4[32][4]; //存放整屏數(shù)據(jù)的數(shù)組,屏幕數(shù)據(jù)量為32/8*32字節(jié) size point[4]; //二維數(shù)組的指針數(shù)組 void delay_us( int us) { while(us>0) { _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();//24條空操作指令為1US,現(xiàn)在為20條 us--; } } void main() { uchar light_T; N=3; light_T=0; relay=0; point[0]=LEDDATA1;point[1]=LEDDATA2; point[2]=LEDDATA3;point[3]=LEDDATA4; //********************** //定時(shí)器1初始化 TL0 = _TH0_TL0_ % 256; TH0 = _TH0_TL0_ / 256 + (char)CY; TR0 = 1; //***************** //sys_init(); //系統(tǒng)初始化,把4個(gè)數(shù)組首地址放進(jìn)point[4]中去 while(1) { one_word(LEDDATA0,writting); //掃描一個(gè)點(diǎn)并予以顯示 KEYS=getkey(); //AD掃描按鍵,其實(shí)按鍵掃描1秒鐘內(nèi)進(jìn)行10次足矣,不必跟隨這個(gè)dis_play()做至少20次的掃描, //因?yàn)槿说氖植豢赡芤幻雰?nèi)按鍵超過10次。 //調(diào)試時(shí)如果發(fā)現(xiàn)LED屏對(duì)光筆的反應(yīng)比較慢,則需要修改getkey()在一秒內(nèi)的時(shí)間占用比例, //即也意味著getkey()在一秒內(nèi)的執(zhí)行次數(shù)?梢赃@樣:設(shè)定一個(gè)計(jì)數(shù)器,每dis_play()一次就+1,初值 //為0,到了1就清零,并且調(diào)用get_key(),否則不執(zhí)行g(shù)et_key(). if(KEYS) //getkey()檢測到按鍵按下就返回按鍵的值,沒按鍵按下就返回0 { switch(KEYS) { case key_enter : break; //”確定“在這里沒意義 case key_esc : break; //沒得退出,已經(jīng)是最底的一層了 case key_words_modle : fourwords();break; //進(jìn)入多字連寫功能 case key_light_level : lightlev(LEDDATA0);break; //調(diào)整屏幕亮度級(jí)別的參數(shù) case key_sleep_time : sleeptim(LEDDATA0);break; //調(diào)整超時(shí)待機(jī)的超時(shí)時(shí)間 case key_fanxian : fanxian(LEDDATA0);break; //反顯操作 case key_cachu : LEDcachu(LEDDATA0);break; //擦除操作 case key_tuoyi : obj_move(LEDDATA0);break; //對(duì)象拖移 case key_all_screen_del : del_all(LEDDATA0);break; // case key_tuoyi_quxiao : break; //”對(duì)象選定確認(rèn)后取消“在這里沒意義 case key_crease : break; //”數(shù)據(jù)+1“在這里沒意義 case key_decrease : break; //”數(shù)據(jù)-1“在這里沒意義 default : break; //沒按鍵匹配的,直接退出。雖然在這里不發(fā)生,但安全起見加上去 } } KEYS=0; light_T++; if(light_T>5){light_T=0;light();} //一秒內(nèi)自動(dòng)調(diào)光4次左右 } } void one_word(uchar dat_addr[32][4],uchar caozuo) //一秒鐘的一部分,大概是1/20秒。進(jìn)行一個(gè)點(diǎn)的掃描并顯示在LED屏上顯示, //以及更新數(shù)碼管的顯示 { if(!pen_key) { saomiao(); //光筆上的按鍵被按下就掃描,光筆這里占時(shí)間筆也算是一個(gè)大塊頭,3DU33的 //響應(yīng)時(shí)間保險(xiǎn)點(diǎn)來計(jì)算大約需要延時(shí)5uS。這樣,每次掃描按最壞打算則需要時(shí) //長為:T=(5+5)*32*N+(5+5)*N=330N(uS).N為給32列LED的高->低變換次數(shù),同時(shí)也為 //計(jì)數(shù)器計(jì)滿溢出的次數(shù)。 LED_GAI(dat_addr,caozuo,LED_ROW,LED_LINE); //修改當(dāng)前屏幕數(shù)據(jù)內(nèi)容以便下面更新顯示,writting意味著LED_GAI()函數(shù) // 對(duì)LEDDATA1[LED_ROW][LED_LINE/8]中的第LED_LINE%8位數(shù)據(jù)作”與0“操作。 //因?yàn)榻o74HC595的輸出端口低電平對(duì)應(yīng)選通該列。 //而相反,假如參數(shù)為erasure,則對(duì)同樣一位數(shù)據(jù)作”或1“運(yùn)算 //另外,如果pen_key沒被按下,那數(shù)據(jù)沒更新就不用改了。 } else {LED_ROW=99;LED_LINE=99;} //當(dāng)光筆上的按鍵沒被按下,即使用者沒打算寫字時(shí),把光筆當(dāng)前坐標(biāo)值顯示為99,99. shu_ma_g(); //數(shù)碼管更新靜態(tài)顯示 dis_play(dat_addr); //LED更新顯示,不管掃描是否執(zhí)行,LED屏肯定要顯示,占用著時(shí)間,而且是占CPU的大部分時(shí)間 //以使人眼察覺不到閃爍,如果顯示時(shí)長比例不>>掃描時(shí)長比例,那人眼將覺得LED在閃爍或微亮掃描 //(”不亮點(diǎn)“)太亮而顯示內(nèi)容(”亮點(diǎn)“)不夠亮 //主要是這個(gè)函數(shù)分配好時(shí)間,以達(dá)到1秒鐘至少掃描20次的效果 } void LED_GAI(uchar obj_mem[32][4],uchar opera,uchar LED_ROW,uchar LED_LINE ) {uchar temp,byteline,bitline; byteline=(LED_LINE-1)/8,bitline=(LED_LINE-1)%8; if(opera) //寫,即對(duì)應(yīng)位作“與0”運(yùn)算 { temp=0X80; temp=_cror_(temp,bitline); obj_mem[LED_ROW][byteline]=obj_mem[LED_ROW][byteline]|temp; } else{ temp=0x7F; temp=_cror_(temp,bitline); obj_mem[LED_ROW][byteline]=obj_mem[LED_ROW][byteline]&temp; } } void Timer1() interrupt 3 { static unsigned char count = 0; //定義靜態(tài)變量count TR0 = 0; //以下調(diào)整出棧入棧的時(shí)間誤差 TL0 += (_TH0_TL0_ + 9) % 256; TH0 += (_TH0_TL0_ + 9) / 256 + (char)CY; TR0 = 1; count++; if(pen_key) if(KEYS==0) { sec=0; min=0;} //光筆不被使用,而且任何按鍵沒被按下 else{ if(count >= 20)//1秒種時(shí)間到 { count = 0; sec++; if(sec == 60)//1分鐘時(shí)間到 { min++; sec = 0; } } if(min>=sleepmin) relay=1;//關(guān)屏 } } ////////////////////////////////////END/////////////////////////////////////////////////////////////////////////// ////////////////////////////////////文件 自動(dòng)調(diào)光.c/////////////////////////////////////////////////////////////// #include"myself.h" #include<reg52.h> #include<intrins.h> void light() { uchar finish,adc_result; //********************* //ADC_POWER_ON ADC_CONTER|=0X80; delay_us(1000); //1ms左右的延時(shí) //********************* //********************* //選擇模擬口(P1.2),即斷開上拉電阻形成模擬口 P1ASF=0x04; //********************* //********************* //選擇P1.2作為ADC轉(zhuǎn)換通道 ADC_CONTER&=0XF0; //低三位清零 _nop_();_nop_();_nop_();_nop_();//讓ADC_CONTER的數(shù)據(jù)穩(wěn)定 ADC_CONTER|=0X03; //切換通道 delay_us(20); //延時(shí)20us使電壓穩(wěn)定 //********************* //********************* //取AD轉(zhuǎn)換結(jié)果,ADRJ上電復(fù)位默認(rèn)為0,即取高8位數(shù)據(jù) ADC_RES=0XFF; //初始化為0XFF; ADC_CONTER|=0X08; //ADC_START _nop_();_nop_();_nop_();_nop_(); do{ finish=0X10; //0001 0000(b) finish|=ADC_CONTER; }while(finish); //等待AD轉(zhuǎn)換完成 ADC_CONTER&=0XE7; //11100111,清ADC_FLAG和ADC_START,停止AD轉(zhuǎn)換 adc_result=ADC_RES; //********************* if(adc_result>0x80)li_level=10; //R5549阻值在100K以上 else if(adc_result>0X71)li_level=9; //R5549阻值在80K~100K區(qū)間 else if(adc_result>0x60)li_level=8; //R5549阻值在60K~80K區(qū)間 else if(adc_result>0X49)li_level=7; //R5549阻值在40K~60K區(qū)間 else if(adc_result>0X2A)li_level=6; //R5549阻值在20K~40K區(qū)間 else if(adc_result>0X17)li_level=5; //R5549阻值在10K~20K區(qū)間 else li_level=4; //降到4級(jí)就好 } void lightlev(uchar showing[32][4]) { uchar key; uchar save_row=LED_ROW,save_line=LED_LINE; //用來保存數(shù)碼管數(shù)據(jù) while(1) { key=getkey(); switch(key) { case key_esc : return;break; //退出 case key_crease : if(men_lig<10)men_lig++;break; //”數(shù)據(jù)+1“ 最大值為10 case key_decrease : if(men_lig>4) men_lig--;break; //”數(shù)據(jù)-1“最少值為4 default : break; //沒按鍵匹配的,直接退出。雖然在這里不發(fā)生,但安全起見加上去 } LED_ROW=0x00;LED_LINE=men_lig; shu_ma_g(); dis_play(showing); LED_ROW=save_row;LED_LINE=save_line; } } ////////////////////////////////////END/////////////////////////////////////////////////////////////////////////// ////////////////////////////////////文件按鍵掃描.c////////////////////////////////////////////////////////// #include"myself.h" #include<reg52.h> #include<intrins.h> uchar getkey() { uchar key,finish,adc_result; //********************* //ADC_POWER_ON ADC_CONTER|=0X80; delay_us(1000); //1ms左右的延時(shí) //********************* //********************* //選擇模擬口(P1.0、P1.1),即斷開上拉電阻形成開漏輸出 P1ASF=0x03; //********************* //********************* //選擇P1.0作為ADC轉(zhuǎn)換通道 ADC_CONTER&=0XF8; //低三位置零,同時(shí)即選擇P1.0 _nop_();_nop_();_nop_();_nop_();//讓ADC_CONTER的數(shù)據(jù)穩(wěn)定 delay_us(20); //延時(shí)20us使電壓穩(wěn)定 //********************* //********************* //取AD轉(zhuǎn)換結(jié)果,ADRJ上電復(fù)位默認(rèn)為0,即取高8位數(shù)據(jù) ADC_RES=0XFF; //初始化為0XFF; ADC_CONTER|=0X08; //ADC_START _nop_();_nop_();_nop_();_nop_(); do{ finish=0X10; //0001 0000(b) finish=ADC_CONTER&finish; }while(!finish); ADC_CONTER&=0XE7; //11100111,請(qǐng)AD轉(zhuǎn)換完成標(biāo)志位,停止AD轉(zhuǎn)換 adc_result=ADC_RES; //********************* if (adc_result<0xB3)//0xb3即3.5V,0XB3/0XFF*5=3.5 { if(adc_result>0x99)key=7; //>3v else if(adc_result>0X80)key=6; //>2.5v else if(adc_result>0X66)key=5; //>2V else if(adc_result>0X4C)key=4; //>1.5V else if(adc_result>0X33)key=3; //>1V else if(adc_result>0X19)key=2; //>0.5V else key=1; }else{ //********************* //ADC_POWER_ON ADC_CONTER|=0X80; delay_us(1000); //1ms左右的延時(shí) //********************* //********************* //選擇模擬口(P1.0、P1.1),即斷開上拉電阻形成開漏輸出 P1ASF=0x03; //********************* //********************* //選擇P1.0作為ADC轉(zhuǎn)換通道 ADC_CONTER&=0XF8; //低三位清零 _nop_();_nop_();_nop_();_nop_();//讓ADC_CONTER的數(shù)據(jù)穩(wěn)定 ADC_CONTER|=0X01; delay_us(20); //切換通道,延時(shí)20us使電壓穩(wěn)定 //********************* //********************* //取AD轉(zhuǎn)換結(jié)果,ADRJ上電復(fù)位默認(rèn)為0,即取高8位數(shù)據(jù) ADC_RES=0XFF; //初始化為0XFF; ADC_CONTER|=0X08; //ADC_START _nop_();_nop_();_nop_();_nop_(); do{ finish=0X10; //0001 0000(b) finish|=ADC_CONTER; }while(finish); //等待AD轉(zhuǎn)換完成 ADC_CONTER&=0XE7; //11100111,請(qǐng)AD轉(zhuǎn)換完成標(biāo)志位,停止AD轉(zhuǎn)換 adc_result=ADC_RES; //********************* if (adc_result<0xB3)//0xb3即3.5V,0XB3/0XFF*5=3.5 { if(adc_result>0x99)key=14; //>3v else if(adc_result>0X80)key=13; //>2.5v else if(adc_result>0X66)key=12; //>2V else if(adc_result>0X4C)key=11; //>1.5V else if(adc_result>0X33)key=10; //>1V else if(adc_result>0X19)key=9; //>0.5V else key=8; } } return key; } ////////////////////////////////////END/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////文件超時(shí)待機(jī).c////////////////////////////////////////////////////////// #include"myself.h" #include<reg52.h> #include<intrins.h> void sleeptim(size showing) { uchar key; uchar save_row=LED_ROW,save_line=LED_LINE; //用來保存數(shù)碼管數(shù)據(jù) while(1) { key=getkey(); switch(key) { case key_esc : return;break; //退出 case key_crease : if(sleepmin<20)sleepmin++;break; //”數(shù)據(jù)+1“ case key_decrease : if(sleepmin>1)sleepmin--;break; //”數(shù)據(jù)-1“最小值為1 default : break; //沒按鍵匹配的,直接退出。雖然在這里不發(fā)生,但安全起見加上去 } LED_ROW=0x00;LED_LINE=sleepmin; shu_ma_g(); dis_play(showing); LED_ROW=save_row;LED_LINE=save_line; } } ////////////////////////////////////END/////////////////////////////////////////////////////////////////////////// ////////////////////////////////////文件 數(shù)碼管顯示.c////////////////////////////////////////////////////////////////// #include "myself.h" #include <intrins.h> #include <reg52.h> sbit RCLK_595=P2^5; sbit SRCLK_595=P2^6; sbit SER_595=P2^7; void shu_ma_g() { digital_show(LED_ROW,LED_LINE); } void digital_show(uchar row,uchar line) { uchar one; one=line%10; input(one); _nop_();_nop_(); one=(line-one)/10; input(one); _nop_();_nop_(); one=row%10; input(one); _nop_();_nop_(); one=(row-one)/10; input(one); _nop_();_nop_(); output(); } //將移位寄存器內(nèi)的數(shù)據(jù)鎖存到輸出寄存器并顯示 void output() { RCLK_595=0; _nop_();_nop_(); RCLK_595=1; _nop_();_nop_(); RCLK_595=0; } //;*****移位寄存器接收一個(gè)字節(jié)(如3FH)數(shù)據(jù)子程序 void input(uchar word) { uchar i; word=~word; //共陽,先取反 for(i=0;i<8;i++) { word=_cror_(word,1); SER_595=CY; SRCLK_595=0; _nop_();_nop_(); SRCLK_595=1; } SER_595=word; } ////////////////////////////////////END/////////////////////////////////////////////////////////////////////////// ////////////////////////////////////文件 display.c///////////////////////////////////////////////////////////////////////// #include"myself.h" #include<reg52.h> #include<intrins.h> void dis_play(uchar show_obj[32][4]) { uchar row,line,temp_row,templine; for(row=0;row<32;row++) {OUT_EN=1; //鎖止輸出 temp_row=P2&0XE0; //保存P2高三位數(shù)據(jù),低五位置零 P2=temp_row|row; //P2口低五位輸出行選數(shù)據(jù),高三位保持不變 for(line=0;line<4;line++) { templine=0X08; //p1.3=1,p1.4,p1.5,p1.6=0 只打開第一個(gè)鎖存器的鎖存使能,P1.3接第一個(gè)鎖存器 //0X08=0000 1000B P1=P1&0X87; //P1&10000111 P1=P1|_crol_(templine,line); //保存了P1的0、1、2、7位,對(duì)3/4/5/6進(jìn)行移位。 P0=show_obj[row][line]; //輸出八位數(shù)據(jù)并鎖存 _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); //延時(shí)500ns,讓數(shù)據(jù)能順利進(jìn)入74HC573 } OUT_EN=0; //輸出使能 delay_us(10*men_lig*li_level); //1MS左右的延時(shí),row循環(huán)執(zhí)行32次,即整個(gè)顯示函數(shù)占時(shí) OUT_EN=1; //30MS左右,而題目要求每秒鐘至少掃描20次即平均分下來 delay_us(10*men_lig*(10-li_level)); //每掃描顯示一次最多用時(shí)50MS } //**************************************延時(shí),level調(diào)節(jié)占空比,即屏幕亮度 OUT_EN=0; //鎖止輸出 } ////////////////////////////////////END/////////////////////////////////////////////////////////////////////////// ////////////////////////////////////多字連寫.c/////////////////////////////////////////////////////////// #include"myself.h" #include<reg52.h> #include<intrins.h> void fourwords() { uchar count; for(count=0;count<4;count++) { do{ //要是“確定”-----寫下一個(gè)字、“esc”----退出多字連寫模式,這兩個(gè)沒按下, //則把程序指針拖回這里來,不然FOR循環(huán)執(zhí)行完了count就+1,即寫下一個(gè)字了 //不要了 LCD_SHOW(); //1602的第一行顯示當(dāng)前模塊,第二行進(jìn)行操作提示,參數(shù)為提示內(nèi)容的字符串首地址 one_word(point[count],writting); //掃描一個(gè)點(diǎn)并予以顯示,在LEDDATA[count]內(nèi)存區(qū) KEYS=0; KEYS=getkey(); //AD掃描按鍵,其實(shí)按鍵掃描1秒鐘內(nèi)進(jìn)行10次足矣,不必跟隨這個(gè)dis_play()做至少20次的掃描, //因?yàn)槿说氖植豢赡芤幻雰?nèi)按鍵超過10次。 //調(diào)試時(shí)如果發(fā)現(xiàn)LED屏對(duì)光筆的反應(yīng)比較慢,則需要修改getkey()在一秒內(nèi)的時(shí)間占用比例, //即也意味著getkey()在一秒內(nèi)的執(zhí)行次數(shù)?梢赃@樣:設(shè)定一個(gè)計(jì)數(shù)器,每dis_play()一次就+1,初值 //為0,到了1就清零,并且調(diào)用get_key(),否則不執(zhí)行g(shù)et_key(). if(KEYS) //getkey()檢測到按鍵按下就返回按鍵的值,沒按鍵按下就返回0 { switch(KEYS) { case key_enter : break; //進(jìn)入下一個(gè)數(shù)據(jù)區(qū),即些下一個(gè)字,break退出后count+1 case key_esc : return; break; //返回最底層的點(diǎn)亮與畫亮功能模式下 // case key_words_modle : break; //沒反應(yīng),因?yàn)橐呀?jīng)在多字連寫功能下了 case key_light_level : lightlev(point[count]);break; //調(diào)整屏幕亮度級(jí)別的參數(shù),這個(gè)功能可在任意模式下進(jìn)入,同時(shí)返回也為進(jìn)入前的當(dāng)前模式 case key_sleep_time : sleeptim(point[count]);break; //調(diào)整超時(shí)待機(jī)的超時(shí)時(shí)間 ,同上 case key_fanxian : fanxian(point[count]);break; //反顯操作 case key_cachu : LEDcachu(point[count]);break; //擦除操作 case key_tuoyi : obj_move(point[count]);break; //對(duì)象拖移 // case key_tuoyi_xuanding : break; //”對(duì)象選定確認(rèn)“在這里沒意義 // case key_tuoyi_quxiao : break; //”對(duì)象選定確認(rèn)后取消“在這里沒意義 // case key_crease : break; //”數(shù)據(jù)+1“在這里沒意義 // case key_decrease : break; //”數(shù)據(jù)-1“在這里沒意義 default : break; //沒按鍵匹配的,直接退出。雖然在這里不發(fā)生,但安全起見加上去 } } }while(KEYS>=key_words_modle&&KEYS<=key_decrease); } fou_show(); //四個(gè)字寫完了,重新顯示出來。完了后退出返回點(diǎn)亮與畫亮模式 } void fou_show()//多字連寫模式中的連續(xù)輪流顯示4個(gè)字的函數(shù),每個(gè)字顯示1秒。4個(gè)字顯示完之后便自動(dòng)退出 { uchar words, times; //words為顯示的第幾個(gè)字,times為dis_play的執(zhí)行次數(shù),執(zhí)行25次大約為1秒 for(words=0;words<4;words++) { for(times=0;times<25;times++) { dis_play(point[words]); } } } ////////////////////////////////////文件 光筆掃描.c////////////////////////////////////////////////////////////////////// #include"myself.h" #include<reg52.h> #include<intrins.h> void saomiao() { uchar tempsave,mod_save; uchar N_times; TR1=0;//關(guān)閉定時(shí)器1 OUT_EN=1; //先讓鎖止LED點(diǎn)陣顯示 mod_save&=0XF0; TMOD|=0X06; //TMOD=XXXX 0110,計(jì)數(shù)器,八位自動(dòng)重載 TH0=0XFF-N; TL0=0XFF-N; TR0=1; //開始對(duì)外負(fù)跳變脈沖進(jìn)行計(jì)算,此時(shí)OUT_EN還是鎖止輸出 for(ROW_TEMP=0;ROW_TEMP<32;ROW_TEMP++) {tempsave=P2&0XE0; //保存P2高三位數(shù)據(jù),低五位置零 P2=tempsave|ROW_TEMP; //P2口低五位輸出行選數(shù)據(jù),高三位保持不變 P0=0X00; //全亮 P1|=0X78; //P1|=0111 1000,573鎖存全部打開 _nop_();_nop_(); for(N_times=0;N_times<N;N_times++) { OUT_EN=0; //亮 delay_us(5); //亮5us的延時(shí) P1&=0X87; //P1&=1000 0111關(guān)閉鎖存允許 OUT_EN=1; //滅 delay_us(5); //5us的延時(shí) } } TR0=0; OUT_EN=1; TR1=1; //開啟定時(shí)器1 } void Timer0() interrupt 1 //定時(shí)器0中斷服務(wù)程序 {uchar templine,line,i,data_sav,result=0x00; LED_ROW=ROW_TEMP; //保存光筆行坐標(biāo) for(i=0;i<5;i++) { OUT_EN=1; for(line=0;line<4;line++) { templine=0X08; //0000 1000 p1.3=1,p1.4,p1.5,p1.6=0 只打開第一個(gè)鎖存器的鎖存使能,P1.3接第一個(gè)鎖存器 //0X08=0000 1000B P1=P1&0X87; //P1&10000111 P1=P1|_crol_(templine,line); //保存了P1的0、1、2、7位,對(duì)3/4/5/6進(jìn)行左移位。 P0=LED_CODE[i][line]; //輸出八位數(shù)據(jù)并鎖存 _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); //延時(shí)500ns,讓數(shù)據(jù)能順利進(jìn)入74HC573 } OUT_EN=0; //573輸出數(shù)據(jù) delay_us(5); //延時(shí)5us,讓光筆數(shù)據(jù)穩(wěn)定 data_sav=P3&0X10; //0001 0000保存P3.4數(shù)據(jù),準(zhǔn)備移位 result|=_cror_(data_sav,5-i); //順序得出5位數(shù)據(jù),剛好當(dāng)光筆所在列為0時(shí)(列選通),光筆數(shù)據(jù)為0;所在列為1時(shí),光筆數(shù)據(jù)為1 } LED_LINE=result; } ////////////////////////////////////END/////////////////////////////////////////////////////////////////////////// ////////////////////////////////////文件 對(duì)象拖移.c/////////////////////////////////////////////////////////////////// #include "myself.h" #include <intrins.h> #include<reg52.h> #define CLICK P3^3 #define X LED_ROW #define Y LED_LINE void enkey(uchar led_data[32][4],uchar x,uchar y); //將第x行第y列反顯 void mov(uchar a,uchar b,uchar c,uchar d);//a^b->c^d void obj_move(uchar led_data[32][4]) { struct zuobiao { uchar x,y; }start,end,go,pref; uchar temp,i,j,chang,kuan; uchar xdata save[32][4]; uchar xdata tempscr[32][4]; while(CLICK);//等待按下 saomiao(); start.x=X;start.y=Y;//起點(diǎn) while(!CLICK);//等待彈起 saomiao(); end.x=X;end.y=Y;//終點(diǎn) if(start.x>=end.x){temp=start.x;start.x=end.x;end.x=temp;} //將start定位到矩形左上角, if(start.y>=end.y){temp=start.y;start.y=end.y;end.y=temp;} //end至右下角 for(i=start.x;i<end.x;i++){enkey(led_data,i,start.y);enkey(led_data,i,end.y);}//反顯方框 for(j=start.y;j<end.y;j++){enkey(led_data,start.x,j);enkey(led_data,end.x,j);} dis_play(led_data); chang=end.x-start.x+1;kuan=end.y-start.y+1;//記錄方框長寬 while(CLICK); saomiao(); if( !( (X>=start.x&&X<=end.x) && (Y>=start.y&&Y<=end.y) ) ) return ;// //開始拖動(dòng) for(i=start.x;i<end.x;i++){enkey(led_data,i,start.y);enkey(led_data,i,end.y);} //恢復(fù)方框的反顯 for(j=start.y;j<end.y;j++){enkey(led_data,start.x,j);enkey(led_data,end.x,j);} dis_play(led_data); go.x=X;go.y=Y; //記錄基準(zhǔn)點(diǎn) for(i=start.x;i<end.x;i++) //將選定區(qū)域“挖出” for(j=start.y;j<end.y;j++) { mov(led_data[i][j/8],j%8,save[i-start.x][(j-start.y)/8],(j-start.y)%8); mov(led_data[i][j/8],j%8,0xff,0); } for(i=0;i<32;i++) //將挖出選定區(qū)域后的屏幕交給tempscr處理 for(j=0;j<4;j++) { tempscr[i][j]=led_data[i][j]; } pref.x=99;pref.y=99; while(!CLICK)//未松開 { saomiao(); //取鼠標(biāo)位置 if(X!=pref.x||Y!=pref.y) { for(i=0;i<32;i++) //將挖出選定區(qū)域后的屏幕交給tempscr處理 for(j=0;j<4;j++) { tempscr[i][j]=led_data[i][j]; } for(i=X-go.x;i<X-go.x+chang;i++) //以鼠標(biāo)位置為基準(zhǔn)點(diǎn),放置選定 for(j=Y-go.y;j<Y-go.y+kuan;j++) { mov(save[i-X+go.x][(j-Y+go.y)/8],(j-Y+go.y)%8,tempscr[i][j/8],j%8); } pref.x=X;pref.y=Y; } dis_play(tempscr); } for(i=0;i<32;i++) //將臨時(shí)屏幕“轉(zhuǎn)正” for(j=0;j<4;j++) { led_data[i][j]=tempscr[i][j]; } } void enkey(uchar led_data[32][4],uchar x,uchar y) //將第x行第y列反顯 { uchar a,b; uchar temp; a=y/8;b=y%8; temp=0x80; temp=_cror_(temp,b); led_data[x][a]=temp^led_data[x][a]; } void mov(uchar a,uchar b,uchar c,uchar d)//a^b->c^d { uchar ta,tb; ta=0x80;tb=0x7f; ta=_cror_(ta,b);tb=_cror_(tb,d); ta=a&ta;tb=b&tb; if(b>d)ta=_crol_(ta,b-d); else ta=_cror_(ta,d-b); c=ta|tb; } ///////////////////////////////////文件 operating.c//////////////////////////////////////////////////////// #include"myself.h" #include<reg52.h> #include<intrins.h> void fanxian(uchar LEDDATA[32][4]) { uchar row; for(row=0;row<32;row++) { LEDDATA[row][0]=~LEDDATA[row][0]; LEDDATA[row][1]=~LEDDATA[row][1]; LEDDATA[row][2]=~LEDDATA[row][2]; LEDDATA[row][3]=~LEDDATA[row][3]; } } void LEDcachu(uchar LEDDATA[32][4]) { do { one_word(LEDDATA,erasure); //掃描一個(gè)點(diǎn)并予以顯示 KEYS=getkey(); //AD掃描按鍵,其實(shí)按鍵掃描1秒鐘內(nèi)進(jìn)行10次足矣,不必跟隨這個(gè)dis_play()做至少20次的掃描, //因?yàn)槿说氖植豢赡芤幻雰?nèi)按鍵超過10次。 //調(diào)試時(shí)如果發(fā)現(xiàn)LED屏對(duì)光筆的反應(yīng)比較慢,則需要修改getkey()在一秒內(nèi)的時(shí)間占用比例, //即也意味著getkey()在一秒內(nèi)的執(zhí)行次數(shù)。可以這樣:設(shè)定一個(gè)計(jì)數(shù)器,每dis_play()一次就+1,初值 //為0,到了1就清零,并且調(diào)用get_key(),否則不執(zhí)行g(shù)et_key(). /*if(KEYS) //getkey()檢測到按鍵按下就返回按鍵的值,沒按鍵按下就返回0 { switch(KEYS) { //為了不讓使用者覺得混亂,這里就不允許多級(jí)嵌套了,因此 //下面很多都不允許 case key_enter : break; //”確定“在這里沒意義 case key_esc : return;break; //退出,返回點(diǎn)亮與畫亮模式 case key_words_modle : break; //這里模式下不允許進(jìn)入多字連寫功能 case key_light_level : break; //不允許調(diào)整屏幕亮度級(jí)別的參數(shù) case key_sleep_time : break; //不允許調(diào)整超時(shí)待機(jī)的超時(shí)時(shí)間 case key_fanxian : break; //不允許反顯操作 case key_cachu : break; //不允許擦除操作 case key_tuoyi : break; //不允許對(duì)象拖移 case key_tuoyi_xuanding : break; //”對(duì)象選定確認(rèn)“在這里沒意義 case key_tuoyi_quxiao : break; //”對(duì)象選定確認(rèn)后取消“在這里沒意義 case key_crease : break; //”數(shù)據(jù)+1“在這里沒意義 case key_decrease : break; //”數(shù)據(jù)-1“在這里沒意義 default : break; //沒按鍵匹配的,直接退出。雖然在這里不發(fā)生,但安全起見加上去 } } */ //這一段可以不需要了 }while(KEYS!=key_esc); } void del_all(uchar obj[32][4]) { uchar row; for(row=0;row<32;row++) { obj[row][0]=0X00; obj[row][1]=0X00; obj[row][2]=0X00; obj[row][3]=0X00; } } ////////////////////////////////////END///////////////////////////////////////////////////////////////////////////完了,就是這些,如果我沒漏掉的話.....我按照自己的工程文檔排列順序拉過來的,應(yīng)該沒漏了..... 總結(jié)寫完了