基于51单片机的带方位指示的自行车码表proteus仿真原理图PCB

功能介绍:
0.本系统采用STC89C52作为单片机
1.采用LCD1602液晶可实时显示码表信息
2.蜂鸣器和LED组成声光报警电路,当速度超过设定的阈值启动报警
3.DS1302时钟芯片可实时显示系统时间
4.采用DC002作为电源接口可直接输入5V给整个系统供电
5.设计的EEPROM支持掉电数据保存,下次使用可查看上次码表记录的相关信息
6.方位传感器采用HMC5883L模块,支持自行车或其他载体的方位信息
7.采用小电机和霍尔传感器模拟车子运动的过程

原理图:
在这里插入图片描述

PCB:
在这里插入图片描述

主程序:

#include "main.h"

#define DIAMETER 20 //直径,单位mm

float distance = 0; //单位m
float totalDistBuf = 0; //单位m
float rate = 0; //单位km/h
float totalDist = 0; //单位km
unsigned char rateAlarm = 30; //单位km/h
unsigned char second = 0; 
unsigned char minute = 0; 
unsigned long pulseCnt = 0;
bit dispFlag = 1;
bit setTimeFlag = 0;
bit setAlarmFlag = 0;
bit motorFlag = 0;
bit refreshFlag = 0;
bit writeFlag = 0;
bit isNewFlag = 1;
unsigned char pwmValue = 8;
unsigned char setIndex = 0;
unsigned char xdata dispRow0[16];
unsigned char xdata dispRow1[16];

enum{
    DISP_RATE_MODE, DISP_DIR_MODE, DISP_TIME_MODE, SET_ALARM_MODE
} dispMode;

void main()
{
    MOTOR = 0; 
    MOTOR_N = 0; //电机关闭
    //初始化
    LCD_Init();
    DS1302_Init();
    EEPROM_Init();

    // EEPROM_WriteByte(IS_NEW_ADDR, 1); //将芯片设为新芯片

    ReadEEPROM();
    // isNewFlag = 1;
    if (isNewFlag != 0) //新芯片
    {
        EEPROM_WriteByte(IS_NEW_ADDR, 0);
        
        //给出初始值
        rateAlarm = 30;
        totalDist = 0;

        WriteEEPROM();
    }

    DS1302_ReadTime();

    Timer0_Init();
    Timer1_Init();
    EXT1_Init();

    //开机显示
    LCD_DispStr(0, 0, "    Welcome!    ");
    HMC5883_Init();
    DelayS(2);
    LCD_Clear();

    while(1)
    {
        //每秒钟更新数据
        if (refreshFlag == 1)
        {
            distance = distance + DIAMETER * 2 * 3.14 * (float)pulseCnt / 1000 ; //单位m
            totalDist = totalDist + DIAMETER * 2 * 3.14 * (float)pulseCnt / 1000; //单位km
            rate = 3.6 * DIAMETER * 2 * 3.14 * (float)pulseCnt / 1000; //单位km/h
            pulseCnt = 0;
            EX1 = 1;
            refreshFlag = 0;
        }
        
        //每分钟写一次EEPROM
        if (writeFlag == 1)
        {
            if (totalDist != totalDistBuf) //里程是否发生变化
            {
                WriteEEPROM();
            }
            totalDistBuf = totalDist;
            writeFlag = 0;
        }
        
        //显示函数
        if (dispFlag == 1)
        {
            if (dispMode == DISP_RATE_MODE) //显示速度
            {
                DispRate();
            }
            else if (dispMode == DISP_DIR_MODE) //显示方向
            {
                DispDirection();
            }
            else if (dispMode == DISP_TIME_MODE) //显示时间
            {
                if (setTimeFlag == 0)
                {
                    DS1302_ReadTime();
                    DispTime(setIndex, setTimeFlag);
                }
            }
            else if (dispMode == SET_ALARM_MODE) //显示报警速度
            {
                if (setAlarmFlag == 0)
                {
                    // ReadEEPROM();
                    if (totalDist != totalDistBuf)
                    {
                        WriteEEPROM();
                    }
                    totalDistBuf = totalDist;
                    DispAlarm(setIndex, setAlarmFlag);
                }
            }
        }

        //超速报警
        if (rate > rateAlarm)
        {
            BUZZER = 0;
        }
        else
        {
            BUZZER = 1;
        }
        KeyProcess();
    }
}

void ReadEEPROM(void)
{
    isNewFlag    = EEPROM_ReadByte(IS_NEW_ADDR);

    rateAlarm      = EEPROM_ReadByte(IS_NEW_ADDR + 1);
    totalDist      = EEPROM_ReadByte(IS_NEW_ADDR + 2);
    totalDist     = ((unsigned int)totalDist << 8) | EEPROM_ReadByte(IS_NEW_ADDR + 3);
}

void WriteEEPROM(void)
{
    EEPROM_WriteByte(IS_NEW_ADDR + 1, rateAlarm);
    EEPROM_WriteByte(IS_NEW_ADDR + 2, (((unsigned int)totalDist & 0xFF00) >> 8));
    EEPROM_WriteByte(IS_NEW_ADDR + 3, ((unsigned int)totalDist & 0x00FF));
}

void DispDirection(void) //显示方向
{
    xdata char dis[16];
    xdata float GaX, GaY;
    xdata unsigned int angle;
    
    HMC5883_MultipleRead();

    GaX = (float)(BUF[0] << 8 | BUF[1]) / 1090; // Combine MSB and LSB of X Data output register
    //GaZ = (BUF[2] << 8 | BUF[3]) / 1090; // Combine MSB and LSB of Z Data output register
    GaY = (float)(BUF[4] << 8 | BUF[5]) / 1090; // Combine MSB and LSB of Y Data output register

    if ((GaX > 0) && (GaY > 0))
        angle = atan(GaY / GaX) * 57;
    else if ((GaX > 0) && (GaY < 0))
        angle = 360 + atan(GaY / GaX) * 57;
    else if ((GaX == 0) && (GaY > 0))
        angle = 90;
    else if ((GaX == 0) && (GaY < 0))
        angle = 270;
    else if (GaX < 0)
        angle = 180 + atan(GaY / GaX) * 57;
        
    angle = angle + 90 - 37; //手动校正
    
    if (angle >= 360)
    {
        angle = angle - 360;
    }
    
    LCD_DispStr(0, 0, "You are heading ");
    
    sprintf(dis, "  A:%03d", angle);
    LCD_DispStr(0, 1, dis);
    LCD_DispOneChar(7, 1, 0xdf);

    if ((angle < 22.5) || (angle > 337.5))
    {
        LCD_DispStr(10, 1, "N  ");
    }
    else if ((angle >= 22.5) && (angle < 67.5))
    {
        LCD_DispStr(10, 1, "N-E");
    }
    else if ((angle >= 67.5) && (angle < 112.5))
    {
        LCD_DispStr(10, 1, "E  ");
    }
    else if ((angle >= 112.5) && (angle < 157.5))
    {
        LCD_DispStr(10, 1, "S-E");
    }
    else if ((angle >= 157.5) && (angle < 202.5))
    {
        LCD_DispStr(10, 1, "S  ");
    }
    else if ((angle >= 202.5) && (angle < 247.5))
    {
        LCD_DispStr(10, 1, "S-W");
    }
    else if ((angle >= 247.5) && (angle < 292.5))
    {
        LCD_DispStr(10, 1, "W  ");
    }
    else if ((angle >= 292.5) && (angle < 337.5))
    {
        LCD_DispStr(10, 1, "N-W");
    }
}

void DispAlarm(unsigned char setIndex, bit setAlarmFlag) //显示报警速度
{


    if (setAlarmFlag == 1)
    {
        LCD_WriteCommand(0x0F, 0);
    }
    else
    {
        LCD_WriteCommand(0x0C, 0);
        LCD_WriteCommand(0x0C, 0);
    }

    sprintf(dispRow0, "Alarm:%6.2fkm/h", (float)rateAlarm);
    sprintf(dispRow1, "Total:%8.2fkm", (float)totalDist / 1000);

    LCD_DispStr(0, 0, dispRow0);
    LCD_DispStr(0, 1, dispRow1);

    switch (setIndex)
    {
        case 1: LCD_LocateXY(8, 0); break;
        case 2: LCD_LocateXY(13, 1); break;
        default: ;
    }
}

void DispRate() //显示当前速度
{

    sprintf(dispRow0, "Rate:%7.2fkm/h", rate);
    sprintf(dispRow1, "Dist:%9.2fkm", distance / 1000);

    LCD_DispStr(0, 0, dispRow0);
    LCD_DispStr(0, 1, dispRow1);
}

void DispTime(unsigned char setIndex, bit setTimeFlag) //显示时间
{

    if (setTimeFlag == 1)
    {
        LCD_WriteCommand(0x0F, 0);
    }
    else
    {
        LCD_WriteCommand(0x0C, 0);
        LCD_WriteCommand(0x0C, 0);
    }

    sprintf(dispRow0, "%02d/%02d/%02d   ", (int)timeBufDec[1], (int)timeBufDec[2], (int)timeBufDec[3]);
    sprintf(dispRow1, "    %02d:%02d:%02d    ", (int)timeBufDec[4], (int)timeBufDec[5], (int)timeBufDec[6]);

    LCD_DispStr(0, 0, dispRow0);
    LCD_DispStr(0, 1, dispRow1);

    switch (timeBufDec[7])
    {
        case 0: LCD_DispStr(10, 0, " Sun. "); break;
        case 1: LCD_DispStr(10, 0, " Sun. "); break;
        case 2: LCD_DispStr(10, 0, " Mon. "); break;
        case 3: LCD_DispStr(10, 0, " Tue. "); break;
        case 4: LCD_DispStr(10, 0, " Wed. "); break;
        case 5: LCD_DispStr(10, 0, "Thur. "); break;
        case 6: LCD_DispStr(10, 0, " Fri. "); break;
        case 7: LCD_DispStr(10, 0, " Sat. "); break;
        default: ;
    }

    switch (setIndex)
    {
        case 1: LCD_LocateXY(1 , 0); break;
        case 2: LCD_LocateXY(4 , 0); break;
        case 3: LCD_LocateXY(7 , 0); break;
        case 4: LCD_LocateXY(14, 0); break;
        case 5: LCD_LocateXY(5 , 1); break;
        case 6: LCD_LocateXY(8 , 1); break;
        case 7: LCD_LocateXY(11, 1); break;
        default: ;
    }
}

void KeyProcess()
{
        if (!KEY_SET) //设置键按下
        {
            DelayMs(10);
            if (!KEY_SET)
            {
                if (dispMode == DISP_TIME_MODE)
                {
                    if (setTimeFlag == 0)
                    {
                        setTimeFlag = 1;
                        setIndex = 1;
                        DispTime(setIndex, setTimeFlag);
                    }
                }
                else if(dispMode == SET_ALARM_MODE)
                {
                    if (setAlarmFlag == 0)
                    {
                        setAlarmFlag = 1;
                        setIndex = 1;
                        DispAlarm(setIndex, setAlarmFlag);
                    }
                }
                else
                {
                    motorFlag = ~motorFlag;
                }
            }
            while (!KEY_SET)
                ;
        }

        if (!KEY_UP) //加键按下
        {
            DelayMs(150);
            if (!KEY_UP)
            {
                if (dispMode == DISP_TIME_MODE)
                {
                    if (setTimeFlag == 1)
                    {
                        switch (setIndex)
                        {
                        case 1:
                        {
                            timeBufDec[1]++;
                            if (timeBufDec[1] >= 100)
                            {
                                timeBufDec[1] = 0;
                            }
                            break;
                        }
                        case 2:
                        {
                            timeBufDec[2]++;
                            if (timeBufDec[2] >= 13)
                            {
                                timeBufDec[2] = 1;
                            }
                            break;
                        }
                        case 3:
                        {
                            timeBufDec[3]++;
                            if (timeBufDec[3] >= YDay(timeBufDec[1], timeBufDec[2]) + 1)
                            {
                                timeBufDec[3] = 1;
                            }
                            break;
                        }
                        case 4:
                        {
                            timeBufDec[7]++;
                            if (timeBufDec[7] > 7)
                            {
                                timeBufDec[7] = 1;
                            }
                            break;
                        }
                        case 5:
                        {
                            timeBufDec[4]++;
                            if (timeBufDec[4] >= 24)
                            {
                                timeBufDec[4] = 0;
                            }
                            break;
                        }
                        case 6:
                        {
                            timeBufDec[5]++;
                            if (timeBufDec[5] >= 60)
                            {
                                timeBufDec[5] = 0;
                            }
                            break;
                        }
                        case 7:
                        {
                            timeBufDec[6]++;
                            if (timeBufDec[6] >= 60)
                            {
                                timeBufDec[6] = 0;
                            }
                            break;
                        }
                        default:;
                        }
                        DispTime(setIndex, setTimeFlag);
                    }
                }
                else if (dispMode == SET_ALARM_MODE)
                {
                    if (setAlarmFlag)
                    {
                        switch (setIndex)
                        {
                            case 1:
                                
                                if (rateAlarm > 200)
                                {
                                    rateAlarm = 200;
                                }
                                else
                                {
                                    rateAlarm++;
                                }
                                break;
                            case 2:
                                totalDist = 0;
                                break;
                        }
                        DispAlarm(setIndex, setAlarmFlag);
                    }
                }
                else
                {
                    if (pwmValue <= 11)
                    {
                        pwmValue++;
                    }
                }
            }
            //while (!KEY_UP);
        }

        if (!KEY_DOWN)//减键按下
        {
            DelayMs(150);
            if (!KEY_DOWN)
            {
                if (dispMode == DISP_TIME_MODE)
                {
                    if (setTimeFlag == 1)
                    {
                        switch (setIndex)
                        {
                        case 1:
                        {
                            if (timeBufDec[1] == 0)
                            {
                                timeBufDec[1] = 100;
                            }
                            timeBufDec[1]--;
                            break;
                        }
                        case 2:
                        {
                            timeBufDec[2]--;
                            if (timeBufDec[2] < 1)
                            {
                                timeBufDec[2] = 12;
                            }
                            break;
                        }
                        case 3:
                        {
                            timeBufDec[3]--;
                            if (timeBufDec[3] < 1)
                            {
                                timeBufDec[3] = YDay(timeBufDec[1], timeBufDec[2]);
                            }
                            break;
                        }
                        case 4:
                        {
                            timeBufDec[7]--;
                            if (timeBufDec[7] < 1)
                            {
                                timeBufDec[7] = 7;
                            }
                            break;
                        }
                        case 5:
                        {
                            if (timeBufDec[4] == 0)
                            {
                                timeBufDec[4] = 24;
                            }
                            timeBufDec[4]--;
                            break;
                        }
                        case 6:
                        {
                            if (timeBufDec[5] == 0)
                            {
                                timeBufDec[5] = 60;
                            }
                            timeBufDec[5]--;
                            break;
                        }
                        case 7:
                        {

                            if (timeBufDec[6] == 0)
                            {
                                timeBufDec[6] = 60;
                            }
                            timeBufDec[6]--;
                            break;
                        }
                        default:;
                        }
                        DispTime(setIndex, setTimeFlag);
                    }
                }
                else if (dispMode == SET_ALARM_MODE)
                {
                    if (setAlarmFlag)
                    {
                        switch (setIndex)
                        {
                            case 1:
                                
                                if (rateAlarm <= 0)
                                {
                                    rateAlarm = 0;
                                }
                                else
                                {
                                    rateAlarm--;
                                }
                                break;
                            case 2:
                                totalDist = 0;
                                break;
                        }
                        DispAlarm(setIndex, setAlarmFlag);
                    }
                }
                else
                {
                    if (pwmValue > 8)
                    {
                        pwmValue--;
                    }
                }
            }
            //while (!KEY_DOWN);
        }

仿真演示视频:
https://www.bilibili.com/video/BV13R4y1G7k4/
实物演示视频:
https://www.bilibili.com/video/BV1Q5411Q7HL/

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值