?? 060305.c
字號:
//幾點說明:關機可以讓單片機真正休眠進入真正低功耗狀態,但是由于液晶一直有電供應且不知其功耗,故能省多少電并不知道,當然可以通過一個管腳通過
//控制三極管的基極來給液晶供電,關機時給其斷電
#include <at89x52.h>
#include"LCD1602.h"
#include"I2C.h"
sfr P1Port = 0x90;
sbit led1=P3^7;
sbit led2=P3^6;
sbit led3=P3^5;
sbit led4=P3^4;
sbit lcd_on=P2^7;//P2^7控制lcd的開關
//######################################################################################################################################
//I2C程序
//######################################################################################################################################
unsigned char wheel_radi;
unsigned short sec_add1;
unsigned char second1;
unsigned char minute;
unsigned char hour;
unsigned short sec_add2; //ms
unsigned int cal_sec_add2; //
unsigned int mil_temp;
unsigned int miles; //最大值為65536,即655.36km
unsigned int speed;
unsigned int max_speed;
unsigned int time_round; //保存一個時間里面包含了幾個36ms
unsigned int temp_radi;
unsigned int totalmile=0;
unsigned int wspeed;//存放圈速度
unsigned char butt_down;
bit speedflag;
bit firstime_flag;//消除速度第一次效應
unsigned char timearray[]={0x30,0x30,0x3a,0x30,0x30,0x3a,0x30,0x30,0xff};
unsigned char speedarray[]={0x30,0x30,0x2e,0x30,0x6b,0x6d,0x2f,0x68,0xff};
unsigned char milesarray[]={0x30,0x30,0x30,0x2e,0x30,0x30,0x6b,0x6d,0xff};
unsigned char wspeedarray[]={0x30,0x30,0x30,0x72,0x2f,0x6d,0x69,0x6e,0xff};
void Delay1ms(unsigned char count)
{
unsigned char i,j;
for(i=0;i<count;i++)
for(j=0;j<33;j++);
}
void inttial_reg()
{
max_speed=0;
speedflag=0;
firstime_flag=0;
sec_add1=0;
second1=0;
minute=0;
hour=0; //時、分、秒、毫秒計數器,用來寄存行駛時間
sec_add2=0;
cal_sec_add2=0;
mil_temp=0;
miles=0;
speed=0;
time_round=0;
temp_radi=180*wheel_radi;
}
void initiall()
{
//warm up 延時
lcd_on=1;
Delay1ms(60);
sta();
wri_one_char(0xa0);
ack();
wri_one_char(0x02);
ack();
sta();
wri_one_char(0xa1);
ack();
wheel_radi=read();
no_ack();
stop();
inttial_reg();
TMOD=0x11;
TL0=0xb0;
TH0=0x3c;
TL1=0x30;
TH1=0xf8; //打開外中斷0,定時器0和定時器1、總中斷的中斷允許
TCON=0x01; //將外中斷0設置為跳變觸發方式
//下面從外部存儲器中讀入車輪周長的值
//將中斷設為下降沿,定時器模式設為1
//將定時器0用來計時,定時器1用來計相鄰脈沖的時間間隔
//如果下一脈沖還沒有到來而已經經過很長時間,則可以將速度置零
//$$$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
LCD_Initial();
}
void timer0 (void) interrupt 1 //計時程序,時間數據輸出到LCD上
{
TL0=0xb0;
TH0=0x3c;
if (sec_add1==19) //定時時長50ms
{
sec_add1=0;
if (second1==59)
{
second1=0;
if (minute==59)
{
minute=0;
if (hour==9)
{
hour=0;
}
else
{
hour++;
}
}
else
{
minute++;
}
}
else
{
second1++;
}
}
else
{
sec_add1++;
}
}
void timer1 (void) interrupt 3 //定時器1的中斷,對轉一圈的時間進行計時
{
TL1=0x30;
TH1=0xf8; //定時時長2ms
sec_add2++;
if(sec_add2>2500){speed=0;wspeed=0;speedflag=1;}
else{speedflag=0;}
}
void pulse_in (void) interrupt 0
{
//將當前寄存器數值保存并置零,同時開啟定時器
//Delay1ms(100);
mil_temp+=wheel_radi; //因為wheel_radi是以厘米為單位的,而且我們的顯示精度到0.01km(即10m),故要和1000進行比較
if (mil_temp>=1000)
{
mil_temp-=1000;
miles++; //這里miles也是取的整數,單位也是10m,盡管最后在lcd上顯示的是km/s
}
cal_sec_add2=sec_add2;
sec_add2=0;
if(speedflag==0)
{
speed=temp_radi/cal_sec_add2;
wspeed=30000/cal_sec_add2;
} //*************#########################*******************由于簡化運算,這里的精度不可能很高,
else {
speed=0;
wspeed=0;
} //這里速度的單位是:百米/小時
if(firstime_flag==0){firstime_flag=1;speed=0;wspeed=0;}//消除速度第一次效應
if(speed>max_speed) max_speed=speed;
IE0=0; //清中斷標志
}
//時間格式: hour(1bit) : minute (int) : second1 (int)
//速度: speed(3bits) 百米/小時------->**.*
//里程: miles 十米------>km .**
//這里很重要的一件事情就是將數據形式轉換為可以送去顯示的形式
void display()
{
timearray[1]=hour+0x30;
timearray[3]=minute/10+0x30;
timearray[4]=minute%10+0x30;
timearray[6]=second1/10+0x30;
timearray[7]=second1%10+0x30;
speedarray[0]=speed/100+0x30;
speedarray[1]=(speed/10)%10+0x30;
speedarray[3]=speed%10+0x30;
milesarray[0]=miles/10000+0x30;
milesarray[1]=(miles/1000)%10+0x30;
milesarray[2]=(miles/100)%10+0x30;
milesarray[4]=(miles/10)%10+0x30;
milesarray[5]=miles%10+0x30;
wspeedarray[0]=wspeed/100+0x30;
wspeedarray[1]=(wspeed/10)%10+0x30;
wspeedarray[2]=wspeed%10+0x30;
}
unsigned int cal_total_miles()
{
unsigned int stoa=0;
sta();
wri_one_char(0xa0);
ack();
wri_one_char(0x00);
ack();
sta();
wri_one_char(0xa1);
ack();
stoa=read();
no_ack();
stop();
stoa=stoa<<8;
sta();
wri_one_char(0xa0);
ack();
wri_one_char(0x01);
ack();
sta();
wri_one_char(0xa1);
ack();
stoa+=read();
no_ack();
stop();
stoa+=(miles/10);
return stoa;
}
void stoa_miles()
{
unsigned int stoa=0;
unsigned char stob;
stoa=cal_total_miles();
//上面程序將數據從存儲器中讀出加上當前里程,下面將數據回存到存儲器中
sta();
wri_one_char(0xa0);
ack();
wri_one_char(0x01);
ack();
stob=stoa&0x00ff;
wri_one_char(stob);
ack();
stop();
Delay1ms(100);
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
sta();
wri_one_char(0xa0);
ack();
wri_one_char(0x00);
ack();
stob=stoa>>8;
wri_one_char(stob);
ack();
stop();
Delay1ms(100);
}
void disp_MILES_MSpeed() //顯示最大速度以及總里程
{
unsigned int MilTemp;
unsigned char chartemp[9];
LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏
MilTemp=cal_total_miles();
chartemp[8]=0xff;
chartemp[4]=0x2e;
chartemp[6]=0x6b;
chartemp[7]=0x6d;
chartemp[5]=MilTemp%10+0x30;
MilTemp/=10;
chartemp[3]=MilTemp%10+0x30;
MilTemp/=10;
chartemp[2]=MilTemp%10+0x30;
MilTemp/=10;
chartemp[1]=MilTemp%10+0x30;
MilTemp/=10;
chartemp[0]=MilTemp%10+0x30;
GotoXY(4,0);
Print(chartemp);
//上面一段顯示了總里程,下面一段將顯示行駛中的最大速度
Delay1ms(100);
MilTemp=max_speed;
chartemp[8]=0xff;
chartemp[2]=0x2e;
chartemp[4]=0x6b;
chartemp[5]=0x6d;
chartemp[6]=0x2f;
chartemp[7]=0x68;
chartemp[3]=MilTemp%10+0x30;
MilTemp/=10;
chartemp[1]=MilTemp%10+0x30;
MilTemp/=10;
chartemp[0]=MilTemp%10+0x30;
GotoXY(4,1);
Print(chartemp);
}
void disp_wheel_radi()
{
unsigned char tempchar2;
unsigned char tempchatable[]={0x47,0x52,0x49,0x54,0x48,0x3a,0xff};
LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏
Delay1ms(100);
GotoXY(5,0);
Print(tempchatable);
tempchar2=wheel_radi;
tempchatable[2]=tempchar2%10+0x30;
tempchar2/=10;
tempchatable[1]=tempchar2%10+0x30;
tempchar2/=10;
tempchatable[0]=tempchar2%10+0x30;
tempchatable[3]=0x63;
tempchatable[4]=0x6d;
tempchatable[5]=0xff;
GotoXY(5,1);
Print(tempchatable);
}
void chan_radi() //改變車輪周長
{
bit changed_flag=0;
disp_wheel_radi();
//將當前周長顯示在lcd上
EA=0;
do
{
if(!(P1Port&0x04))//如果發現UP鍵被按下
{
Delay1ms(100);//延時進行前沿消抖
if(!(P1Port&0x04))//確認UP鍵確實被按下一次
{
while(!(P1Port&0x04));//等待UP按鍵彈起
Delay1ms(100);//后沿消抖
wheel_radi++; //車輪周長增加1
changed_flag=1;//判斷車輪周長變化了的標志
if(wheel_radi>230) wheel_radi=180;
if(wheel_radi<180) wheel_radi=180;//限制車輪周長在180~230cm之間
disp_wheel_radi();//將車輪周長在lcd上顯示出來
}
}
if(!(P1Port&0x02))//判斷MODE鍵是否被按下
{
Delay1ms(100);
led1=1;
if(!(P1Port&0x02))
{
while(!(P1Port&0x02));
Delay1ms(100);
break;
}
}
}while(1);
if(changed_flag)
{
changed_flag=0;
sta();
wri_one_char(0xa0);
ack();
wri_one_char(0x02);
ack();
wri_one_char(wheel_radi);
ack();
stop();
Delay1ms(100);
miles=0x0000;
sta();
wri_one_char(0xa0);
ack();
wri_one_char(0x00);
ack();
wri_one_char(0x00);
ack();
stop();
Delay1ms(100);
sta();
wri_one_char(0xa0);
ack();
wri_one_char(0x01);
ack();
wri_one_char(0x00);
ack();
stop();
inttial_reg();
}
EA=1;
}
void main (void)
{
bit dispflag1;
bit dispflag2;
bit MODE2flag;
unsigned int to_time;
initiall();
//led1=0;//測試用句
//led2=0;//測試用句
//led3=0;//測試用句
//led4=0;//測試用句
MODE2flag=0;
IE=0x8f; //開中斷
TR0=1;
Delay1ms(1);
TR1=1;
do{
if(second1%2==0) dispflag1=0;
else dispflag1=1;
if(dispflag1!=dispflag2)
{
dispflag2=dispflag1;
display();
GotoXY(0,0);
Print(wspeedarray);
GotoXY(8,0);
Print(timearray);
GotoXY(0,1);
Print(speedarray);
GotoXY(8,1);
Print(milesarray);
}
butt_down=P1Port;
if(!(P1Port&0x01))//關機程序
{
EA=0;
for(to_time=6000;to_time>0;to_time--);
if(P1Port&0x01)break;
else{
stoa_miles();
LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏 shut down lcd
LCD_Write(0x08,1);//顯示關
PCON+=0x02;//進入掉電方式
}
}
else if(!(P1Port&0x02))//判斷是否MODE鍵被按下第一次,若是則進入下一步×××××××××××××××××××××××××
{
Delay1ms(100);//延時10ms,軟件消除前沿抖動
if(P1Port&0x02)break;//再次判斷,若MODE鍵沒有被按下了第一次則退出
else{ //確實MODE鍵被按下了第一次
while(!(P1Port&0x02));//等待第一次按鍵彈起后,再處理
Delay1ms(100);//延時10ms,軟件消除后沿抖動
disp_MILES_MSpeed();//顯示總里程和本次騎行最大速度
for(to_time=120;to_time>0;to_time--)//延時一段時間,同時在本段時間內判斷MODE鍵有沒有第二次被按下
{
Delay1ms(100);
if(!(P1Port&0x02))//這后面的過程基本重復×××××××××××××××××××××××××的過程
{
Delay1ms(100);
if(P1Port&0x02)break;
else{ //若確實MODE鍵被按下了第二次
while(!(P1Port&0x02));//等待第二次按鍵彈起
MODE2flag=1;
Delay1ms(100);//軟件消除后沿抖動
break;
}
}
}
}
}
if(MODE2flag){MODE2flag=0;chan_radi();}
}while(1);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -