经常写代码太累太没趣了,DIY遥控时钟玩玩,还别说一动起手来才知道模电没学好。在调试过程中还发现比遥控更牛B的功能,小手一模到屏的数据线还会调时。哈哈能到这就是传说中的触屏功能??可用在这里有点浪费啊,费了大半天原来是没上拉受干拢了。时钟掉电可走两年1602+1302+C52。用着自己造的东东就是爽啊,下次想DIY 手机(呵呵技术难达到) 牛人多的是在这里本人只是想写点东东与大家交流下,分享DIY的乐趣,以及激励学习的热情。以下是时钟源程序(程序写的啰嗦别笑)
#include
//寄存器宏定义
#define W_SECOND 0x80
#define W_MINUTE 0x82
#define W_HOUR 0x84
#define R_SECOND 0x81
#define R_MINUTE 0x83
#define R_HOUR 0x85
#define W_PROTECT 0x8E
#define R_DAY 0x87
#define R_MONTH 0x89
#define R_YEAR 0x8D
#define W_YEAR 0x8C
#define W_MONTH 0x88
#define W_DAY 0x86
#define uchar unsigned char
#define uint unsigned int
#define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0替换
#define wei P2
***it RS=P2^6;
***it RW=P2^5;
***it PSB=P1^2;
***it EN=P2^4;
//位寻址寄存器宏定义
***it ACC_7=ACC^7;
***it SCLK=P2^1;
***it DIO=P2^2;
***it CE=P2^3;
***it IR=P3^2; //红外接口标志
***it BUZZ=P3^4;
//***it SZEN=CH;
uchar GUBIAO,jishu,busy;
char dat1,flag,flag1,miao,fen,shi,r,yue,flag2,flag3,h;
uchar code addr_tab[]={
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,//第一行汉字位置
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,//第二行汉字位置
0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,//第三行汉字位置
0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,//第四行汉字位置
};
uchar code tab[]={'0','1','2','3','4','5','6','7','8','9'};
unsigned char IRcord[4];
unsigned char irdata[33];
/*------------------------------------------------
函数声明
------------------------------------------------*/
void lcd_wcmd(uchar cmd);
void lcd_wdat(uchar dat);
void dipl(unsigned char a);
void W1302(unsigned char addr,dat) ;
void Ir_work(void);
void Ircordpro(void);
void Delay(unsigned int t);
void queding();
void lcd_rdat();
void delay(uchar z);
void gonnen();
void taojia();
void taojian();
unsigned char R1302(unsigned char addr);
void delay_1ms(void);
/*------------------------------------------------
全局变量声明
------------------------------------------------*/
unsigned char irtime;//红外用全局变量
unsigned char a,b,m,n;
bit irpro_ok,irok;
/*------------------------------------------------
定时器0中断处理
------------------------------------------------*/
void tim0_isr (void) interrupt 1 using 1
{
irtime++; //用于计数2个下降沿之间的时间
}
/*------------------------------------------------
外部中断0中断处理
------------------------------------------------*/
void EX0_ISR (void) interrupt 0 //外部中断0服务函数
{
static unsigned char i; //接收红外信号处理
static bit startflag; //是否开始处理标志位
if(startflag)
{
if(irtime<63&&irtime>=33)//引导码 TC9012的头码,9ms+4.5ms
i=0;
irdata=irtime;//存储每个电平的持续时间,用于以后判断是0还是1
irtime=0;
i++;
if(i==33)
{
irok=1;
i=0;
}
}
else
{
irtime=0;
startflag=1;
}
}
/*------------------------------------------------
定时器0初始化
------------------------------------------------*/
void TIM0init(void)//定时器0初始化
{
TMOD=0x02;//定时器0工作方式2,TH0是重装值,TL0是初值
TH0=0x00; //重载值
TL0=0x00; //初始化值
ET0=1; //开中断
TR0=1;
}
/*------------------------------------------------
外部中断0初始化
------------------------------------------------*/
void EX0init(void)
{
IT0 = 1; //指定外部中断0下降沿触发,INT0 (P3.2)
EX0 = 1; //使能外部中断
EA = 1; //开总中断
}
//*************************************************************
//*************************************************************
//调时间功能选择
//*************************************************************
//*************************************************************
void gonnen() //功能键函数
{
unsigned char f,g;
R1302(R_MINUTE);
if(flag2==0) //中断功能函数运行后读DS1302数标志
{
fen=dat1;
R1302(R_HOUR);
shi=dat1;
R1302(R_DAY);
r=dat1;
R1302(R_MONTH);
yue=dat1;
flag2=1;
}
W1302(W_PROTECT,0X00); //
W1302(W_SECOND,0X80);
W1302(W_PROTECT,0X80);
flag=1;
flag1=1; //中断功能函数运行后调时间函数进入标志
flag3=1;
GUBIAO++; //屏幕光标
if(GUBIAO==1) //光标位置选择
{
lcd_wcmd(0x80+0x4a);
lcd_wcmd(0x0F);
}
if(GUBIAO==2)
{
lcd_wcmd(0x80+0x47);
lcd_wcmd(0x0F);
}
if(GUBIAO==3)
{
lcd_wcmd(0x80+0x44);
lcd_wcmd(0x0F);
}
if(GUBIAO==4)
{
lcd_wcmd(0x80+0x0b);
lcd_wcmd(0x0F);
}
if(GUBIAO==5)
{
lcd_wcmd(0x80+0x08);
lcd_wcmd(0x0F);
}
if(GUBIAO==6) //功能键函数退出前处理各标志和对DS1302写入数据
{
GUBIAO=0;
flag=0; //中断功能函数退出后主函数恢复运行标志
flag1=0; //中断功能函数退出后调时间函数不能进入标志
flag2=0;
flag3=0;
lcd_wcmd(0x0c);
f=fen/10; //十进制转十六进制准备给DS1302送数据
g=fen%10; //
fen=f*16+g; //
f=shi/10; //
g=shi%10; //
shi=f*16+g; //
f=r/10; //
g=r%10; //
r=f*16+g; //
f=yue/10; //
g=yue%10; //
yue=f*16+g; //
W1302(W_PROTECT,0X00); //把转好的十六进制数送给DS1302
W1302(W_MINUTE,fen);
W1302(W_HOUR,shi);
W1302(W_DAY,r);
W1302(W_MONTH,yue);
W1302(W_SECOND,0X55);
W1302(W_PROTECT,0X80);
}
}
//*************************************************************
//*************************************************************
// 调时间加加
//*************************************************************
//*************************************************************
void taojia()
{
if(flag1==1)
{
if(GUBIAO==2) //分
{
fen++;
if(fen>=60)
fen=0;
lcd_wcmd(0x80+0x47);
dipl(fen);
lcd_wcmd(0x80+0x47);
}
if(GUBIAO==3) //时
{
shi++;
if(shi>=24)
shi=0;
lcd_wcmd(0x80+0x44);
dipl(shi);
lcd_wcmd(0x80+0x44);
}
if(GUBIAO==4) //日
{
r++;
if(r>=32)
r=1;
lcd_wcmd(0x80+0x0b);
dipl(r);
lcd_wcmd(0x80+0x0b);
}
if(GUBIAO==5) //月
{
yue++;
if(yue>=13)
yue=1;
lcd_wcmd(0x80+0x08);
dipl(yue);
lcd_wcmd(0x80+0x08);
}
}
}
//*************************************************************
//*************************************************************
// 调时间减减
//*************************************************************
//*************************************************************
void taojian()
{
if(flag3==1)
{
if(GUBIAO==2) //分
{
fen--;
if(fen<0)
fen=59;
lcd_wcmd(0x80+0x47);
dipl(fen);
lcd_wcmd(0x80+0x47);
}
if(GUBIAO==3) //时
{
shi--;
if(shi<0)
shi=23;
lcd_wcmd(0x80+0x44);
dipl(shi);
lcd_wcmd(0x80+0x44);
}
if(GUBIAO==4) //日
{
r--;
if(r<1)
r=31;
lcd_wcmd(0x80+0x0b);
dipl(r);
lcd_wcmd(0x80+0x0b);
}
if(GUBIAO==5) //月
{
yue--;
if(yue<1)
yue=12;
lcd_wcmd(0x80+0x08);
dipl(yue);
lcd_wcmd(0x80+0x08);
}
}
}
/*------------------------------------------------
键值处理
------------------------------------------------*/
void zuanhuan(void) //a--b
{
switch(a)
{
case 0x45:gonnen(); break;
case 0x46:taojia(); break;
case 0x40:taojian(); break;
default:break;
}
}
//*************************************************************
//*************************************************************
//红外键值散转
//*************************************************************
//*************************************************************
void Ir_work(void)
{
a=IRcord[2];
zuanhuan();
irpro_ok=0;//处理完成标志
}
/*------------------------------------------------
红外码值处理
------------------------------------------------*/
void Ircordpro(void)//红外码值处理函数
{
unsigned char i, j, k;
unsigned char cord,value;
k=1;
for(i=0;i<4;i++) //处理4个字节
{
for(j=1;j<=8;j++) //处理1个字节8位
{
cord=irdata[k];
if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差
value|=0x80;
if(j<8)
{
value>>=1;
}
k++;
}
IRcord=value;
value=0;
}
irpro_ok=1;//处理完毕标志位置1
}
//*************************************************************
//*************************************************************
//延时
//*************************************************************
//*************************************************************
void delay_1ms(void) //延时程序
{
uchar K,L;
for(K=0;K<10;K++)
for(L=0;L<20;L++);
}
void delay(uchar z)
{
uchar i,j;
for(i=z;i>0;i--)
for(j=220;j>0;j--);
}
//*************************************************************
//*************************************************************
//检测LCD忙
//*************************************************************
//*************************************************************
void busy_1602(void) //查询忙碌标志信号程序
{
do
{
EN=0;
RW=1;
RS=0;
EN=1;
busy=P0;
EN=0;
delay_1ms();
} while(busy&&0x10==1);
}
//*************************************************************
//*************************************************************
//LCD显汉字
//*************************************************************
//*************************************************************
void hanzi_Disp(uchar x,uchar y,uchar *pt)
{
lcd_wcmd(addr_tab[8*x+y]); //写地址
while(*pt>0)
{
lcd_wdat(*(pt++)); //写数据
}
}
//*************************************************************
//*************************************************************
//LCD写指令
//*************************************************************
//*************************************************************
void lcd_wcmd(uchar cmd)
{ busy_1602();
EN=0;
RW=0;
RS=0;
EN=1;
P0=cmd;
EN=0;
}
//*************************************************************
//*************************************************************
//LCD写数据
//*************************************************************
//*************************************************************
void lcd_wdat(uchar dat)
{ busy_1602();
EN=0;
RW=0;
RS=1;
EN=1;
P0=dat;
EN=0;
}
//*************************************************************
//*************************************************************
//LCD读数据
//*************************************************************
//*************************************************************
/*void lcd_rdat()
{
unsigned char lcddat;
EN = 0;
RS = 0;
RW = 1;
delay(4);
EN = 1;
lcddat = P0;
delay(4);
EN = 0;
} */
//*************************************************************
//*************************************************************
//LCD初始化
//*************************************************************
//*************************************************************
void lcd_init()//LCD初始化
{
lcd_wcmd(0x38);
lcd_wcmd(0x0c);
lcd_wcmd(0x06);
}
//*****************************************************************
//DS1302写地址,数据发送函数****************************
//******************************************************************
void W1302(unsigned char addr,dat)
{
unsigned char i,temp;
CE=0;
SCLK=0;
CE=1;
//DS1302发地址
for(i=8;i>0;i--)
{
SCLK=0;
temp=addr;
DIO=(bit)(temp&0x01); //每次传输低字节
addr>>=1;
SCLK=1;
}
//DS1302发送数据
for(i=8;i>0;i--)
{
SCLK=0;
temp=dat;
DIO=(bit)(temp&0x01);
dat>>=1;
SCLK=1;
}
CE=0;
}
//*************************************************************
//**************************************************************
//DS1302数据读取函数
//*************************************************************
//*************************************************************
unsigned char R1302(unsigned char addr)
{
unsigned char i,temp,dat2;
CE=0;
SCLK=0;
CE=1;
//DS1302发送地址
for(i=8;i>0;i--)
{
SCLK=0;
temp=addr;
DIO=(bit)(temp&0x01); //每次传输低字节
addr>>=1;
SCLK=1;
}
//DS1302读取数据
for(i=8;i>0;i--)
{
ACC_7=DIO;
SCLK=1;
ACC>>=1;
SCLK=0;
}
CE=0;
dat1=ACC;
dat2=dat1/16;
dat1=dat1%16;
dat1=dat1+dat2*10;
return(dat1);
}
//*************************************************************
//*************************************************************
//初始化DS1302
//*************************************************************
//*************************************************************
void Init(void)
{
P2=0XFF;
W1302(W_PROTECT,0X00);
// W1302(W_SECOND,0X00);
// W1302(W_MINUTE,0X10);
// W1302(W_HOUR,0X20);
W1302(W_YEAR,0X12);
// W1302(W_MONTH,0X04);
// W1302(W_DAY,0X21);
W1302(W_PROTECT,0X80);
}
//*************************************************************
//*************************************************************
//转换显示时间
//*************************************************************
//*************************************************************
void dipl(unsigned char a)
{ unsigned char b,c,d;
b=a/10;
c=a%10;
lcd_wdat(tab);
lcd_wdat(tab[c]);
}
//*************************************************************
//*************************************************************
//主函数
//*************************************************************
//*************************************************************
void main() //主函数
{
EX0init(); //初始化外部中断
TIM0init();//初始化定时器
lcd_init();
Init();
while(1)
{
while(flag==1)
{
if(irok) //如果接收好了进行红外处理
{
Ircordpro();
irok=0;
}
if(irpro_ok) //如果处理好后进行工作处理,如按对应的按键后显示对应的数字等
{
Ir_work();
}
}
lcd_wcmd(0x80+0x4a); //秒
R1302(R_SECOND);
dipl(dat1);
lcd_wcmd(0x80+0x47); //分
R1302(R_MINUTE);
dipl(dat1);
lcd_wcmd(0x80+0x44); //时
R1302(R_HOUR);
dipl(dat1);
lcd_wcmd(0x80+0x05); //年
R1302(R_YEAR);
dipl(dat1);
lcd_wcmd(0x80+0x08); //月
R1302(R_MONTH);
dipl(dat1);
lcd_wcmd(0x80+0x0b); //日
R1302(R_DAY);
dipl(dat1);
lcd_wcmd(0x80+0x07);
lcd_wdat('-');
lcd_wcmd(0x80+0x0a);
lcd_wdat('-');
lcd_wcmd(0x80+0x46);
lcd_wdat(':');
lcd_wcmd(0x80+0x49);
lcd_wdat(':');
lcd_wcmd(0x80+0x03);
lcd_wdat('2');
lcd_wcmd(0x80+0x04);
lcd_wdat('0');
if(irok) //如果接收好了进行红外处理
{
Ircordpro();
irok=0;
}
if(irpro_ok) //如果处理好后进行工作处理,如按对应的按键后显示对应的数字等
{
Ir_work();
}
}
}
4
|
|
|
|