|
求助大神,小弟找了一段源程序,但是有点问题,求助大神帮忙。
源程序:
#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).
求解救
|
|