專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

LED點(diǎn)陣書寫顯示屏的程序和電路圖

作者:佚名   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2010年05月18日   【字體:

最后補(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:




LED驅(qū)動(dòng)板原理圖:



光筆PCB:




光筆 原理圖:



主控板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é)寫完了
關(guān)閉窗口

相關(guān)文章