超级给力,为发扬电子DIY精神,方便大家制作,公开本制作的程序了,希望大家多多支持!
占楼拉票了,ysjabcd的速度里程计,清新不落俗套,独一无二,可以做成产品哦!
带单次里程显示,方便计算任意两地间路程.带时间显示,红外调时,解决了机械按键不能密闭防水的缺点,也可移植到不方便近距离调时的时钟。
做一个这家伙装在您的自行车上,随时掌握速度时间,还是您自己动手制作的,那是相当的有面子!
更多精彩http://forum.eepw.com.cn/thread/205904/1
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define ISP_BYTE_READ 1 //ISP字节读
#define ISP_BYTE_PROGRAM 2 //ISP直接编程
#define ISP_SECTOR_ERASE 3 //ISP扇区擦除
/*以下是配置STC单片机的寄存器*/
/*相关资料在STC89C51RC的PDF的第35页开始*/
sfr ISP_DATA = 0xE2;
sfr ISP_ADDRH = 0xE3;
sfr ISP_ADDRL = 0xE4;
sfr ISP_CMD = 0xE5;
sfr ISP_TRIG = 0xE6;
sfr ISP_CONTR = 0xE7;
uchar code table[]="km/h km";
uchar code table1[]=" km";
sbit rs=P2^4; // 液晶
sbit rw=P2^5; // 液晶
sbit en=P2^6; // 液晶
uint aa,time,s1,s11;
uchar num,bb,a,b,up,down;
uchar IRCOM[7];//红外数组
unsigned long int quan,s2,s21; //
sbit ACC0 = ACC^0; //1302
sbit ACC7 = ACC^7; //1302
sbit IRIN = P3^2; //红外接收器数据线
sbit T_CLK = P3^6; /*实时时钟时钟线引脚 */
sbit T_IO = P3^4; /*实时时钟数据线引脚 */
sbit T_RST = P3^5; /*实时时钟复位线引脚 */
uchar flag;
uchar sec, min, hour;
void Write_DS1302Init(void);
void display();
void delayhw(uchar x); //x*0.14MS 红外延时
void delay(uint z);//液晶延时
/********************************************************************
* 功能 : EEPROM的扇区擦除
* 输入 : Address(擦除扇区的地址)
***********************************************************************/
void ISP_ERASE(Address)
{
ISP_ADDRL = Address;
ISP_ADDRH = Address >> 8;
ISP_CONTR = 0x81;
ISP_CMD = ISP_SECTOR_ERASE;
ISP_TRIG = 0x46; //PDF手册中说先像 ISP_TRIG 中写入 0x46, 然后写入 0xb9
ISP_TRIG = 0xb9;
_nop_();
_nop_();
}
/********************************************************************
* 输入 : Address(想要读取EEPROM的地址)
*********************************************************************/
uint ISP_READ(Address)
{
uchar Read_Data;
ISP_ADDRL = Address;
ISP_ADDRH = Address >> 8;
// EA = 0;
ISP_CONTR = 0x81;
ISP_CMD = ISP_BYTE_READ;
ISP_TRIG = 0x46;
ISP_TRIG = 0xb9;
_nop_();
_nop_();
Read_Data = ISP_DATA;
return Read_Data;
}
/********************************************************************
* 输入 : Address为编程的地址,Data_temp为想要编程的值
***********************************************************************/
void ISP_PROGRAM(Address, Data_temp)
{
ISP_DATA = Data_temp;
ISP_ADDRL = Address;
ISP_ADDRH = Address >> 8;
ISP_CONTR = 0x81;
ISP_CMD = ISP_BYTE_PROGRAM;
ISP_TRIG = 0x46;
ISP_TRIG = 0xb9;
_nop_();
_nop_();
}
void delay(uint z) //液晶延时
{
uint x,y;
for(x=110;x>0;x--)
for(y=z;y>0;y--);
}
void write_com(uchar com) //液晶写命令
{
rs=0;
P0=com;
delay(1);
en=1;
delay(1);
en=0;
}
void write_data(uchar date) //液晶写数据
{
rs=1;
P0=date;
delay(1);
en=1;
delay(1);
en=0;
}
void init()
{
quan=0;
en=0;
rw=0;
aa=0;
up=0;
down=0;
flag=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
EA=1; //开总中断
EX0=1; //开外部中断0
IT0=1; //外部中断设为下降沿触发
ET0=1; // 开定时器0中断
TMOD=0x11;//定时器0设定为定时器模式
TH0=(65536-5000)/256;
TL0=(65536-5000)%256; //定时器0装初值5ms
TR0=1;//启动定时器0
EX1=1; //开外部中断1
IT1=1; //外部中断1设为下降沿触发
flag=0;
}
void v_RTInputByte(uchar ucDa) //往DS1302写入1Byte数据
{
uchar i;
ACC = ucDa;
T_RST = 1;
for(i=8; i>0; i--)
{
T_IO = ACC0;
T_CLK = 1;
T_CLK = 0;
ACC = ACC >> 1;
}
}
uchar uc_RTOutputByte(void) //读取1byte数据
{
uchar i;
T_RST = 1;
for(i=8; i>0; i--)
{
ACC = ACC >>1;
// T_IO=1;
ACC7 = T_IO;
T_CLK = 1;
T_CLK = 0;
}
return(ACC);
}
void v_W1302(uchar ucAddr, uchar ucDa) //输入 : ucAddr: DS1302地址, ucDa: 要写的数据
{
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(ucAddr); // 写地址
_nop_();
_nop_();
v_RTInputByte(ucDa); // 写1Byte数据
T_CLK = 1;
T_RST = 0;
}
uchar uc_R1302(uchar ucAddr) // 读取DS1302某地址的数据
{
uchar ucDa;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(ucAddr); //写地址,命令
_nop_();
_nop_();
ucDa = uc_RTOutputByte(); //读1Byte数据
T_CLK = 1;
T_RST = 0;
return(ucDa);
}
void keyscan() //设置时钟的键盘扫描程序
{
if(flag!=0)
{
while(flag)
{
if(flag==1)
{
write_com(0x80+0x47);
write_com(0x0f);
}
if(flag==2)
{
write_com(0x80+0x44);
}
if(flag==3)
{
write_com(0x80+0x41);
} //
if(up==1)
{
if(flag==1)
{
sec++;
if(sec==60)
sec=0;
}
if(flag==2)
{
min++;
if(min==60)
min=0;
}
if(flag==3)
{
hour++;
if(hour==24)
hour=0;
}
up=0;
display();
}
if(down==1)
{
if(flag==1)
{
sec--;
if(sec==255)
sec=59;
}
if(flag==2)
{
min--;
if(min==255)
min=59;
}
if(flag==3)
{
hour--;
if(hour==255)
hour=23;
}
down=0;
display();
}
// display();
}
Write_DS1302Init();
}
}
uchar dectobcd(uchar dec)// DEC码转换为BCD码
{
uchar bcd;
bcd = 0;
while(dec >= 10)
{
dec -= 10;
bcd++;
}
bcd <<= 4;
bcd |= dec;
return bcd;
}
uchar bcdtodec(uchar bcd) // BCD码转换为DEC码
{
uchar data1;
data1 = bcd & 0x0f; //取BCD低4位
bcd = bcd & 0x70; //剔除BCD的最高位和低4位。
data1 += bcd >> 1;
data1 += bcd >> 3; //用位移代替乘法运算
return data1;
}
void Write_DS1302Init(void)
{
sec=dectobcd(sec);
min=dectobcd(min);
hour=dectobcd(hour);
v_W1302(0x8e,0);
v_W1302(0x80,sec); //写入秒;
v_W1302(0x82,min); //写入分
v_W1302(0x84,hour); //写入小时
}
void display() //1302显示
{
uchar hourshi,hourge,minshi,minge,secshi,secge;
hourshi=hour/10;
hourge=hour%10;
minshi=min/10;
minge=min%10;
secshi=sec/10;
secge=sec%10;
write_com(0x80+0x40);
write_data(0x30+hourshi);
write_data(0x30+hourge);
write_data(0x3a);
write_data(0x30+minshi);
write_data(0x30+minge);
write_data(0x3a);
write_data(0x30+secshi);
write_data(0x30+secge);
}
void Run_DS1302(void) // 读出DS1302中的数据,并在液晶上进行显示
{ uchar dd;
for(dd=10;dd>0;dd--) //加入循环,防止速度变化太快,不方便度数
{
sec = bcdtodec(uc_R1302(0x81)); //读出DS1302中的秒;
min = bcdtodec(uc_R1302(0x83)); //读出DS1302中的分
hour = bcdtodec(uc_R1302(0x85)); //读出DS1302中的小时
if(hour==0) //时间校准,每天0:30:30减少15s
{
if(min==30)
{
if(sec==45)
{
while(sec)
{
sec = bcdtodec(uc_R1302(0x81));
}
sec=46;
Write_DS1302Init();
}
}
}
display();
keyscan();
}
}
void write_su(uint dat)//速度显示
{
uchar shi,ge;
shi=dat%100/10;
ge=dat%10;
write_com(0x80);
write_data(0x20);
write_com(0x81);
write_data(0x30+shi);
write_data(0x30+ge);
}
void write_s1(uint s1)//一次里程显示
{
uchar bai,shi,ge,dian;
// wan=s1/10000; //s1为一次路程,一般不会超过几百km,故无万千位
// qian=s1%10000/1000;
bai=s1%10000/1000;
shi=s1%1000/100;
ge=s1%100/10;
dian=s1%10;
write_com(0x89);
write_data(0x30+bai);
write_data(0x30+shi);
write_data(0x30+ge);
write_data(0x2e);
write_data(0x30+dian);
}
void write_s2(uint s2)//总里程显示
{
uchar wan,qian,bai,shi,ge,dian;
wan=s2%1000000/100000;
qian=s2%100000/10000;
bai=s2%10000/1000;
shi=s2%1000/100;
ge=s2%100/10;
dian=s2%10;
write_com(0x80+0x49);
write_data(0x30+wan);
write_data(0x30+qian);
write_data(0x30+bai);
write_data(0x30+shi);
write_data(0x30+ge);
write_data(0x2e);
write_data(0x30+dian);
}
void main()
{
init();
write_com(0x83);
for(num=0;num<13;num++) //先显示固定的km/h km
{
write_data(table[num]);
delay(2);
}
write_com(0x80+0x46);
for(num=0;num<10;num++) //先显示固定的km
{
write_data(table1[num]);
delay(2);
}
// ISP_ERASE(0x2000); //
// ISP_PROGRAM(0x2000, 0x05);
// ISP_ERASE(0x2c01);
// ISP_PROGRAM(0x2c01, 0x40);
a=ISP_READ(0x2003);
delay(20);
b=ISP_READ(0x2207);
s21=a*256+b; //读出的两个八位合成一个十六位
// s21=248; //要改,用来清空第一次写入eeprom的数据
write_s2(s21); //显示开机总里程
while(1)
{
s1=quan*0.65; //s1为一次路程 这里一圈按0.65m算
if(s11!=s1) //如果s1发生了变化
{
s2=s21+s1; //s2为总里程 ,s21为开机读出的里程
a=s2/256; //s2为16位,把其分为两个八位分别写入存储器
b=s2%256;
ISP_ERASE(0x2003); // 扇区擦除。无字节擦除
ISP_PROGRAM(0x2003, a);
delay(20);
ISP_ERASE(0x2207);
ISP_PROGRAM(0x2207, b); // 将两组数据写向不同扇区
write_s2(s2);
}
s11=s1;
write_s1(s1); // 一次路程显示
delay(100);
write_com(0x81); //换行
write_su(bb); //速度显示
bb=0;
Run_DS1302();
}
}
void timer0() interrupt 1
{
TH0=(65536-5000)/256;
TL0=(65536-5000)%256; //定时器0装初值5ms
aa++;
}
void exter1() interrupt 2
{
if(aa>=200)//即车轮转一圈时间超过1秒,认为速度为零
bb=0;
if(aa<200)
{
time=aa*5;//定时器为5ms,为避免带小数点,此乃为正常时间的1000倍
bb=65*36/time;//65为车圈周长的100倍,单位为米,bb为整型变量,舍掉速度小数点
}
aa=0;
quan++;
}
void exter0() interrupt 0
{
unsigned char j,k,N=0;
EX1 = 0;
delayhw(15);
if (IRIN==1)
{ EX1 =1;
return;
}
//确认IR信号出现
while (!IRIN) //等IR变为高电平,跳过9ms的前导低电平信号。
{delayhw(1);}
for (j=0;j<4;j++) //收集四组数据
{
for (k=0;k<8;k++) //每组数据有8位
{
while (IRIN) //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
{delayhw(1);}
while (!IRIN) //等 IR 变为高电平
{delayhw(1);}
while (IRIN) //计算IR高电平时长
{
delayhw(1);
N++;
if (N>=30)
{ EX1=1;
return;} //0.14ms计数过长自动离开。
} //高电平计数完毕
IRCOM[j]=IRCOM[j] >> 1; //数据最高位补“0”
if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;} //数据最高位补“1”
N=0;
}//end for k
}//end for j
if (IRCOM[2]!=~IRCOM[3])
{ EX1=1;
return; }
IRCOM[5]=IRCOM[2] & 0x0F; //取键码的低四位
IRCOM[6]=IRCOM[2] >> 4; //右移4次,高四位变为低四位
if(IRCOM[5]>9)
{ IRCOM[5]=IRCOM[5]+0x37;}
else
IRCOM[5]=IRCOM[5]+0x30;
if(IRCOM[6]>9)
{ IRCOM[6]=IRCOM[6]+0x37;}
else
IRCOM[6]=IRCOM[6]+0x30;
if(IRCOM[6]==0x34)
{
if(IRCOM[5]==0x35)
{
flag=flag+1;
if(flag==4)
{
write_com(0x0c);
flag=0;
}
}
}
if(IRCOM[6]==0x34)
{
if(IRCOM[5]==0x34)
{
down=1;
}
}
if(IRCOM[6]==0x34)
{
if(IRCOM[5]==0x30)
{
up=1;
}
}
EX1 = 1;
return;
}
void delayhw(unsigned char x) //x*0.14MS 红外延时
{
unsigned char i;
while(x--)
{
for (i = 0; i<13; i++) {}
}
}#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define ISP_BYTE_READ 1 //ISP字节读
#define ISP_BYTE_PROGRAM 2 //ISP直接编程
#define ISP_SECTOR_ERASE 3 //ISP扇区擦除
/*以下是配置STC单片机的寄存器*/
/*相关资料在STC89C51RC的PDF的第35页开始*/
sfr ISP_DATA = 0xE2;
sfr ISP_ADDRH = 0xE3;
sfr ISP_ADDRL = 0xE4;
sfr ISP_CMD = 0xE5;
sfr ISP_TRIG = 0xE6;
sfr ISP_CONTR = 0xE7;
uchar code table[]="km/h km";
uchar code table1[]=" km";
sbit rs=P2^4; // 液晶
sbit rw=P2^5; // 液晶
sbit en=P2^6; // 液晶
uint aa,time,s1,s11;
uchar num,bb,a,b,up,down;
uchar IRCOM[7];//红外数组
unsigned long int quan,s2,s21; //
sbit ACC0 = ACC^0; //1302
sbit ACC7 = ACC^7; //1302
sbit IRIN = P3^2; //红外接收器数据线
sbit T_CLK = P3^6; /*实时时钟时钟线引脚 */
sbit T_IO = P3^4; /*实时时钟数据线引脚 */
sbit T_RST = P3^5; /*实时时钟复位线引脚 */
uchar flag;
uchar sec, min, hour;
void Write_DS1302Init(void);
void display();
void delayhw(uchar x); //x*0.14MS 红外延时
void delay(uint z);//液晶延时
/********************************************************************
* 功能 : EEPROM的扇区擦除
* 输入 : Address(擦除扇区的地址)
***********************************************************************/
void ISP_ERASE(Address)
{
ISP_ADDRL = Address;
ISP_ADDRH = Address >> 8;
ISP_CONTR = 0x81;
ISP_CMD = ISP_SECTOR_ERASE;
ISP_TRIG = 0x46; //PDF手册中说先像 ISP_TRIG 中写入 0x46, 然后写入 0xb9
ISP_TRIG = 0xb9;
_nop_();
_nop_();
}
/********************************************************************
* 输入 : Address(想要读取EEPROM的地址)
*********************************************************************/
uint ISP_READ(Address)
{
uchar Read_Data;
ISP_ADDRL = Address;
ISP_ADDRH = Address >> 8;
// EA = 0;
ISP_CONTR = 0x81;
ISP_CMD = ISP_BYTE_READ;
ISP_TRIG = 0x46;
ISP_TRIG = 0xb9;
_nop_();
_nop_();
Read_Data = ISP_DATA;
return Read_Data;
}
/********************************************************************
* 输入 : Address为编程的地址,Data_temp为想要编程的值
***********************************************************************/
void ISP_PROGRAM(Address, Data_temp)
{
ISP_DATA = Data_temp;
ISP_ADDRL = Address;
ISP_ADDRH = Address >> 8;
ISP_CONTR = 0x81;
ISP_CMD = ISP_BYTE_PROGRAM;
ISP_TRIG = 0x46;
ISP_TRIG = 0xb9;
_nop_();
_nop_();
}
void delay(uint z) //液晶延时
{
uint x,y;
for(x=110;x>0;x--)
for(y=z;y>0;y--);
}
void write_com(uchar com) //液晶写命令
{
rs=0;
P0=com;
delay(1);
en=1;
delay(1);
en=0;
}
void write_data(uchar date) //液晶写数据
{
rs=1;
P0=date;
delay(1);
en=1;
delay(1);
en=0;
}
void init()
{
quan=0;
en=0;
rw=0;
aa=0;
up=0;
down=0;
flag=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
EA=1; //开总中断
EX0=1; //开外部中断0
IT0=1; //外部中断设为下降沿触发
ET0=1; // 开定时器0中断
TMOD=0x11;//定时器0设定为定时器模式
TH0=(65536-5000)/256;
TL0=(65536-5000)%256; //定时器0装初值5ms
TR0=1;//启动定时器0
EX1=1; //开外部中断1
IT1=1; //外部中断1设为下降沿触发
flag=0;
}
void v_RTInputByte(uchar ucDa) //往DS1302写入1Byte数据
{
uchar i;
ACC = ucDa;
T_RST = 1;
for(i=8; i>0; i--)
{
T_IO = ACC0;
T_CLK = 1;
T_CLK = 0;
ACC = ACC >> 1;
}
}
uchar uc_RTOutputByte(void) //读取1byte数据
{
uchar i;
T_RST = 1;
for(i=8; i>0; i--)
{
ACC = ACC >>1;
// T_IO=1;
ACC7 = T_IO;
T_CLK = 1;
T_CLK = 0;
}
return(ACC);
}
void v_W1302(uchar ucAddr, uchar ucDa) //输入 : ucAddr: DS1302地址, ucDa: 要写的数据
{
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(ucAddr); // 写地址
_nop_();
_nop_();
v_RTInputByte(ucDa); // 写1Byte数据
T_CLK = 1;
T_RST = 0;
}
uchar uc_R1302(uchar ucAddr) // 读取DS1302某地址的数据
{
uchar ucDa;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(ucAddr); //写地址,命令
_nop_();
_nop_();
ucDa = uc_RTOutputByte(); //读1Byte数据
T_CLK = 1;
T_RST = 0;
return(ucDa);
}
void keyscan() //设置时钟的键盘扫描程序
{
if(flag!=0)
{
while(flag)
{
if(flag==1)
{
write_com(0x80+0x47);
write_com(0x0f);
}
if(flag==2)
{
write_com(0x80+0x44);
}
if(flag==3)
{
write_com(0x80+0x41);
} //
if(up==1)
{
if(flag==1)
{
sec++;
if(sec==60)
sec=0;
}
if(flag==2)
{
min++;
if(min==60)
min=0;
}
if(flag==3)
{
hour++;
if(hour==24)
hour=0;
}
up=0;
display();
}
if(down==1)
{
if(flag==1)
{
sec--;
if(sec==255)
sec=59;
}
if(flag==2)
{
min--;
if(min==255)
min=59;
}
if(flag==3)
{
hour--;
if(hour==255)
hour=23;
}
down=0;
display();
}
// display();
}
Write_DS1302Init();
}
}
uchar dectobcd(uchar dec)// DEC码转换为BCD码
{
uchar bcd;
bcd = 0;
while(dec >= 10)
{
dec -= 10;
bcd++;
}
bcd <<= 4;
bcd |= dec;
return bcd;
}
uchar bcdtodec(uchar bcd) // BCD码转换为DEC码
{
uchar data1;
data1 = bcd & 0x0f; //取BCD低4位
bcd = bcd & 0x70; //剔除BCD的最高位和低4位。
data1 += bcd >> 1;
data1 += bcd >> 3; //用位移代替乘法运算
return data1;
}
void Write_DS1302Init(void)
{
sec=dectobcd(sec);
min=dectobcd(min);
hour=dectobcd(hour);
v_W1302(0x8e,0);
v_W1302(0x80,sec); //写入秒;
v_W1302(0x82,min); //写入分
v_W1302(0x84,hour); //写入小时
}
void display() //1302显示
{
uchar hourshi,hourge,minshi,minge,secshi,secge;
hourshi=hour/10;
hourge=hour%10;
minshi=min/10;
minge=min%10;
secshi=sec/10;
secge=sec%10;
write_com(0x80+0x40);
write_data(0x30+hourshi);
write_data(0x30+hourge);
write_data(0x3a);
write_data(0x30+minshi);
write_data(0x30+minge);
write_data(0x3a);
write_data(0x30+secshi);
write_data(0x30+secge);
}
void Run_DS1302(void) // 读出DS1302中的数据,并在液晶上进行显示
{ uchar dd;
for(dd=10;dd>0;dd--) //加入循环,防止速度变化太快,不方便度数
{
sec = bcdtodec(uc_R1302(0x81)); //读出DS1302中的秒;
min = bcdtodec(uc_R1302(0x83)); //读出DS1302中的分
hour = bcdtodec(uc_R1302(0x85)); //读出DS1302中的小时
if(hour==0) //时间校准,每天0:30:30减少15s
{
if(min==30)
{
if(sec==45)
{
while(sec)
{
sec = bcdtodec(uc_R1302(0x81));
}
sec=46;
Write_DS1302Init();
}
}
}
display();
keyscan();
}
}
void write_su(uint dat)//速度显示
{
uchar shi,ge;
shi=dat%100/10;
ge=dat%10;
write_com(0x80);
write_data(0x20);
write_com(0x81);
write_data(0x30+shi);
write_data(0x30+ge);
}
void write_s1(uint s1)//一次里程显示
{
uchar bai,shi,ge,dian;
// wan=s1/10000; //s1为一次路程,一般不会超过几百km,故无万千位
// qian=s1%10000/1000;
bai=s1%10000/1000;
shi=s1%1000/100;
ge=s1%100/10;
dian=s1%10;
write_com(0x89);
write_data(0x30+bai);
write_data(0x30+shi);
write_data(0x30+ge);
write_data(0x2e);
write_data(0x30+dian);
}
void write_s2(uint s2)//总里程显示
{
uchar wan,qian,bai,shi,ge,dian;
wan=s2%1000000/100000;
qian=s2%100000/10000;
bai=s2%10000/1000;
shi=s2%1000/100;
ge=s2%100/10;
dian=s2%10;
write_com(0x80+0x49);
write_data(0x30+wan);
write_data(0x30+qian);
write_data(0x30+bai);
write_data(0x30+shi);
write_data(0x30+ge);
write_data(0x2e);
write_data(0x30+dian);
}
void main()
{
init();
write_com(0x83);
for(num=0;num<13;num++) //先显示固定的km/h km
{
write_data(table[num]);
delay(2);
}
write_com(0x80+0x46);
for(num=0;num<10;num++) //先显示固定的km
{
write_data(table1[num]);
delay(2);
}
// ISP_ERASE(0x2000); //
// ISP_PROGRAM(0x2000, 0x05);
// ISP_ERASE(0x2c01);
// ISP_PROGRAM(0x2c01, 0x40);
a=ISP_READ(0x2003);
delay(20);
b=ISP_READ(0x2207);
s21=a*256+b; //读出的两个八位合成一个十六位
// s21=248; //要改,用来清空第一次写入eeprom的数据
write_s2(s21); //显示开机总里程
while(1)
{
s1=quan*0.65; //s1为一次路程 这里一圈按0.65m算
if(s11!=s1) //如果s1发生了变化
{
s2=s21+s1; //s2为总里程 ,s21为开机读出的里程
a=s2/256; //s2为16位,把其分为两个八位分别写入存储器
b=s2%256;
ISP_ERASE(0x2003); // 扇区擦除。无字节擦除
ISP_PROGRAM(0x2003, a);
delay(20);
ISP_ERASE(0x2207);
ISP_PROGRAM(0x2207, b); // 将两组数据写向不同扇区
write_s2(s2);
}
s11=s1;
write_s1(s1); // 一次路程显示
delay(100);
write_com(0x81); //换行
write_su(bb); //速度显示
bb=0;
Run_DS1302();
}
}
void timer0() interrupt 1
{
TH0=(65536-5000)/256;
TL0=(65536-5000)%256; //定时器0装初值5ms
aa++;
}
void exter1() interrupt 2
{
if(aa>=200)//即车轮转一圈时间超过1秒,认为速度为零
bb=0;
if(aa<200)
{
time=aa*5;//定时器为5ms,为避免带小数点,此乃为正常时间的1000倍
bb=65*36/time;//65为车圈周长的100倍,单位为米,bb为整型变量,舍掉速度小数点
}
aa=0;
quan++;
}
void exter0() interrupt 0
{
unsigned char j,k,N=0;
EX1 = 0;
delayhw(15);
if (IRIN==1)
{ EX1 =1;
return;
}
//确认IR信号出现
while (!IRIN) //等IR变为高电平,跳过9ms的前导低电平信号。
{delayhw(1);}
for (j=0;j<4;j++) //收集四组数据
{
for (k=0;k<8;k++) //每组数据有8位
{
while (IRIN) //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
{delayhw(1);}
while (!IRIN) //等 IR 变为高电平
{delayhw(1);}
while (IRIN) //计算IR高电平时长
{
delayhw(1);
N++;
if (N>=30)
{ EX1=1;
return;} //0.14ms计数过长自动离开。
} //高电平计数完毕
IRCOM[j]=IRCOM[j] >> 1; //数据最高位补“0”
if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;} //数据最高位补“1”
N=0;
}//end for k
}//end for j
if (IRCOM[2]!=~IRCOM[3])
{ EX1=1;
return; }
IRCOM[5]=IRCOM[2] & 0x0F; //取键码的低四位
IRCOM[6]=IRCOM[2] >> 4; //右移4次,高四位变为低四位
if(IRCOM[5]>9)
{ IRCOM[5]=IRCOM[5]+0x37;}
else
IRCOM[5]=IRCOM[5]+0x30;
if(IRCOM[6]>9)
{ IRCOM[6]=IRCOM[6]+0x37;}
else
IRCOM[6]=IRCOM[6]+0x30;
if(IRCOM[6]==0x34)
{
if(IRCOM[5]==0x35)
{
flag=flag+1;
if(flag==4)
{
write_com(0x0c);
flag=0;
}
}
}
if(IRCOM[6]==0x34)
{
if(IRCOM[5]==0x34)
{
down=1;
}
}
if(IRCOM[6]==0x34)
{
if(IRCOM[5]==0x30)
{
up=1;
}
}
EX1 = 1;
return;
}
void delayhw(unsigned char x) //x*0.14MS 红外延时
{
unsigned char i;
while(x--)
{
for (i = 0; i<13; i++) {}
}
}