基于51单片机的码表里程表仿真

仿真图:

在这里插入图片描述

芯片/模块的特点:

AT89C52简介:
AT89C52是一款经典的8位单片机,是意法半导体(STMicroelectronics)公司生产的一系列单片机之一。它基于8051内核,并具有许多与其兼容的特性。

AT89C52的主要特点如下:

内部存储器:AT89C52具有8KB的闪存(Flash)存储器,可用于存储用户程序和数据。这些存储器的内容可以通过编程器进行编程和擦除。

RAM存储器:AT89C52配备了256字节的随机存取存储器(RAM),用于暂存数据和程序的变量。

外部扩展性:AT89C52支持多种外部扩展设备的连接,包括外部存储器(如RAM、EEPROM)和外设(如ADC、LCD、UART等),通过外部硬件连接,可以扩展单片机的功能和应用。

通用I/O引脚:AT89C52拥有32个可编程的通用输入/输出引脚,可用于连接外部设备和与其他芯片进行通信。

定时器/计数器:AT89C52内置了3个16位定时器/计数器和一个可编程的串行定时器/计数器。这些计时器/计数器可用于实现定时功能、生成脉冲信号、测量时间间隔等。0

串行通信:AT89C52支持串行通信接口,包括UART(串行异步通信)和SPI(串行外设接口),便于与其他设备进行数据通信和交互。

低功耗模式:AT89C52具有多种低功耗模式,如空闲模式和电源下模式,在不需要执行任务的时候可以将CPU进入低功耗状态以节省能量。

宽电源电压范围:AT89C52的工作电压范围通常为4.0V至5.5V,可以满足大多数应用需求。

24C02特点:
存储容量:24C02具有2K位的存储容量,即可以存储2千个位数据。它的存储空间被组织成256个字节,每个字节由8个位组成。

串行接口:24C02采用串行接口进行数据读写,与主控器件之间进行通信。它使用两根线路(串行数据线SDA和串行时钟线SCL)进行数据传输,简化了连接和控制电路。

低功耗:24C02在工作时功耗低,适用于电池供电或对功耗要求较高的应用场景。它还具有自动功耗优化功能,可以在闲置状态下自动进入低功耗模式。

多功能保护:24C02具有多种数据保护功能,包括写保护、密钥保护和唯一序列号保护。这些功能可以保护数据的安全性和完整性。

高速读写操作:24C02支持快速的读写操作,具备高达400 kHz的传输速度。它能够快速、准确地读取和写入存储器中的数据。

长寿命和可靠性:24C02采用耐用的封装材料,具有较高的抗震动和抗振动能力。它具备较长的数据保存时间和可靠性,适用于各种工业和消费类应用。

DS1302特点:
高精度时间计数:DS1302能够提供高精度的实时时钟计数,可以记录年、月、日、星期、小时、分钟和秒等时间信息。它内部集成了晶体振荡器,提供稳定的时钟信号。

低功耗设计:DS1302采用低功耗设计,可以在低功耗模式下运行,有效延长电池寿命。即使在停电情况下,它也能保持时间数据,并通过外部连接电池继续提供计时功能。

串行接口:DS1302通过串行实时时钟接口(SPI)进行通信和控制。使用少数几个引脚,可以与主控器件进行数据交换和时钟同步。

容易集成:DS1302集成了时钟计数和RAM存储器功能,并具有简单的接口和命令,容易与各种微控制器和单片机集成。它不需要复杂的控制信号,可以通过简单的读写命令进行操作。

可编程控制功能:DS1302具有可编程的控制功能,可以设置闹钟、写保护等特殊功能。它还支持多种时间格式的选择,例如24小时制或12小时制。

温度补偿:DS1302内置温度补偿功能,可以校正温度对时钟频率的影响,提高时钟计数的准确性。

高稳定性和抗震动能力:DS1302具有高稳定性和抗震动能力,适用于各种工业和消费类应用场景。

主程序:

#include <reg52.h>
#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 = 3;
unsigned char setIndex = 0;

enum{
    DISP_RATE_MODE, DISP_TIME_MODE, SET_ALARM_MODE
} dispMode;

void main()
{
    //初始化
    LCD_Init();
    DS1302_Init();
    EEPROM_Init();

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

    ReadEEPROM();
    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!    ");
    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_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 DispAlarm(unsigned char setIndex, bit setAlarmFlag)
{
    static unsigned char xdata dispRow0[16];
    static unsigned char xdata dispRow1[16];

    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()
{
    static unsigned char xdata dispRow0[16];
    static unsigned char xdata dispRow1[16];

    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)
{
    static unsigned char xdata dispRow0[] = "  /  /     ";
    static unsigned char xdata dispRow1[] = "      :  :      ";

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

    dispRow0[0] = timeBufDec[1] / 10 +'0';
    dispRow0[1] = timeBufDec[1] % 10 +'0';
    dispRow0[3] = timeBufDec[2] / 10 +'0';
    dispRow0[4] = timeBufDec[2] % 10 +'0';
    dispRow0[6] = timeBufDec[3] / 10 +'0';
    dispRow0[7] = timeBufDec[3] % 10 +'0';
    dispRow1[4] = timeBufDec[4] / 10 +'0';
    dispRow1[5] = timeBufDec[4] % 10 +'0';  
    dispRow1[7] = timeBufDec[5] / 10 +'0';
    dispRow1[8] = timeBufDec[5] % 10 +'0';
    dispRow1[10] = timeBufDec[6] / 10 +'0';
    dispRow1[11] = timeBufDec[6] % 10 +'0';

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

    switch (timeBufDec[7])
    {
        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(200);
            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:
                                rateAlarm++;
                                if (rateAlarm > 200)
                                {
                                    rateAlarm = 200;
                                }
                                break;
                            case 2:
                                totalDist = 0;
                                break;
                        }
                        DispAlarm(setIndex, setAlarmFlag);
                    }
                }
                else
                {
                    if (pwmValue <= 11)
                    {
                        pwmValue++;
                    }
                }
            }
            //while (!KEY_UP);
        }

        if (!KEY_DOWN) //下键按下
        {
            DelayMs(200);
            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--;
                                }
                                break;
                            case 2:
                                totalDist = 0;
                                break;
                        }
                        DispAlarm(setIndex, setAlarmFlag);
                    }
                }
                else
                {
                    if (pwmValue > 3)
                    {
                        pwmValue--;
                    }
                }
            }
            //while (!KEY_DOWN);
        }

        if (!KEY_LEFT) //左键按下
        {
            DelayMs(10);
            if (!KEY_LEFT)
            {
                if (dispMode == DISP_TIME_MODE)
                {
                    if (setTimeFlag == 1)
                    {
                        setIndex--;
                        if (setIndex < 1)
                        {
                            setIndex = 7;
                        }
                        DispTime(setIndex, setTimeFlag);
                    }
                }
                else if (dispMode == SET_ALARM_MODE)
                {
                    if (setAlarmFlag)
                    {
                        setIndex--;
                        if (setIndex < 1)
                        {
                            setIndex = 2;
                        }
                        DispAlarm(setIndex, setAlarmFlag);
                    }
                }
                
            }
            while (!KEY_LEFT)
                ;
        }

        if (!KEY_RIGHT) //右键按下
        {
            DelayMs(10);
            if (!KEY_RIGHT)
            {
                if (dispMode == DISP_TIME_MODE)
                {
                    if (setTimeFlag == 1)
                    {
                        setIndex++;
                        if (setIndex > 7)
                        {
                            setIndex = 1;
                        }
                        DispTime(setIndex, setTimeFlag);
                    }
                }
                if (setAlarmFlag)
                    {
                        setIndex++;
                        if (setIndex > 2)
                        {
                            setIndex = 1;
                        }
                        DispAlarm(setIndex, setAlarmFlag);
                    }
            }
            while (!KEY_RIGHT)
                ;
        }

        if (!KEY_ENTER) //确认键按下
        {
            DelayMs(10);
            if (!KEY_ENTER)
            {
                if (dispMode == DISP_RATE_MODE)
                {
                    dispMode = DISP_TIME_MODE;
                    setTimeFlag = 0;
                    setIndex = 0;
                }
                else if (dispMode == DISP_TIME_MODE)
                {
                    if (setTimeFlag == 1)
                    {
                        setTimeFlag = 0;
                        setIndex = 0;
                        DS1302_WriteTime();
                        DispTime(setIndex, setTimeFlag);
                    }
                    else
                    {
                        dispMode = SET_ALARM_MODE;
                        setIndex = 0;
                    }
                }
                else if (dispMode == SET_ALARM_MODE)
                {
                    if (setAlarmFlag == 1)
                    {
                        setAlarmFlag = 0;
                        setIndex = 0;
                        WriteEEPROM();
                        DispAlarm(setIndex, setAlarmFlag);
                    }
                    else
                    {
                        dispMode = DISP_RATE_MODE;
                        setIndex = 0;
                    }
                }
            }
            while (!KEY_ENTER)
                ;
        }
}

void EXT1_Init()
{
    IT1 = 1; //下降沿触发
    EX1 = 1; //使能外部中断0
    EA = 1; //打开总中断
}

void EXT1_Interrupt() interrupt 2 using 1
{
    pulseCnt++;
}

void Timer0_Init(void)
{
    TMOD &= 0xF0; //定时器模式0
    TMOD |= 0x01;
    PT0 = 1; //设置T0为高优先级
    TH0 = RH_10MS(3); //10ms
    TL0 = RL_10MS(3);
    TR0 = 1; //启动T0计时
    ET0 = 1; //打开T0中断
    EA = 1;  //打开总中断
}

void Timer0_Intterupt(void) interrupt 1 using 0
{
    static unsigned int cnt=0;   
    static unsigned char IN1Count = 0;
    
//    TH0 = 0xF8; //设置定时初值
//    TL0 = 0xCD; //设置定时初值 2ms
    
    TH0 = 0xFC; //设置定时初值
    TL0 = 0x66; //设置定时初值 1ms
    
    IN1Count++;
    cnt++;
    
    if (motorFlag == 1)
    {
        if (IN1Count < pwmValue) //占空比调节
        {
            MOTOR = 0;    
        }
        else if ((IN1Count >= pwmValue) && (IN1Count <= 11)) //关闭时间段
        {
            MOTOR = 1;
        }
        else
        {
            IN1Count = 0; //一个周期结束
        }
    }
    else
    {
        MOTOR = 1;
    }
    if (cnt >= 250) //500ms
    {
        dispFlag = ~dispFlag;
        cnt = 0;
    }
}

void Timer1_Init(void)
{
    TMOD &= 0x0F; //定时器模式1
    TMOD |= 0x10;
    TH1 = RH_10MS(5); //50ms
    TL1 = RL_10MS(5);
    TR1 = 1; //开启T1计时
    ET1 = 1; //打开T1中断
    EA = 1;  //打开总中断
}


void Timer1_Intterupt(void) interrupt 3 using 2
{
    static unsigned int cnt=0;

    TH1 = RH_10MS(5); //50ms
    TL1 = RL_10MS(5);

    cnt++;
    if (cnt >= 20) //1s
    {
        EX1 = 0;
        if (second >= 60)
        {
            second = 0;
            minute++;
            if (minute == 1)
            {
                writeFlag = 1;
                minute = 0;
            }
        }
        else
        {
            second++;
        }
        
        refreshFlag = 1;
        cnt = 0;
    }
}



设计文件:

链接:https://pan.baidu.com/s/1cIazVFRddKprFV11rI9fog?pwd=ghiu

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值