機(jī)械社區(qū)

 找回密碼
 注冊(cè)會(huì)員

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 4126|回復(fù): 9
打印 上一主題 下一主題

單片機(jī)學(xué)習(xí)之三:做一個(gè)自行車車速表

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
1#
發(fā)表于 2023-9-3 17:37:45 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
看到論壇里已經(jīng)有人做過(guò)。
原理都一樣,利用霍爾元件感受自行車前輪轉(zhuǎn)的圈數(shù)。統(tǒng)計(jì)時(shí)間,計(jì)算車速,里程,保留最高速度至DS1302的RAM,計(jì)量騎行的總時(shí)間。
不多說(shuō),上圖。因?yàn)閷?shí)物被朋友拿走了,這里上PCB圖,原理圖,并貼出代碼。
代碼肯定不專業(yè),各位輕噴。

評(píng)分

參與人數(shù) 2威望 +101 收起 理由
東東2012173 + 1
老鷹 + 100

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

推薦
發(fā)表于 2023-9-4 07:46:35 | 只看該作者
你這,能搭話的就少了啊我反正是看不明白
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();
        }
}
4#
發(fā)表于 2023-9-4 08:10:55 | 只看該作者
大俠水平高啊,機(jī)電通吃妥妥的。
5#
發(fā)表于 2023-9-4 08:25:38 | 只看該作者
         專業(yè)技術(shù)貼,比我們以前用匯編語(yǔ)言方便多了!
6#
 樓主| 發(fā)表于 2023-9-4 08:26:18 | 只看該作者
DianGongN 發(fā)表于 2023-9-4 08:10
大俠水平高啊,機(jī)電通吃妥妥的。

談不上啊,特備是電,真的業(yè)余水平,玩玩就好。
7#
 樓主| 發(fā)表于 2023-9-4 08:29:12 | 只看該作者
江東老歌 發(fā)表于 2023-9-4 08:25
專業(yè)技術(shù)貼,比我們以前用匯編語(yǔ)言方便多了!

我朋友仍然用匯編。匯編編譯出來(lái)的,文件個(gè)頭都比C小很多,運(yùn)行效率也高。你們才是高手。
我問(wèn)我那朋友,匯編可讀性差,你編著不費(fèi)勁?人家說(shuō)習(xí)慣就好,就像平時(shí)說(shuō)話一樣了。

點(diǎn)評(píng)

你這朋友是真正的高手!  發(fā)表于 2023-9-4 08:31
8#
 樓主| 發(fā)表于 2023-9-4 08:55:46 | 只看該作者
白無(wú)無(wú) 發(fā)表于 2023-9-4 07:46
你這,能搭話的就少了啊我反正是看不明白

咱們不是在討論低矮歪嗎?只要愿意去動(dòng)手做的,肯邁出實(shí)踐的第一步,就成功了一半。

9#
發(fā)表于 2023-9-4 13:04:53 | 只看該作者
覺(jué)歷!
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|手機(jī)版|Archiver|機(jī)械社區(qū) ( 京ICP備10217105號(hào)-1,京ICP證050210號(hào),浙公網(wǎng)安備33038202004372號(hào) )

GMT+8, 2024-11-2 06:39 , Processed in 0.058481 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回復(fù) 返回頂部 返回列表