|
2#
樓主 |
發(fā)表于 2023-9-3 17:38:21
|
只看該作者
//這是一個(gè)用于測(cè)量自行車車速、里程的程序,需要專門設(shè)計(jì)的硬件支持。
//電路包含幾大部分:脈沖采樣、DS1302以及89S52,5位LED數(shù)碼管顯示。
#include <reg52.h>
#include<intrins.h>
// 0 1 2 3 4 5 6 7 8 9 空 //碼表,不帶小數(shù)點(diǎn),最后兩位為顯示空和-
unsigned char code table[] = {0x77,0x14,0xb3,0xb6,0xd4,0xe6,0xe7,0x34,0xf7,0xf6,0x00,0x80};
unsigned char code table_D[] = {0x7f,0x1c,0xbb,0xbe,0xdc,0x6d,0xee,0x3c,0xff,0xfe,0x00,0x02,0x82,0xa2,0x80};//碼表,帶小數(shù)點(diǎn)。
unsigned long z=4294967295; // 2毫秒的個(gè)數(shù)
unsigned int time=65535,dc = 0;
unsigned int maxg,maxs,maxb,maxq,maxw,v,max; // 最后兩個(gè)是速度 和 最高車速
unsigned char gn = 1; // 功能切換
unsigned char g,s,b,q,w,temp,xhcs; //顯示推送位
unsigned long sg,ss,sb,sq,sw,ssw;
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
sbit T_CLK = P1^6; //實(shí)時(shí)時(shí)鐘時(shí)鐘線引腳
sbit T_IO = P1^5; //實(shí)時(shí)時(shí)鐘數(shù)據(jù)線引腳
sbit T_RST = P1^7; //實(shí)時(shí)時(shí)鐘復(fù)位線引腳
sbit p11 = P1^1;
sbit p10 = P1^0;
bit dw=1;
// **************************************************************************************************************
// * 名 稱:delay(void) *
// * 功 能:延遲 *
// * 輸 入:無(wú) *
// * 輸 出:無(wú) *
// **************************************************************************************************************
void delay(void)
{
unsigned char x,j;
for(j=0;j<2;j++)
for(x=0;x<=148;x++);
}
// **************************************************************************************************************
// * 名 稱:v_RTInputByte() *
// * 功 能:往DS1302寫入1Byte數(shù)據(jù) *
// * 輸 入:ucDa 寫入的數(shù)據(jù) *
// * 輸 出:無(wú) *
// **************************************************************************************************************
void v_RTInputByte(unsigned char ucDa)
{
unsigned char i;
ACC = ucDa;
T_RST = 1;
for(i=8; i>0; i--)
{
T_IO = ACC0;
T_CLK = 1;
T_CLK = 0;
ACC = ACC >> 1;
}
}
// **************************************************************************************************************
// * 名 稱:uc_RTOutputByte() *
// * 功 能:從DS1302讀取1Byte數(shù)據(jù) *
// * 輸 入:無(wú) *
// * 返回值:ACC *
// **************************************************************************************************************
unsigned char uc_RTOutputByte(void)
{
unsigned char 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);
}
// **************************************************************************************************************
// * 名 稱:v_W1302(unsigned char ucAddr, unsigned char ucDa) *
// * 功 能:往DS1302寫入數(shù)據(jù) *
// * 輸 入:ucAddr: DS1302地址, ucDa: 要寫的數(shù)據(jù) *
// * 返回值:無(wú) *
// **************************************************************************************************************
void v_W1302(unsigned char ucAddr, unsigned char ucDa)
{
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(ucAddr); // 寫地址
_nop_();
_nop_();
v_RTInputByte(ucDa); // 寫1Byte數(shù)據(jù)
T_CLK = 1;
T_RST = 0;
}
// **************************************************************************************************************
// * 名 稱:uc_R1302(unsigned char ucAddr) *
// * 功 能:讀取DS1302某地址的數(shù)據(jù) *
// * 輸 入:ucAddr: DS1302地址 *
// * 返回值:ucDa :讀取的數(shù)據(jù) *
// **************************************************************************************************************
unsigned char uc_R1302(unsigned char ucAddr)
{
unsigned char ucDa;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(ucAddr); //寫地址,命令
_nop_();
_nop_();
ucDa = uc_RTOutputByte(); //讀1Byte數(shù)據(jù)
T_CLK = 1;
T_RST = 0;
return(ucDa);
}
// **************************************************************************************************************
// * 名稱 : bcdtodec(unsigned char bcd) *
// * 功能 : BCD碼轉(zhuǎn)換為DEC碼 *
// * 輸入 : bcd碼 *
// * 輸出 : dec碼 *
// **************************************************************************************************************
unsigned char bcdtodec(unsigned char bcd)
{
unsigned char data1;
data1 = bcd & 0x0f; //取BCD低4位
bcd = bcd & 0x70; //剔除BCD的最高位和低4位。
data1 += bcd >> 1;
data1 += bcd >> 3; //用位移代替乘法運(yùn)算
return data1;
}
void lc()
{
unsigned long x,y;
x = sg + ss*10 + sb*100 + sq*1000 + sw*10000 + ssw*100000;
x = x*41/200;
if(x == 487805)
{
x=0;
xhcs++;
}
x = x % 100000;
w = x / 10000;
if (x < 10000)w=10;
y = x % 10000;
q = y / 1000; //求四位數(shù)的千位
if (x < 1000)q=10;
y = y % 1000; //求四位數(shù)去除千位的值
b = y / 100; //求四位數(shù)的百位
y = y % 100; //求四位數(shù)去除千位后再去除百位的值
s = y / 10; //求四位數(shù)的十位
g = y % 10; //求四位數(shù)的個(gè)位
}
void dlc()
{
unsigned long x,y;
x = dc*41/200;
x = x % 100000;
w = x / 10000;
if (x < 10000)w=10;
y = x % 10000;
q = y / 1000; //求四位數(shù)的千位
if (x < 1000)q=10;
y = y % 1000; //求四位數(shù)去除千位的值
b = y / 100; //求四位數(shù)的百位
y = y % 100; //求四位數(shù)去除千位后再去除百位的值
s = y / 10; //求四位數(shù)的十位
g = y % 10; //求四位數(shù)的個(gè)位
}
void ljlc(void)
{
if(sg > 9)
{
sg = 0;
ss++;
}
if(ss == 10)
{
ss = 0;
sb++;
}
if(sb == 10)
{
sb = 0;
sq++;
}
if(sq == 10)
{
sq = 0;
sw++;
}
if(sw == 10)
{
sw = 0;
ssw++;
}
if(ssw == 10)
{
ssw = 0;
}
}
void readdata()
{
//*******************************************************************
//最高速
v_W1302(0x8f,0);
maxg = bcdtodec(uc_R1302(0xc1)); //讀出DS1302中的maxg
v_W1302(0x8f,0);
maxs = bcdtodec(uc_R1302(0xc3)); //讀出DS1302中的maxs
v_W1302(0x8f,0);
maxb = bcdtodec(uc_R1302(0xc5)); //讀出DS1302中的maxb
v_W1302(0x8f,0);
maxq = bcdtodec(uc_R1302(0xc7)); //讀出DS1302中的maxq
v_W1302(0x8f,0);
maxw = bcdtodec(uc_R1302(0xc9)); //讀出DS1302中的maxw
//*******************************************************************
//總里程
v_W1302(0x8f,0);
sg = bcdtodec(uc_R1302(0xcb)); //讀出DS1302中的sg
v_W1302(0x8f,0);
ss = bcdtodec(uc_R1302(0xcd)); //讀出DS1302中的ss
v_W1302(0x8f,0);
sb = bcdtodec(uc_R1302(0xcf)); //讀出DS1302中的sb
v_W1302(0x8f,0);
sq = bcdtodec(uc_R1302(0xd1)); //讀出DS1302中的sq
v_W1302(0x8f,0);
sw = bcdtodec(uc_R1302(0xd3)); //讀出DS1302中的sw
v_W1302(0x8f,0);
ssw = bcdtodec(uc_R1302(0xd5)); //讀出DS1302中的ssw
//*******************************************************************
//循環(huán)次數(shù)
v_W1302(0x8f,0);
xhcs = bcdtodec(uc_R1302(0xd7)); //讀出DS1302中的xhcs
}
void savedata(void)
{
//*****************************************************************************
// 最高車速
v_W1302(0x8e,0);
v_W1302(0xc0,maxg);
v_W1302(0x8e,0);
v_W1302(0xc2,maxs);
v_W1302(0x8e,0);
v_W1302(0xc4,maxb);
v_W1302(0x8e,0);
v_W1302(0xc6,maxq);
v_W1302(0x8e,0);
v_W1302(0xc8,maxw);
//*****************************************************************************
// 總里程
v_W1302(0x8e,0);
v_W1302(0xca,sg);
v_W1302(0x8e,0);
v_W1302(0xcc,ss);
v_W1302(0x8e,0);
v_W1302(0xce,sb);
v_W1302(0x8e,0);
v_W1302(0xd0,sq);
v_W1302(0x8e,0);
v_W1302(0xd2,sw);
v_W1302(0x8e,0);
v_W1302(0xd4,ssw);
//*****************************************************************************
//循環(huán)次數(shù)
v_W1302(0x8e,0);
v_W1302(0xd6,xhcs);
}
void ql()
{
//*****************************************************************************
// 最高車速
v_W1302(0x8e,0);
v_W1302(0xc0,0);
v_W1302(0x8e,0);
v_W1302(0xc2,0);
v_W1302(0x8e,0);
v_W1302(0xc4,0);
v_W1302(0x8e,0);
v_W1302(0xc6,0);
v_W1302(0x8e,0);
v_W1302(0xc8,0);
//*****************************************************************************
// 總里程
v_W1302(0x8e,0);
v_W1302(0xca,0);
v_W1302(0x8e,0);
v_W1302(0xcc,0);
v_W1302(0x8e,0);
v_W1302(0xce,0);
v_W1302(0x8e,0);
v_W1302(0xd0,0);
v_W1302(0x8e,0);
v_W1302(0xd2,0);
v_W1302(0x8e,0);
v_W1302(0xd4,0);
//*****************************************************************************
//循環(huán)次數(shù)
v_W1302(0x8e,0);
v_W1302(0xd6,0);
}
void clock()
{
unsigned char min, hour;
v_W1302(0x8f, 0);
min = bcdtodec(uc_R1302(0x83)); //讀出DS1302中的分
v_W1302(0x8f, 0);
hour = bcdtodec(uc_R1302(0x85)); //讀出DS1302中的小時(shí)
w = hour/10;
q = hour%10;
b = 14;
s = min/10;
g = min%10;
}
void xh(void)
{
g = xhcs%100;
if(g<10)s = 10;else s = g / 10;
g = g % 10;
b = 10;
q = 10;
w = 10;
}
void display(void)
{
P2=0x01;
P0=table[w];
delay();
P0=0x00;
P2=0x02;
P0=table[q];
delay();
P0=0x00;
P2=0x04;
P0=table_D[b];
delay();
P0=0x00;
P2=0x08;
P0=table[g];
delay();
P0=0x00;
P2=0x10;
P0=table[s];
delay();
P0=0x00;
}
void tim(void) interrupt 1 using 1
{
TH0=0xf0;//重新賦值,定時(shí)2毫秒
TL0=0x5f;
time++;//計(jì)時(shí),數(shù)2毫秒的個(gè)數(shù)zs();
}
void ISR_INT0(void) interrupt 0 using 1
{
sg++;
dc++;
z=time;//車輪轉(zhuǎn)動(dòng)1圈所用的時(shí)間--------多少個(gè)2毫秒
time=0;//計(jì)時(shí)復(fù)零
}
void adjust(void)
{
unsigned char min,sec;
v_W1302(0x8f, 0);
sec = bcdtodec(uc_R1302(0x81)); //讀出DS1302中的秒
v_W1302(0x8f, 0);
min = bcdtodec(uc_R1302(0x83)); //讀出DS1302中的分
w = min/10;
q = min%10;
b = 10;
s = sec/10;
g = sec%10;
if(p10 == 0)
{
if(sec > 29)
{
v_W1302(0x8e,0);
v_W1302(0x80,0x59); //寫入秒sec = 59;
}
else
{
v_W1302(0x8e,0);
v_W1302(0x80,0x00); //寫入秒sec = 00;
}
}
}
void jscs(void)
{
unsigned long ls;
v = 369000/z;
if(v > max)max = v;
if(v < 6)v = 0;
maxw = max/10000;
ls = max%10000;
maxq = ls/1000;
ls = ls%1000;
maxb = ls/100;
ls = ls%100;
maxs = ls/10;
maxg =ls%10;
}
void cs(void)
{
unsigned long ls;
if(v > 9999)w = v/10000;else w=10;
ls = v%10000;
if(ls > 999)q = ls/1000;else q=10;
ls = ls%1000;
b = ls/100;
ls = ls%100;
s = ls/10;
g = ls%10;
}
void maxcs(void)
{
unsigned long ls;
if(max > 9999)w = max/10000;else w=10;
ls = max%10000;
if(ls > 999)q = ls/1000;else q=10;
ls = ls%1000;
b = ls/100;
ls = ls%100;
s = ls/10;
g = ls%10;
}
/********************************************************************
* 名稱 : Write_DS1302Init()
* 功能 : 往DS1302中寫入數(shù)據(jù)。最開(kāi)始顯示的數(shù)據(jù)就是在這里設(shè)置的。
* 輸入 : 無(wú)
* 輸出 : 無(wú)
***********************************************************************/
void Write_DS1302Init(void)
{
v_W1302(0x8e,0);
v_W1302(0x80,0x00); //寫入秒
v_W1302(0x8e,0);
v_W1302(0x82,0x09); //寫入分
v_W1302(0x8e,0);
v_W1302(0x84,0x18); //寫入小時(shí)
v_W1302(0x8e,0);
v_W1302(0x86,0x18); //寫入日
v_W1302(0x8e,0);
v_W1302(0x88,0x06); //寫入月
v_W1302(0x8e,0);
v_W1302(0x8a,0x01); //寫入星期
v_W1302(0x8e,0);
v_W1302(0x8c,0x18); //寫入年
}
void ljsj(void)
{}
void main(void)
{
unsigned char xd=0,q;
EX0 = 1;//外部中斷0設(shè)置
IT0 = 1;
EX1 = 1;//外部中斷1設(shè)置
IT1 = 1;
//定時(shí)器設(shè)置 2ms in 24M crystal,工作方式1,16位計(jì)數(shù)器,2毫秒4000個(gè)脈沖故(65536-4000)的16進(jìn)制為f05f。
TMOD |= 0x01;
TH0 = 0xf0;
TL0 = 0x5f;
ET0 = 1; //打開(kāi)中斷
TR0 = 1;
EA = 1;
v_W1302(0x8e,0);//打開(kāi)寫保護(hù)
// v_W1302(0x90,0x00); // TCS 4位 DS 2位 TS 2位
// xxxx xx xx
// 1010可以充電 01一個(gè)二極管 00無(wú)電阻
// 其他禁止充電 10兩個(gè)二極管 01 2K電阻
// 其他禁止充電 10 4K電阻
// 11 8K電阻
//如果以1個(gè)二極管串聯(lián)4K電阻充電,則為:10100110 十六進(jìn)制為:0xa6
// Write_DS1302Init();
if (p11 == 0) //檢測(cè)是否按下按鈕,在系統(tǒng)加電時(shí)按下按鈕,則執(zhí)行清零程序
{
ql();
for(q=0;q<255;q++) delay();
for(q=0;q<255;q++) delay();
}
readdata(); //讀出DS1302內(nèi)的數(shù)據(jù)
max = maxg + maxs*10 + maxb*100 + maxq*1000 + maxw*10000; //計(jì)算以前的最高車速
while(1)
{
if (p11 == 0 & xd == 0) //檢測(cè)是否按下按鈕
{
gn++; //如果按下按鍵則轉(zhuǎn)換功能
if(gn > 7)gn = 1;
xd = 1; //如果沒(méi)有松開(kāi)按鍵不允許繼續(xù)轉(zhuǎn)換
for(q=0;q<255;q++) delay();
for(q=0;q<255;q++) delay();
if(p11 == 1)xd = 0;
}
jscs(); //計(jì)算車速
ljlc(); //累計(jì)里程
if(time < 2500)ljsj(); //如果時(shí)間小于5秒(行車中)則執(zhí)行累積時(shí)間
else if(time <3000)
{
time = 65530;
savedata(); //否則認(rèn)為已停車,保存數(shù)據(jù)
z = time;
}
else time = 65530; //保持time=3500,不至于育溢出
switch(gn)
{
case 1:clock();break; //時(shí)鐘
case 2:cs();break; //車速
case 3:dlc();break; //當(dāng)前里程
case 4:lc();break; //總里程
case 5:xh();break; //總里程數(shù)
case 6:maxcs();break; //最高車速
case 7:adjust();break; //對(duì)表
}
display();
}
} |
|