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






