找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2506|回复: 5
打印 上一主题 下一主题
收起左侧

51单片机自行车里程表设计C程序看不懂,求指教

[复制链接]
回帖奖励 18 黑币 回复本帖可获得 3 黑币奖励! 每人限 1 次
跳转到指定楼层
楼主
ID:766352 发表于 2021-5-9 23:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
基于单片机的自行车里程表设计(有原理图 仿真电路 源程序 pcb) - 单片机DIY制作 (51hei.com)
上面帖子上的这段程序没看懂,有人可以帮忙讲解下吗,尤其是下面两句,速度和里程是怎么计算的呢,速度除以40 的意思是?
count参数是500ms产生的脉冲数,是这个意思吗,希望帮忙解释下,谢谢或者有别的里程速度计算公式可以用在这个程序中实现功能的吗?

Mileage=Mileage+10*(Velocity/3.6)/2;                 //里程m=里程+速度km/h/3.6/2
Velocity=count *2*3.14*RADIUS /100000*2*3600  /40;//将500ms的距离经过运算得到km/h,将速度/100,方便显示



完整程序如下:
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#include "Data.h"
#include "DS1302.h"
#include "AT24C02.h"
sbit COUNT_IN=P3^2;
//定义1602相关管脚
sbit rs=P1^4;     //寄存器选择位
sbit en=P1^0;     //使能信号位
//键盘定义
sbit K1=P3^4;        //设置时间
sbit K3=P3^6;        //减按键
sbit K2=P3^5;        //加按键
sbit K4=P3^7;        //设置半径安全距离
sbit BEEP=P3^0;
uint count;
unsigned long Velocity,Mileage;
uchar code tab1[]={"  /  /     :    "};        
uchar code tab2[]={"  0.000km 00km/h"};
uchar code tab3[]={"Wheel Radius  cm"};
uchar code tab4[]={"Safe Speed  km/h"};
uchar code tab5[]={"Sec :           "};                                             
uchar Mode=0;
uchar bike_set=0;
uchar a;
char RADIUS,SAFE_SPEED;
bit LED_SEC;
uchar before_sec;      
uchar code num[]={
                           0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//1         
                           0x1f,0x01,0x01,0x1f,0x10,0x10,0x1f,0x00,//2
                            0x1f,0x01,0x01,0x1f,0x01,0x01,0x1f,0x00,//3         
                           0x11,0x11,0x11,0x1f,0x01,0x01,0x01,0x00,//4
                             0x1f,0x10,0x10,0x1f,0x01,0x01,0x1f,0x00,//5         
                            0x1f,0x10,0x10,0x1f,0x11,0x11,0x1f,0x00,//6
                             0x1f,0x01,0x01,0x01,0x01,0x01,0x01,0x00,//7        //自定义字符
};
void READS();
void SETS();
void delay(uint x)
{
        uint i,j;
        for(i=0;i<x;i++)
        for(j=0;j<110;j++);//延时
}
void init()
{
        IT0=1;        //INT0负跳变触发      
    TMOD=0x01;//定时器工作于方式1
        TH0=0x3c;          //50ms
        TL0=0xb0;
        EA=1; //CPU开中断总允许
        ET0=1;//开定时中断
        EX0=1;//开外部INTO中断
    TR0=1;//启动定时
}
/********液晶写入指令函数与写入数据函数,以后可调用**************/
void write_1602com(uchar com)//****液晶写入指令函数****
{
        rs=0;//数据/指令置为指令
        P0=com;//送入数据
        delay(1);
        en=1;//拉高使能端,为制造有效的下降沿做准备
        delay(1);
        en=0;//en由高变低,产生下降沿,液晶执行命令
}
void write_1602dat(uchar dat)//***液晶写入数据函数****
{
        rs=1;//数据/指令置为数据
        P0=dat;//送入数据
        delay(1);
        en=1; //en置高电平,为制造下降沿做准备
        delay(1);
        en=0; //en由高变低,产生下降沿,液晶执行命令
}
void Lcd_ram()      //自定义字符集
{
        uint i,j,k=0,temp=0x40;
        for(i=0;i<7;i++)
        {
           for(j=0;j<8;j++)
           {
            write_1602com(temp+j);   //写地址
            write_1602dat(num[k]);   //写数据
            k++;
           }
           temp=temp+8;  }    }
void lcd_init()//***液晶初始化函数****
{
        Lcd_ram();
        write_1602com(0x38);//设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据
        write_1602com(0x0c);//开显示不显示光标
        write_1602com(0x06);//整屏不移动,光标自动右移
        write_1602com(0x01);//清显示
        write_1602com(0x80);//显示固定符号从第一行第1个位置之后开始显示
        for(a=0;a<16;a++)
        {
                write_1602dat(tab1[a]);//向液晶屏写固定符号部分
        }
        write_1602com(0x80+0x40);//显示固定符号写入位置,从第2个位置后开始显示
        for(a=0;a<16;a++)
        {
                write_1602dat(tab2[a]);//写显示固定符号
        }
}
void display()
{
        //   1km/h=100m/0.1h                   360s
        //   10km/h=100m/0.01h          36s
        //  100km/h=100m/0.001h  3.6s
        if(Mode==0&&bike_set==0)
        {
                //读时间
                        Ds1302_Read_Time();
                        //显示时间
                        write_1602com(0x80);
                        write_1602dat(0x30+time_buf1[1]/10);
                        write_1602dat(0x30+time_buf1[1]%10);
                        write_1602com(0x80+3);
                        write_1602dat(0x30+time_buf1[2]/10);
                        write_1602dat(0x30+time_buf1[2]%10);
                        write_1602com(0x80+6);
                        write_1602dat(0x30+time_buf1[3]/10);
                        write_1602dat(0x30+time_buf1[3]%10);
                        write_1602com(0x80+9);
                        write_1602dat(0x30+time_buf1[4]/10);
                        write_1602dat(0x30+time_buf1[4]%10);
                        write_1602com(0x80+12);
                        write_1602dat(0x30+time_buf1[5]/10);
                        write_1602dat(0x30+time_buf1[5]%10);
                        write_1602com(0x80+15);
                        write_1602dat(time_buf1[7]-1);               
                        if(before_sec!=time_buf1[6])
                        {
                                before_sec=time_buf1[6];
                                write_1602com(0x80+11);
                                write_1602dat(':');
                                LED_SEC=1;
                        }
                        if(LED_SEC==0)
                        {
                                write_1602com(0x80+11);
                                write_1602dat(' ');      
                        }
                     write_1602com(0x80+0x40);
                        if(Mileage/1000000==0)
                        write_1602dat(' ');
                        else
                 write_1602dat(0x30+Mileage/1000000);//数字+0x30得到该数字LCD显示码
                        if(Mileage%1000000/100000==0)
                        write_1602dat(' ');
                        else      
         write_1602dat(0x30+Mileage%1000000/100000);//数字+0x30得到该数字LCD显示码
        write_1602dat(0x30+Mileage%1000000%100000/10000);
         write_1602com(0x80+0x40+4);
       write_1602dat(0x30+Mileage%1000000%100000%10000/1000);
   write_1602dat(0x30+Mileage%1000000%100000%10000%1000/100);
     write_1602dat(0x30+Mileage%1000000%100000%10000%1000%100/10);                          SETS();
          write_1602com(0x80+0x40+10);
          write_1602dat(0x30+Velocity/10);
          write_1602dat(0x30+Velocity%10);//数字+30得到该数字的LCD1602显示码
        }
        else if(Mode!=0)
        {
                switch(Mode)
                {
                        case 1:      
                                write_1602com(0x80+0x40);//显示固定符号写入位置
                                for(a=0;a<16;a++)
                                {
                                        write_1602dat(tab5[a]);//写显示固定符号
                                }
                                write_1602com(0x80+0x40+14);
                                write_1602dat(0x30+time_buf1[6]/10);
                                write_1602dat(0x30+time_buf1[6]%10);      
                                write_1602com(0x0F);         //打开闪烁
                                write_1602com(0x80+1);
                                break;                                                  
                        case 2:
                                write_1602com(0x80+4);
                                break;
                        case 3:
                                write_1602com(0x80+7);
                                break;
                        case 4:
                                write_1602com(0x80+10);
                                break;
                        case 5:
                                write_1602com(0x80+13);
                                break;
                        case 6:
                                write_1602com(0x80+0x40+15);
                                break;
                        case 7:
                                write_1602com(0x80+15);
                                break;
                        case 8:
                                write_1602com(0x0c);
                                write_1602com(0x80);//显示固定符号第1行第1个位置后显示
                                for(a=0;a<16;a++)
                                {
                                   write_1602dat(tab1[a]);//向液晶屏写固定符号部分
                                }
                                write_1602com(0x80+0x40);//显示固定符号写入位置,从第2个位置后开始显示
                                for(a=0;a<16;a++)
                                {
                                        write_1602dat(tab2[a]);//写显示固定符号
                                }
                                break;
                }
        }
        else if(bike_set!=0)
        {
                switch(bike_set)
                {
                        case 1:      
                                write_1602com(0x80);//显示固定符号写入位置
                                for(a=0;a<16;a++)
                                {
                                        write_1602dat(tab3[a]);//写显示固定符号
                                }
                                write_1602com(0x80+0x40);//显示固定符号写入位置
                                for(a=0;a<16;a++)
                                {
                                        write_1602dat(tab4[a]);//写显示固定符号
                                }
                                write_1602com(0x80+12);
                                write_1602dat(0x30+RADIUS/10);                   //车轮半径
                                write_1602dat(0x30+RADIUS%10);
                                write_1602com(0x80+0x40+10);
                                write_1602dat(0x30+SAFE_SPEED/10);                   //安全速度
                                write_1602dat(0x30+SAFE_SPEED%10);      
                                write_1602com(0x0F);         //打开闪烁
                                write_1602com(0x80+13);
                                break;                                                  
                        case 2:
                                write_1602com(0x80+0x40+11);
                                break;
                        case 3:
                               write_1602com(0x0c);
                             write_1602com(0x80);/              
        for(a=0;a<16;a++)
                                {
                                        write_1602dat(tab1[a]);//向液晶屏写固定符号部分
                                }
                                 write_1602com(0x80+0x40);//从第2个位置后显示
                                for(a=0;a<16;a++)
                                {
                                        write_1602dat(tab2[a]);//写显示固定符号
                                }
                                break;
                }
        }      
}
void KEY()
{      
        if(bike_set==0&&K1==0)
        {
                delay(20);
                if(bike_set==0&&K1==0)
                {
                        BEEP=0;
                        delay(50);
                        BEEP=1;
                        Mode++;
                        display();
                        if(Mode>=8)
                        {
                                Mode=0;
                                Ds1302_Write_Time();
                        }
                }
                while(bike_set==0&&K1==0);
        }
        if(K4==0&&Mode==0)
        {
                delay(20);
                if(K4==0&&Mode==0)
                {
                        BEEP=0;
                        delay(50);
                        BEEP=1;
                        bike_set++;
                        display();
                        if(bike_set>=3)
                        {
                                bike_set=0;
                                SETS();
                        }
                }
                while(Mode==0&&K4==0);
        }
        //+
        if(K2==0&&(Mode!=0||bike_set!=0))
        {
                delay(20);
                //调时
                if(K2==0&&(Mode!=0||bike_set!=0))
                {
                        BEEP=0;
                        delay(50);
                        BEEP=1;      
                        switch(Mode)
                        {
                                case 1:
                                        time_buf1[1]++;
                                        if(time_buf1[1]>=100)
                                                time_buf1[1]=0;
                                        write_1602com(0x80);
                                        write_1602dat(0x30+time_buf1[1]/10);
                                        write_1602dat(0x30+time_buf1[1]%10);
                                        write_1602com(0x80+1);
                                        break;
                                case 2:
                                        time_buf1[2]++;
                                        if(time_buf1[2]>=13)
                                                time_buf1[2]=1;
                                        write_1602com(0x80+3);
                                        write_1602dat(0x30+time_buf1[2]/10);
                                        write_1602dat(0x30+time_buf1[2]%10);
                                        write_1602com(0x80+4);
                                        break;
                                case 3:
                                        time_buf1[3]++;
                                        if(time_buf1[3]>=YDay(time_buf1[1],time_buf1[2])+1)
                                                time_buf1[3]=1;
                                        write_1602com(0x80+6);
                                        write_1602dat(0x30+time_buf1[3]/10);
                                        write_1602dat(0x30+time_buf1[3]%10);
                                        write_1602com(0x80+7);
                                        break;
                                case 4:
                                        time_buf1[4]++;
                                        if(time_buf1[4]>=24)
                                                time_buf1[4]=0;
                                        write_1602com(0x80+9);
                                        write_1602dat(0x30+time_buf1[4]/10);
                                        write_1602dat(0x30+time_buf1[4]%10);
                                        write_1602com(0x80+10);
                                        break;
                                case 5:
                                        time_buf1[5]++;
                                        if(time_buf1[5]>=60)
                                                time_buf1[5]=0;
                                        write_1602com(0x80+12);
                                        write_1602dat(0x30+time_buf1[5]/10);
                                        write_1602dat(0x30+time_buf1[5]%10);
                                        write_1602com(0x80+13);
                                        break;
                                case 6:
                                        time_buf1[6]++;
                                        if(time_buf1[6]>=60)
                                                time_buf1[6]=0;
                                        write_1602com(0x80+0x40+14);
                                        write_1602dat(0x30+time_buf1[6]/10);
                                        write_1602dat(0x30+time_buf1[6]%10);
                                        write_1602com(0x80+0x40+15);
                                        break;
                                case 7:
                                        time_buf1[7]++;
                                        if(time_buf1[7]>=8)
                                                time_buf1[7]=1;
                                        write_1602com(0x80+15);
                                        write_1602dat(time_buf1[7]-1);
                                        write_1602com(0x80+15);
                                        break;
                        }
                        switch(bike_set)
                        {
                                case 1:
                                        RADIUS++;
                                        if(RADIUS>=71)
                                        RADIUS=0;
                                        write_1602com(0x80+12);
                                        write_1602dat(0x30+RADIUS/10);
                                        write_1602dat(0x30+RADIUS%10);
                                        write_1602com(0x80+13);
                                        break;
                                case 2:
                                        SAFE_SPEED++;
                                        if(SAFE_SPEED>=100)
                                        SAFE_SPEED=0;
                                        write_1602com(0x80+0x40+10);
                                        write_1602dat(0x30+SAFE_SPEED/10);
                                        write_1602dat(0x30+SAFE_SPEED%10);
                                        write_1602com(0x80+0x40+11);
                                        break;
                        }
                }
                while(K2==0);
        }
        if(K3==0&&(Mode!=0||bike_set!=0))
        {
                delay(20);
                //调时
                if(K3==0&&(Mode!=0||bike_set!=0))
                {
                        BEEP=0;
                        delay(50);
                        BEEP=1;
                        switch(Mode)
                        {
                                case 1:
                                        time_buf1[1]--;
                                        if(time_buf1[1]<0)
                                                time_buf1[1]=99;
                                        write_1602com(0x80);
                                        write_1602dat(0x30+time_buf1[1]/10);
                                        write_1602dat(0x30+time_buf1[1]%10);
                                        write_1602com(0x80+1);
                                        break;
                                case 2:
                                        time_buf1[2]--;
                                        if(time_buf1[2]<=0)
                                                time_buf1[2]=12;
                                        write_1602com(0x80+3);
                                        write_1602dat(0x30+time_buf1[2]/10);
                                        write_1602dat(0x30+time_buf1[2]%10);
                                        write_1602com(0x80+4);
                                        break;
                                case 3:
                                        time_buf1[3]--;
                                        if(time_buf1[3]<=0)
                                                time_buf1[3]=YDay(time_buf1[1],time_buf1[2]);
                                        write_1602com(0x80+6);
                                        write_1602dat(0x30+time_buf1[3]/10);
                                        write_1602dat(0x30+time_buf1[3]%10);
                                        write_1602com(0x80+7);
                                        break;
                                case 4:
                                        time_buf1[4]--;
                                        if(time_buf1[4]<0)
                                                time_buf1[4]=23;
                                        write_1602com(0x80+9);
                                        write_1602dat(0x30+time_buf1[4]/10);
                                        write_1602dat(0x30+time_buf1[4]%10);
                                        write_1602com(0x80+10);
                                        break;
                                case 5:
                                        time_buf1[5]--;
                                        if(time_buf1[5]<0)
                                                time_buf1[5]=59;
                                        write_1602com(0x80+12);
                                        write_1602dat(0x30+time_buf1[5]/10);
                                        write_1602dat(0x30+time_buf1[5]%10);
                                        write_1602com(0x80+13);
                                        break;
                                case 6:
                                        time_buf1[6]--;
                                        if(time_buf1[6]<0)
                                                time_buf1[6]=59;
                                        write_1602com(0x80+0x40+14);
                                        write_1602dat(0x30+time_buf1[6]/10);
                                        write_1602dat(0x30+time_buf1[6]%10);
                                        write_1602com(0x80+0x40+15);
                                        break;
                                case 7:
                                        time_buf1[7]--;
                                        if(time_buf1[7]<1)
                                                time_buf1[7]=7;
                                        write_1602com(0x80+15);
                                        write_1602dat(time_buf1[7]-1);
                                        write_1602com(0x80+15);
                                        break;
                        }
                        switch(bike_set)
                        {
                                case 1:
                                        RADIUS--;
                                        if(RADIUS<0)
                                        RADIUS=70;
                                        write_1602com(0x80+12);
                                        write_1602dat(0x30+RADIUS/10);
                                        write_1602dat(0x30+RADIUS%10);
                                        write_1602com(0x80+13);
                                        break;
                                case 2:
                                        SAFE_SPEED--;
                                        if(SAFE_SPEED<0)
                                        SAFE_SPEED=99;
                                        write_1602com(0x80+0x40+10);
                                        write_1602dat(0x30+SAFE_SPEED/10);
                                        write_1602dat(0x30+SAFE_SPEED%10);
                                        write_1602com(0x80+0x40+11);
                                        break;
                        }
                }
                while(K3==0);
        }      
        if(K2==0&&K3==0&&Mode==0&bike_set==0)
        {
                BEEP=0;
                delay(100);
                BEEP=1;
                delay(100);
                BEEP=0;
                delay(100);
                BEEP=1;
                delay(100);
                Mileage=0;
                SETS();
                while(K2==0&&K3==0);
        }
}
void BJ_SAFE()
{
        if(Velocity>SAFE_SPEED)
        {
                BEEP=0;
        }
        else
        {
                BEEP=1;
        }
}
void main()
{
        //初始化
        Ds1302_Init();
        lcd_init();
        initeeprom();
        //读取初始参数
        READS();
        //定时器初始化
//        InitTimer0();
        init();
        lcd_init();
        before_sec=time_buf1[6];
        while(1)
        {
                if(Mode==0&&bike_set==0)
                {
                        display();
                        BJ_SAFE();
                }
                KEY();
        }
void EXINT0() interrupt 0
{
        count++;
}
void time0() interrupt 1
{
        uchar m,n;
        TH0=0x3c;
        TL0=0xb0;         //50ms
        m++;
        if(LED_SEC==1)
        {
                n++;
                if(n>=10)
                {
                        n=0;
                        LED_SEC=0;
                }
        }
        if(m>=10)
        {
                m=0;
                Mileage=Mileage+10*(Velocity/3.6)/2;                 //里程m=里程+速度km/h/3.6/2
                Velocity=count *2*3.14*RADIUS /100000*2*3600  /40;//500ms的距离经过运算得到km/h,将速度/100,方便显示
                count=0;      
        }
}
//读初值
void READS()
{
        uchar Mileage_H,Mileage_M,Mileage_L;
        delay(10);
        RADIUS=read_add(0x01);
        delay(10);
        SAFE_SPEED=read_add(0x02);

        delay(10);
        Mileage_H=read_add(0x03);
        delay(10);
        Mileage_M=read_add(0x04);
        delay(10);
        Mileage_L=read_add(0x05);
        Mileage=Mileage_H*100000+Mileage_M*1000+Mileage_L*10;
}
//写初值
void SETS()
{
        delay(10);
        write_add(0x01,RADIUS);
        delay(10);
        write_add(0x02,SAFE_SPEED);
/*      Mileage_H=Mileage/10000;                         //123.4560
        Mileage_M=Mileage%10000/100;
        Mileage_L=Mileage%10000%100; */
        delay(10);
        write_add(0x03,Mileage/100000);
        delay(10);
        write_add(0x04,Mileage%100000/1000);
        delay(10);
        write_add(0x05,Mileage%100000%1000/10);

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:917514 发表于 2021-5-10 10:59 | 只看该作者
单独对下面的这两行代码进行解释:
Mileage=Mileage+10*(Velocity/3.6)/2;                 //里程m=里程+速度km/h/3.6/2
Velocity=count *2*3.14*RADIUS /100000*2*3600  /40;//将500ms的距离经过运算得到km/h,将速度/100,方便显示
1、首先是500ms里程数和速度刷新一次;
2、里程数计算:之前的里程数+根据500ms前的速度与500ms的乘积计算得来。
Mileage(当前总里程数)=Mileage(500ms前的里程数)+10*(Velocity/3.6)/2; 这里除以2可以理解为乘以0.5秒(500ms),乘以10是为了方便显示;
3、速度计算:
Velocity=count *2*3.14*RADIUS /100000*2*3600  /40
(1)count/40是自行车转动的圈数(可能大于1,也可能小于1,速度快大于1,速度慢可能小于1),也就是在500ms内,自行车轮胎滚了几圈,乘以轮胎的周长(2*3.14*RADIUS),也就是自行车前进的距离。
(2)为啥count要除以40,count是500ms内总的接收到信号的次数,车轮一周应该有40个传感器或者车轮转动一周会产生40个脉冲信号,所以要除以40,才是自行车真正的转动圈数;
(3)100000=100*1000,除以100是为了方便显示,除以1000是将M转化成KM;
(4)后面那个乘以2,实际是除以0.5s(500ms),乘以3600是将秒转成小时,以便得到速度是KM/H

评分

参与人数 1黑币 +50 收起 理由
admin + 50 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

板凳
ID:766352 发表于 2021-5-10 17:47 | 只看该作者
xll_9527 发表于 2021-5-10 10:59
单独对下面的这两行代码进行解释:
Mileage=Mileage+10*(Velocity/3.6)/2;                 //里程m=里程+ ...

你好,请问车轮转一圈产生40个脉冲这个是固定的吗
这个设计的测试方法可以用在实际自行车上使用吗?我师傅问此设计实际意义有吗?麻烦解答下,谢谢。测量的精度能满足要求吗?
回复

使用道具 举报

地板
ID:149451 发表于 2022-3-14 10:54 | 只看该作者
刘珍 发表于 2021-5-10 17:47
你好,请问车轮转一圈产生40个脉冲这个是固定的吗
这个设计的测试方法可以用在实际自行车上使用吗?我师 ...

我理解这个“40”取决于轮子转一周遮光(采集信号)的次数
回复

使用道具 举报

5#
ID:584814 发表于 2022-3-14 11:37 | 只看该作者
先从原理上搞,然后就清楚了:
在车架上安装一个触发装置,车轮转动一周计一次数,累加;
单片机开个定时器,累加到一定时间时,与车轮上的计数器通过以下公式:
里程=计数×车轮周长;速度=计数×车轮周长÷一定时间
所以在程序中找相关的项目就可以,自己写比读可能更方便。计数器常用霍尔之类的
回复

使用道具 举报

6#
ID:983641 发表于 2022-3-15 11:55 | 只看该作者
轮子是多大的?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表