标题: 单片机做的自行车里程表,求助,求助。 [打印本页]

作者: yxy294691582    时间: 2016-4-20 12:31
标题: 单片机做的自行车里程表,求助,求助。
求助大神,小弟找了一段源程序,但是有点问题,求助大神帮忙。
源程序:
#include<reg52.h>
#define         uchar unsigned char

/****************************************************************
引脚定义:
P20=SW1   时钟设置时更改“时”,直径设置时更改十位
P21=SW2           时钟设置时更改“分”的十位,直径设置时更改个位
P22=SW3    时钟设置时更改“分”的个位
P23=Enter 确认更改设置
P32=Disp  正常工作时更改显示模式
****************************************************************************/
sbit P10=P1^0;        //独立键盘端口
sbit P11=P1^1;
sbit P12=P1^2;
sbit P13=P1^3;
sbit P33=P3^3;        //改变显示内容键
sbit RS=P3^7;        //LCDRS脚
sbit RW=P3^6;        //LCDRW脚
sbit E=P3^4;        //LCDE脚
sbit busy=P0^7;
sbit P35=P3^5;        //霍尔口
/****************************************************************
变量定义:
i      延时变量
qsls      圈数临时变量,用于判断里程显示选用m还是km作为单位
qs     圈数
sj     累计行驶时间,单位为秒
lc              累计里程
pjsd    平均速度
ssji    定时器T1 20ms中断次数,用于计算速度等
sji             本次速度对应的20ms中断次数
sjiold          上次速度对应的20ms中断次数
sd2            当前速度
tc            轮胎周长

*s                  字符串显示子程序字符指针
line          字符串显示子程序列数
row                  字符串显示子程序行数
com                  写控制字
dat                  显示码字
gw                  累计里程、当前速度、累计时间、平均速度的个位
sw                  累计里程、当前速度、累计时间、平均速度的十位
bw                  累计里程、当前速度、累计时间、平均速度的百位
qw                  累计里程、当前速度、累计时间、平均速度的千位
ww                  累计里程、累计时间的万位
sww                  累计里程、累计时间的十万位
ssj    定时器T0 50ms中断次数,每20次sj加1
cgw                  当前时间(时钟)的个位
csw                  当前时间(时钟)的十位
cbw                  当前时间(时钟)的百位
cqw                  当前时间(时钟)的千位
cww                  当前时间(时钟)的万位
csww          当前时间(时钟)的十万位
cww2          当前时间(时钟)的辅助万位
MODE          显示模式
tr1                  轮胎设置变量1(十位)
tr2                  轮胎设置变量2(个位)

****************************************************************************/
unsigned int i,qsls;
unsigned long qs,sj,lc,pjsd,ssji,sji,sjiold,sd2,tc;
uchar *s,line,row,com,dat,gw,sw,bw,qw,ww,sww,ssj,cgw,csw,cbw,cqw,cww,csww,cww2,MODE,tr1,tr2;

/***********************************void wait()*****************************
    该函数的作用是对LCD进行检测,看LCD是否处于忙的状态.当bflag=1时表示忙,
此时不可以向LCD进行读写操作.而当busy=0时,表示可以向它读写数据.
****************************************************************************/
void wait()
{P0=0xff;
RW=1; RS=0;                  
do{E=0;E=1;}while(busy==1);
}

/**************************************void dispone()*******************************
    该函数的作用是向LCD写入数据并显示出来.
***********************************************************************************/
void dispone(dat)
{P0=dat;
RW=0; RS=1;                 
E=0; E=1;                    
wait();
}

/**********************************void wrcom()*******************************
      该函数的作用是向LCD写入控制字.
******************************************************************************/
void wrcom(com)
{P0=com;
RW=0; RS=0;                  
E=0; E=1;   
wait();
}

/***************************************void init_LCD()*******************************
     该函数的作用是初始化LCD.
*****************************************************************************************/
void init_LCD()
{wrcom(0x01);        
wrcom(0x06);        
wrcom(0x38);        
wrcom(0x0c);      
}

/****************************************void dispmore()********************************
    该函数的作用是向LCD写入一串数据,并把数据串显示出来.
******************************************************************************************/
void dispmore(line,row,uchar dat[],i) //格式为dispmore(第几行,第几列,开始要显示的字符地址,显示几个字符);
{uchar com;
s=dat;
if(line==1)                 
{com=0x80+row-1;           
wrcom(com);
while((i--)!=0&&com<=0x8f)   
        {dispone(*s);
    com++;
        s++;
        }
}
else
{com=0xc0+row-1;            
wrcom(com);
while((i--)!=0&&com<=0xcf)      
        {dispone(*s);
        com++;
        s++;
        }
}
}

/****************************************void ttimep()********************************
累计行驶时间数据处理及显示子程序
******************************************************************************************/
void ttimep()
{

sww=sj/36000;
ww=sj%36000/3600;
qw=sj%3600/600;
bw=sj%600/60;
sw=sj%60/10;
gw=sj%10;
wrcom(0xc1);                                  
dispone('T');                                  
dispone('i');                                   
dispone('m');                                  
dispone('e');
dispone(' ');
dispone(' ');                                  
dispone(sww+0x30);
dispone(ww+0x30);
dispone(':');                                  
dispone(qw+0x30);
dispone(bw+0x30);
dispone(':');                                  
dispone(sw+0x30);
dispone(gw+0x30);
}

/****************************************void timer1()********************************
T1中断服务子程序,每20ms中断一次,ssji加1,根据公式S=tc*qs和V=tc/ssj计算累计里程和
******************************************************************************************/
void timer1() interrupt 3       
{                                                               
ssji++;
TH1=0xb1;
TL1=0xdf;
}

/****************************************void lcp()********************************
累计里程数据处理和显示子程序,若<999m则单位为m,若>999m则单位为km
******************************************************************************************/                                                            
void lcp()                                          
{
qsls=100000/tc;               
if(qs>qsls){
sww=qs*tc/10000000;
ww=qs*tc%10000000/1000000;
qw=qs*tc%1000000/100000;
bw=qs*tc%10000000/10000;
sw=qs*tc%10000/1000;
wrcom(0x81);
dispone('S');
dispone(' ');
dispone(' ');
dispone(' ');
dispone(' ');
dispone(sww+0x30);
dispone(ww+0x30);
dispone(qw+0x30);
dispone('.');
dispone(bw+0x30);
dispone(sw+0x30);
dispone(' ');
dispone('k');
dispone('m');
}
else{
qw=qs*tc%100000/10000;
bw=qs*tc%10000/1000;
sw=qs*tc%1000/100;
gw=qs*tc%100/10;
wrcom(0x81);                                  
dispone('S');                                  
dispone(' ');
dispone(' ');
dispone(' ');
dispone(' ');
dispone(' ');
dispone(' ');
dispone(qw+0x30);
dispone(bw+0x30);
dispone(sw+0x30);
dispone('.');
dispone(gw+0x30);
dispone(' ');
dispone('m');
}
}

/****************************************void pjsdp()********************************
平均速度数据处理及显示子程序
******************************************************************************************/
void pjsdp()                                 
{
pjsd=qs*tc*36/sj;
qw=pjsd%100000/10000;
bw=pjsd%10000/1000;
sw=pjsd%1000/100;
gw=pjsd%100/10;
wrcom(0x82);
dispone('V');
dispone('a');
dispone(' ');
dispone(' ');
dispone(qw+0x30);
dispone(bw+0x30);
dispone('.');
dispone(sw+0x30);
dispone(gw+0x30);
dispone(' ');
dispone('k');
dispone('m');
dispone('/');
dispone('h');
}

/****************************************void sdp()********************************
当前速度数据处理及显示子程序
******************************************************************************************/
void sdp()                                       
{
if(sji!=0)
sd2=tc*1800/sji;
else sd2=0;
qw=sd2%100000/10000;
bw=sd2%10000/1000;
sw=sd2%1000/100;
gw=sd2%100/10;
wrcom(0x82);
dispone('V');
dispone(' ');
dispone(' ');
dispone(' ');
dispone(qw+0x30);
dispone(bw+0x30);
dispone('.');
dispone(sw+0x30);
dispone(gw+0x30);
dispone(' ');
dispone('k');
dispone('m');
dispone('/');
dispone('h');
}

/****************************************void clkp()********************************
当前时间(时钟)数据处理及显示子程序
******************************************************************************************/
void clkp()
{
wrcom(0xc4);
dispone(csww+0x30);
dispone(cww+0x30);
dispone(':');
dispone(cqw+0x30);
dispone(cbw+0x30);
dispone(':');
dispone(csw+0x30);
dispone(cgw+0x30);
}

/****************************************void int0()********************************
外部中断0(霍尔)中断服务程序
*****************************************************************************************/
void int0() interrupt 0                       
{
EX0=0;                               
qs++;                                                        //圈数+1
TR1=0;
sjiold=sji;                                            //停止T1计时
sji=ssji;                       
TH1=0xb1;                                                //重置T1定时常数
TL1=0xdf;
ssji=0;
TR1=1;                                                    //T1重新开始计时
switch(MODE)
{
   case 0:wrcom(0x01);lcp();ttimep();break;
   case 1:wrcom(0x01);sdp();pjsdp();break;
   case 2:wrcom(0x01);dispmore(1,5,"Time Now",8);clkp();break;
   default:break;
}
for(i=0;i<32000;i++);
IE0=0;
EX0=1;
}

/****************************************void int1()********************************
显示模式选择按钮(Disp)中断服务子程序
******************************************************************************************/
void int1() interrupt 2                       
{
EX1=0;
if(++MODE>3) MODE=0;
switch(MODE)
{
   case 0:wrcom(0x01);lcp();ttimep();break;
   case 1:wrcom(0x01);sdp();pjsdp();break;
   case 2:wrcom(0x01);dispmore(1,5,"Time Now",8);clkp();break;
   default:break;
}
for(i=0;i<32000;i++);
IE1=0;
EX1=1;
}

/****************************************vvoid timer0()********************************
T0中断服务子程序,主要用于计算累计行驶时间,50ms一次中断,每20次sj++,更新累计行驶时间(单位秒)
*******************************************************************************************/
void timer0() interrupt 1               
{                                                       
TH0=0x3c;
TL0=0xb0;
if(++ssj>19)
{
sj++;
ssj=0;
cgw++;
if(cgw>9){cgw=0;csw++;
           if(csw>5){csw=0;++cbw;
                                        if(cbw>9){cbw=0;++cqw;
                                                                        if(cqw>5){cqw=0;
                                                                                                        cww2++;if(cww2>23)cww2=0;csww=cww2/10;cww=cww2%10;                                                                                                               
                                                                                                                        }
                                                                                        }
                                                        }
                        }

if (MODE==0) {lcp();ttimep();}
if (MODE==2) clkp();
}
}

/****************************************void main()********************************
主程序,初始化LCD,显示欢迎信息,更改时钟、直径设置,开中断、计时器等
******************************************************************************************/
void main()
{
init_LCD();
dispmore(1,1,"-Digital  Meter-",16);
for(i=0;i<25000;i++);
dispmore(2,1,"   Welcome      ",16);
for(i=0;i<25000;i++);
dispmore(2,1,"   Welcome.     ",16);
for(i=0;i<25000;i++);
dispmore(2,1,"   Welcome..    ",16);
for(i=0;i<25000;i++);
dispmore(2,1,"   Welcome...   ",16);
for(i=0;i<25000;i++);
dispmore(2,1,"   Welcome....  ",16);
for(i=0;i<25000;i++);
dispmore(2,1,"   Welcome..... ",16);
for(i=0;i<30000;i++);
wrcom(0x01);
MODE=0;
qs=0;


P1=0xff;  //键盘口
cgw=csw=cbw=cqw=cww=csww=cww2=0;
wrcom(0x01);
dispmore(1,5,"Set Time",8);
clkp();
while(1){
if(P13==0){for(i=0;i<4000;i++);if(P13==0)break;}
if(P10==0){for(i=0;i<4000;i++);if(P10==0){cww2++;if(cww2>23)cww2=0;csww=cww2/10;cww=cww2%10;clkp();for(i=0;i<32000;i++);}}
if(P11==0){for(i=0;i<4000;i++);if(P11==0){if(++cqw>5)cqw=0;clkp();for(i=0;i<32000;i++);}}
if(P12==0){for(i=0;i<4000;i++);if(P12==0){if(++cbw>9)cbw=0;clkp();for(i=0;i<32000;i++);}}
}

for(i=0;i<30000;i++);

tr1=5;
tr2=5;
wrcom(0x01);
dispmore(1,1,"Set Bike Tire L=",16);
wrcom(0xc9);
dispone('c');
wrcom(0xca);
dispone('m');
P1=0xff;
wrcom(0xc6);dispone(tr1+0x30);
wrcom(0xc7);dispone(tr2+0x30);
while(1){
if(P10==0){for(i=0;i<4000;i++);if(P10==0){if(++tr1>9)tr1=0;wrcom(0xc6);dispone(tr1+0x30);for(i=0;i<32000;i++);}}
if(P11==0){for(i=0;i<4000;i++);if(P11==0){if(++tr2>9)tr2=0;wrcom(0xc7);dispone(tr2+0x30);for(i=0;i<32000;i++);}}
if(P13==0){for(i=0;i<4000;i++);if(P13==0)break;}
}
tc=3.14*(10*tr1+tr2);



TMOD=0x11;                                           //T0和T1均是定时器方式
TH0=0x3c;                                           //置定时常数
TL0=0xb0;
TH1=0xb1;
TL1=0xdf;
IT0=1;                                                   //外部中断触发方式均是边缘触发
IT1=1;
IE=0x9f;                                           //开中断
IP=0x02;
TR0=1;                                                   //T0和T1开始计时
TR1=1;
P35=1;                                                   //霍尔口
IE0=0;
wrcom(0x01);
for (;;);

}

编译结果:
Build target 'Target 1'
compiling 总程序.c...
linking...
*** WARNING L15: MULTIPLE CALL TO SEGMENT
    SEGMENT: ?PR?_DISPMORE?譥程序
    CALLER1: ?PR?INT0?譥程序
    CALLER2: ?PR?INT1?譥程序
*** WARNING L15: MULTIPLE CALL TO SEGMENT
    SEGMENT: ?PR?_DISPMORE?譥程序
    CALLER1: ?PR?INT1?譥程序
    CALLER2: ?C_C51STARTUP
Program Size: data=103.0 xdata=0 code=4190
creating hex file from "总程序"...
"总程序" - 0 Error(s), 2 Warning(s).


求解救

作者: yxy294691582    时间: 2016-4-20 12:32
顶·~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
作者: admin    时间: 2016-4-20 18:15
"总程序" - 0 Error(s), 2 Warning(s).
0个错误 程序是没有问题的  2个警告可以忽略.
作者: yxy294691582    时间: 2016-4-20 23:27
admin 发表于 2016-4-20 18:15
"总程序" - 0 Error(s), 2 Warning(s).
0个错误 程序是没有问题的  2个警告可以忽略.

谢谢~但我用Protus仿真也提示错误,[SPICE]H1:unknown controlling source(null),我百度翻译是;未知控制源错误。这怎么弄啊?
求教大神!!!!!
作者: 1678    时间: 2016-4-21 09:09
论坛有帖子啊  你找自行车就可找到
作者: yxy294691582    时间: 2016-4-21 10:25
1678 发表于 2016-4-21 09:09
论坛有帖子啊  你找自行车就可找到

谢谢                  
作者: YBZYBZ    时间: 2016-5-2 15:06
这有个AT89C2051自行车里程表 新建文件夹.rar (34.74 KB, 下载次数: 47)




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1