当前位置:文档之家› led点阵书写屏程序

led点阵书写屏程序

#include

#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、超时待机时间设定
//
//联系人:唐敏健(150********/380467850@https://www.doczj.com/doc/9c11351698.html,)
//
//****************************************************************************

#include"myself.h"
#include
#include




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
#include

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_STA

RT
_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
#include

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(ad

c_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
#include





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
#include

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
#include

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
#include



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
#include

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{
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
#include

#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;ifor(j=start.y;jdis_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;ifor(j=start.y;jdis_play(led_data);

go.x=X;go.y=Y; //记录基准点
for(i=start.x;ifor(j=start.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;ifor(j=Y-go.y;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
#include

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///////////////////////////////////////////////////////////////////////////

相关主题
文本预览
相关文档 最新文档