基于51单片机的汽车智能灯光控制系统仿真

本文介绍了AT89C52单片机的基本特性和应用,如内部存储、I/O引脚、定时器/计数器等,同时详细阐述了HC-SR04非接触式测距模块的使用,以及两者在主程序中的配合,实现远光灯和近光灯控制,结合低功耗和按键操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

仿真图:

在这里插入图片描述

芯片/模块的特点:

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,可以满足大多数应用需求。

HC-SR04特点:

  1. 非接触式测距:HC-SR04利用超声波技术进行测距,可以在不接触测量目标物的情况下获取距离信息。这种非接触式的特性使得它在许多应用中非常有用。
  2. 宽测量范围:HC-SR04可以测量的距离范围较广,通常为2厘米到400厘米。这使得它可以满足许多测量需求,从近距离到远距离的测量都可以应对。
  3. 高精度:HC-SR04测量距离的精度相对较高,可以达到3毫米左右。这对于需要较精确距离测量的应用是非常有益的。
  4. 易于使用:HC-SR04的使用非常简单,只需要提供一个触发信号,然后等待接收到回波信号,并通过计算来确定距离。它使用简单的电平触发和回波检测机制。
  5. 快速测量响应:HC-SR04可以快速地对目标进行测量并提供准确的结果。它的测量响应时间通常在几十毫秒的范围内。
  6. 低功耗:HC-SR04的功耗相对较低,适合在需要长时间运行或使用电池供电的应用中使用。

主程序:

#include <reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include <stdio.h>
#include "delay.h"
//#include "math.h"
#define MANUAL 0
#define AUTO 1


sbit TRIG = P1^0; //出发放超声波
sbit ECHO = P1^1; //检测反馈



sbit LIGHT_FLAG = P1^2;

sbit HIGH_BEAM = P2^2; //远光灯

sbit LOW_BEAM = P2^3; //近光灯


sbit LED_MANUAL = P2^0; //手动模式指示灯

sbit LED_AUTO = P2^1; //自动模式指示灯

sbit KEY_CHANGE = P3^7; //远近光灯切换按键
sbit KEY_SWITCH = P3^6; //关灯按键
sbit KEY_MODE = P3^2; //自动手动切换

bit TrigFlag = 0; //触发标志
unsigned char LEDFlag = 0; //远近光灯标志
float distance = 0; //实际测试距离
bit modeFlag = 0;   //手动自动模式变量
bit switchFlag = 0;
bit rekey0;
bit rekey1;
bit rekey2; //按键防止重复变量

void Timer0_Init(); //函数声明
void Timer1_Init();
void KeyProcess();

void main()
{
    TRIG = 0;
    Timer0_Init(); //定时器0初始化
    Timer1_Init();
    HIGH_BEAM = 0;      //远光灯
    LOW_BEAM = 0;      //近光灯
    LED_MANUAL = 0;      //手动指示灯
    LED_AUTO = 0;      //自动指示灯
    DelayS(1);
    HIGH_BEAM = 1; //远光灯
    LOW_BEAM = 1; //近光灯
    LED_MANUAL = 1; //手动灯
    LED_AUTO = 1; //自动灯

    while (1) //主循环
    {
        if (TrigFlag == 1)
        {
            TR0 = 0;
            TrigFlag = 0;
            TRIG = 1; //启动一次模块		//不可以使用其他终端 容易造成死循环
            DelayUs10x(1);
            TRIG = 0;
            while (!ECHO)
                ;    //当RX为零时等待
            TR1 = 1; //开启计数
            while (ECHO)
                ; //当RX为1计数并等待
            TR1 = 0;
            distance = 1.12 * ((float)TH1 * 256 + TL1) * 17 / 100; //算出来是mm,1.12为系数
            TH1 = 0;
            TL1 = 0;
            TH0 = (65536 - 18432) / 256; //重新赋值 20ms
            TL0 = (65536 - 18432) % 256;
            TR0 = 1;
        }

        if (switchFlag == 1)
        {
            if (modeFlag == AUTO) //自动模式下
            {
                LED_MANUAL = 1;
                LED_AUTO = 0;
                if (LIGHT_FLAG == 1) //光照暗
                {
                    if (distance < 300)
                    {
                        LOW_BEAM = 0;  //近光灯开
                        HIGH_BEAM = 1; //远光灯关
                    }
                    else
                    {
                        LOW_BEAM = 1;  //近光灯关
                        HIGH_BEAM = 0; //远光灯开
                    }
                }
                else
                {
                    LOW_BEAM = 1;  //近光灯关
                    HIGH_BEAM = 1; //远光灯关
                }
            }
            else
            {
                LED_MANUAL = 0;
                LED_AUTO = 1;
                if (LEDFlag == 0)
                {
                    LOW_BEAM = 1;  //近光灯关
                    HIGH_BEAM = 1; //远光灯关
                }
                else if (LEDFlag == 1)
                {
                    LOW_BEAM = 0;  //近光灯开
                    HIGH_BEAM = 1; //远光灯关
                }
                else
                {
                    LOW_BEAM = 1;  //近光灯关
                    HIGH_BEAM = 0; //远光灯开
                }
            }
        }
        else
        {
            LOW_BEAM = 1;  //近光灯关
            HIGH_BEAM = 1; //远光灯关
            //指示灯闪烁,有助于判断程序是否运行
            LED_MANUAL = 1; 
            LED_AUTO = 1; 
            DelayMs(250);
            DelayMs(250);
            LED_MANUAL = 0; 
            LED_AUTO = 0;
            DelayMs(250);
            DelayMs(250);
        }

        KeyProcess();
    }
}

void KeyProcess()
{
    if (switchFlag == 1)
    {
        if (KEY_MODE == 0) //手动自动切换
        {
            DelayMs(10);
            if (KEY_MODE == 0 && rekey0 == 0)
            {
                rekey0 = 1;
                modeFlag = ~modeFlag;
            }
        } //切换置位对应灯亮
        else
        {  
            rekey0 = 0;
        }

        if (modeFlag == MANUAL) //手动模式下
        {
            if (KEY_CHANGE == 0) //远光灯切换按键
            {
                DelayMs(10);
                if (KEY_CHANGE == 0 && rekey1 == 0) //远光灯切换按键
                {
                    rekey1 = 1;
                    if (LEDFlag >= 2)
                    {
                        LEDFlag = 1;
                    }
                    else
                    {
                        LEDFlag++;
                    }
                }
            }
            else
            {
                rekey1 = 0;
            }
        }
    }

    if (KEY_SWITCH == 0) //切换按键
    {
        DelayMs(10);
        if (KEY_SWITCH == 0 && rekey2 == 0) //切换按键
        {
            rekey2 = 1;
            switchFlag = ~switchFlag;
        }
    }
    else
    {
        rekey2 = 0;
    }
}

void Timer0_Init()
{
    TMOD &= 0xF0;
    TMOD |= 0x01;                //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
    TH0 = (65536 - 18432) / 256; //重新赋值 20ms
    TL0 = (65536 - 18432) % 256;
    EA = 1;  //总中断打开
    ET0 = 1; //定时器中断打开
    TR0 = 1; //定时器开关打开
}

void Timer1_Init()
{
    TMOD &= 0x0F;
    TMOD |= 0x10;                //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
    TH1 = 0; 
    TL1 = 0;
    EA = 1;  //总中断打开
    ET1 = 1; //定时器中断打开
    TR1 = 0; //定时器开关关闭
}

void Timer0_Interrupt() interrupt 1
{
    static unsigned int cnt = 0;

    TH0 = (65536 - 18432) / 256; //重新赋值 20ms
    TL0 = (65536 - 18432) % 256;

    cnt++;
    if (cnt > 50) //1s定时发出超声波
    {
        TrigFlag = 1;
        cnt = 0;
    }
}

void Timer1_Interrupt() interrupt 3
{
    TH1 = 0;
    TL1 = 0;
}

设计文件:

链接:https://pan.baidu.com/s/1m80YJYcjLAy20WpTOGBFNg?pwd=s4ne

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值