• 【毕业设计】基于超声波与红外的自动调速风扇系统(代码开源) -物联网 嵌入式 stm32



    1 简介

    Hi,大家好,这里是丹成学长,今天向大家介绍一个 单片机项目,大家可用于 课程设计 或 毕业设计

    基于超声波与红外的自动调速风扇系统


    单片机-嵌入式毕设选题大全及项目分享:

    https://blog.csdn.net/m0_71572576/article/details/125409052


    1 设计概要

    本系统为基于红外和超声波的手动/自动调速风扇系统,风扇转速的调节模式可分为自动模式与手动模式:在自动模式下,由超声波检测人与风扇的距离,根据距离调节风扇转速;在手动模式下,可通过红外遥控的按键调节风扇转速。相应参数信息通过LCD液晶显示屏显示。本系统的主控芯片采用STC89C52单片机,测距采用HC-SR04超声波模块,风扇电机由L298N电机驱动模块驱动,遥控部分用传统的红外遥控器,显示部分用LCD1602液晶显示屏。电机驱动模块采用12V供电,单片机及其他各部分采用5V供电。

    在这里插入图片描述

    2 系统设计

    2.1 系统供电问题

    STC89C52单片机及超声波传感器、红外遥控接收头、液晶显示屏均为+5V标准供电,可以直接使用电脑USB接口引出电压。但考虑到电机用到PWM调速,需要大电压和大电流,因此决定使用电池盒额外供电。

    2.2 自动/手动模式的切换

    主函数内部用一个while大循环,超声波数据采集及电机驱动等程序均放在循环内部。在while内部有两段程序,一段为手动模式,一段为自动模式,分别放在if…else…的两个分支内。定义全局变量flag,在红外遥控中断内部可改变flag的值,通过flag的值控制if…else…选择结构的走向,进而实现两种模式的切换。

    2.3 PWM信号的产生

    电机转速调节需用到PWM信号,需由单片机内部产生。有两种可行方案:其一为通过软件延时,不断地改变某一引脚电平的高低,由该引脚向外输出PWM信号;其二为通过中断计时,计满后进入中断服务程序,在中断服务程序中改变某一引脚电平的高低,由该引脚向外输出PWM信号。考虑到系统较为复杂,用方案一在时间上会占用单片机的大量资源,影响到系统的稳定性和实时性,因此采用方案二。

    2.4 单片机内部资源的分配

    在本系统中,用到两个定时器和两个中断:超声波测距时等待返回波用到一个定时器,控制PWM信号的发生用到一个定时器;红外遥控的响应用到一个外部中断,PWM信号的发生用到定时器中断。考虑到系统的实时性,给红外遥控分配优先级最高的外部中断0,PWM信号发生使用定时器T0并开中断,超声波测距使用定时器T1,不开中断。

    三、硬件搭建

    由于硬件部分中的很多模块在仿真软件中都没有,且各模块之间的连接关系比较简单,因此在这里不提供电路图,仅用语言描述各引脚之间的连接关系。

    3.1 单片机最小系统

    对51 系列单片机来说, 最小系统一般应该包括: 单片机、时钟电路、复位电路、输入/ 输出设备等。最小系统的焊接有一套标准的流程,为基本功,这里不做赘述。

    3.2 电机驱动模块

    本系统电机驱动模块使用常见的L298N电机驱动模块。L298N芯片可以驱动两个二相电机,也可以驱动一个四相电机,输出电压最高可达50V,可以直接通过电源来调节输出电压;可以直接用单片机的IO口提供信号;而且电路简单,使用比较方便。

    在本系统中,只使能了EnA来驱动一个电机,其中EnA接单片机引脚P20,IN1接P21,IN2接P22。L298N电机驱动模块实物图如下所示:

    在这里插入图片描述

    3.3 超声波测距模块

    在自动调速模式下,需用到超声波模块采集距离信息。本系统采用HC-SR04超声波模块, HC-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测距精度可达高到3mm;模块包括超声波发射器、接收器与控制电路。基本工作原理:

    • (1)采用I0口TRIG触发测距,给至少10us的高电平信号;

    • (2)模块自动发送8个40khz的方波,自动检测是否有信号返回;

    • (3)有信号返回,通过I0口ECHO输出一个高电平,高电平持续的时间就是超声往返所用的时间。

    • (4)根据声音在空气中的速度为344米/秒,即可计算出所测的距离。

    在本系统中,超声波模块的Trig脚接单片机引脚P36,Echo脚接单片机引脚P22。HC-SR04工作时序图如下所示:

    在这里插入图片描述

    3.4 红外遥控模块

    根据使用的编码芯片不同,红外遥控编码的格式也不同,较普遍的有NEC标准和PHILIPS标准。最常用的是NEC标准,本系统采用的也是NEC标准。

    NEC标准:遥控载波的频率为38KHz(占空比1:3)当某个键按下时,发射端首先发射一个完整的全码,如果按键超过108ms仍未松开,接下来发射的代码(连发代码)将由起始码(9ms)和结束码(2.5ms)组成,并每隔108ms重复。

    一个完整的全码由引导码、用户码、用户码、数据码、数据码以及数据反码共同组成。其中,引导码高电平9ms,低电平4.5ms;系统码8位,数据码8位,共32位;其中前16位为用户识别码,能区别不同的红外遥控设备,以防止不同的机种遥控码互相干扰。后16位为8位的操作码和8位的操作反码,用于核对数据是否接收准确。收端根据数据码做出应该执行上面动作的判断。连发代码是在持续按键时发送的码。它告知接收端。某键是在被连续的按着。

    NEC标准下的发射码表示:发射数据0时用“0.56ms高电平 + 0.565ms低电平 = 1.125ms”表示;发射数据1用“0.56ms高电平 + 1.69ms低电平 = 2.25ms”表示。

    在本系统中,红外接收器的INIR脚接单片机引脚P32。NEC标准完整码组成及NEC标准发射码如下所示:

    在这里插入图片描述

    3.5 液晶显示模块

    本系统的液晶显示部分采用LCD1602液晶显示屏。1602液晶也叫1602字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵型液晶模块 它有若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符。每位之间有一个点距的间隔,每行之间也有也有间隔,起到了字符间距和行间距的作用。

    LCD1602是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。目前市面上字符液晶绝大多数是基于HD44780液晶芯片的,控制原理是完全相同的,因此基于HD44780写的控制程序可以很方便地应用于市面上大部分的字符型液晶。

    在本系统中,液晶显示屏接法如下所示:

    在这里插入图片描述

    3.6 供电模块

    为了驱动电机,需采用+12V供电,结合手上现有资源,决定采用4节3.7V的锂电池串联供电。串联后的输出电压在+15V左右,使用LM2596S直流降压模块,将电压降至+12V后提供给电机驱动模块L298N,单片机所需的+5V电可直接从电机驱动模块中引出。

    4 工程代码(全开源)

    代码用C语言编写,在Keil5环境下开发的。给每个模块都写了驱动,每个模块的驱动拿出后略加改动,都能单独使用。代码工程结构如下所示:

    在这里插入图片描述

    4.1 总头文件

    把常用的宏定义和硬件的引脚连接定义到了reg52.h里面,更名为my52.h。所以整个工程代码中每个文件都#include "my52.h"而不是 #include “reg52.h”。

    #ifndef __MY52_H__
    #define __MY52_H__
    
    /*  BYTE Registers  */
    sfr P0    = 0x80;
    sfr P1    = 0x90;
    sfr P2    = 0xA0;
    sfr P3    = 0xB0;
    sfr PSW   = 0xD0;
    sfr ACC   = 0xE0;
    sfr B     = 0xF0;
    sfr SP    = 0x81;
    sfr DPL   = 0x82;
    sfr DPH   = 0x83;
    sfr PCON  = 0x87;
    sfr TCON  = 0x88;
    sfr TMOD  = 0x89;
    sfr TL0   = 0x8A;
    sfr TL1   = 0x8B;
    sfr TH0   = 0x8C;
    sfr TH1   = 0x8D;
    sfr IE    = 0xA8;
    sfr IP    = 0xB8;
    sfr SCON  = 0x98;
    sfr SBUF  = 0x99;
    
    /*  8052 Extensions  */
    sfr T2CON  = 0xC8;
    sfr RCAP2L = 0xCA;
    sfr RCAP2H = 0xCB;
    sfr TL2    = 0xCC;
    sfr TH2    = 0xCD;
    
    
    /*  BIT Registers  */
    /*  PSW  */
    sbit CY    = PSW^7;
    sbit AC    = PSW^6;
    sbit F0    = PSW^5;
    sbit RS1   = PSW^4;
    sbit RS0   = PSW^3;
    sbit OV    = PSW^2;
    sbit P     = PSW^0; //8052 only
    
    /*  TCON  */
    sbit TF1   = TCON^7;
    sbit TR1   = TCON^6;
    sbit TF0   = TCON^5;
    sbit TR0   = TCON^4;
    sbit IE1   = TCON^3;
    sbit IT1   = TCON^2;
    sbit IE0   = TCON^1;
    sbit IT0   = TCON^0;
    
    /*  IE  */
    sbit EA    = IE^7;
    sbit ET2   = IE^5; //8052 only
    sbit ES    = IE^4;
    sbit ET1   = IE^3;
    sbit EX1   = IE^2;
    sbit ET0   = IE^1;
    sbit EX0   = IE^0;
    
    /*  IP  */
    sbit PT2   = IP^5;
    sbit PS    = IP^4;
    sbit PT1   = IP^3;
    sbit PX1   = IP^2;
    sbit PT0   = IP^1;
    sbit PX0   = IP^0;
    
    /*  P3  */
    sbit RD    = P3^7;
    sbit WR    = P3^6;
    sbit T1    = P3^5;
    sbit T0    = P3^4;
    sbit INT1  = P3^3;
    sbit INT0  = P3^2;
    sbit TXD   = P3^1;
    sbit RXD   = P3^0;
    
    /*  SCON  */
    sbit SM0   = SCON^7;
    sbit SM1   = SCON^6;
    sbit SM2   = SCON^5;
    sbit REN   = SCON^4;
    sbit TB8   = SCON^3;
    sbit RB8   = SCON^2;
    sbit TI    = SCON^1;
    sbit RI    = SCON^0;
    
    /*  P1  */
    sbit T2EX  = P1^1; // 8052 only
    sbit T2    = P1^0; // 8052 only
    
    /*  T2CON  */
    sbit TF2    = T2CON^7;
    sbit EXF2   = T2CON^6;
    sbit RCLK   = T2CON^5;
    sbit TCLK   = T2CON^4;
    sbit EXEN2  = T2CON^3;
    sbit TR2    = T2CON^2;
    sbit C_T2   = T2CON^1;
    sbit CP_RL2 = T2CON^0;
    
    /*------------------一下为添加部分---------------------*/
    
    #define uint unsigned int
    #define uchar unsigned char
    
    #define HighGear 4
    #define MiddleGear 3
    #define LowGear 2
    
    //电机驱动
    sbit ENA = P2^0; //PWM输入端口
    sbit IN1 = P2^1; //0
    sbit IN2 = P2^2; //1
    
    //超声波
    sbit Trig=P3^6;
    sbit Echo=P3^7;
    
    //LCD1602
    sbit RS=P1^2;  // 数据/命令选择端(H/L)
    sbit RW=P1^1;  //读写选择端(H/L)
    sbit E=P1^0;   //使能信号
    
    //红外遥控
    sbit IRIN=P3^2;// 红外接收器端口定义,外部中断0优先级最高
    
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133

    4.2 电机驱动及头文件

    电机驱动文件motor_driver.c:

    #include "my52.h"
    
    uchar motor_gear,pwm_num;
    
    void motor_run(uchar gear)
    {
        motor_gear = gear; //挡位设置,分2,3,4档
        TMOD = 0x11; //设置定时器1为工作方式1
        TH1 = (65536-100)/256; //装初值,每0.1ms中断一次
        TL1 = (65536-100)%256;
        ET1 = 1; //开定时器1中断
        TR1 = 1; //启动定时器1
    }
    
    void T1_PWM() interrupt 3
    {
        TH1 = (65536-100)/256; //装初值
        TL1 = (65536-100)%256;
        pwm_num++;
        if(pwm_num == 5)
            pwm_num = 0;
        if(pwm_num <= motor_gear)
            ENA = 1;
        else
            ENA = 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    电机驱动头文件motor_driver.h

    1 #ifndef __MOTOR_DRIVER_C__
    2 #define __MOTOR_DRIVER_C__
    3 extern motor_run(uchar gear); //可填2,3,4,占空比分别为0.6,0.8,1
    4 #endif
    
    • 1
    • 2
    • 3
    • 4

    4.3 超声波驱动及头文件

    超声波驱动文件sr04_driver.c:

    #include "my52.h"
    #include "motor_driver.h"
    #include <intrins.h> // _nop_()延时
    
    extern uchar InfraredGear;
    
    uint distance()     //HC-SR04超声波测距模块工作函数
    {
        uint dis = 0;
        uint time = 0;
        uchar i = 10;
    
        Trig = 0;//初始化
        Echo = 0;
    
    
        TMOD = 0x11;
        TH0=0;//给T0装初值0
        TL0=0;
    
        Trig = 1;
        while(i--)
            _nop_();
        while(Echo==0);
        TR0=1;//启动T0
        while(Echo==1);//等待返回信号的接收完毕
        time=TH0*256+TL0;//微秒
        dis=(time*1.7+5)/10;//340米每秒即0.34毫米每微秒,1.7=0.34/2×10,来回除2,四舍五入先乘10
        TR0=0;//关闭T0
    
        return dis;
    }
    
    void sr04_motor(uint dist)
    {
        if(dist <= 300)
            InfraredGear = LowGear;
        else if(dist > 600)
            InfraredGear = HighGear;
        else
            InfraredGear = MiddleGear;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    超声波驱动头文件sr04_driver.h:

    4.4 红外遥控驱动及头文件

    红外遥控驱动文件infrared_driver.c:

    #include "my52.h"
    #include "delay.h"
    
    extern uchar InfraredGear;
    extern uchar Flag ;
    
    uchar IrValue[4];//两位用户码,一位数据码,一位数据反码
    uchar num;
    
    void read() interrupt 0{//红外中断读取档位数据
        uchar j,k,t;
        uint i;
        num=0;
        t=IrValue[2];
        delay_ms(7);//起始码前9ms为低电平,在这里等待7ms
        if(IRIN==0){//确认真的收到信号后执行以下程序
            i=1000;    //如果出错利用i跳出以下等待,以免程序在这里死循环
            while((IRIN==0)&&(i>0)){ //等待前9ms结束
                delay_10us(1);
                i--;
            }
            if(IRIN==1){//起始码前9ms结束,后4.5ms为高电平
                i=500; //用i防止死循环
                while((IRIN==1)&&(i>0)){//等待起始码的后4.5ms高电平
                    delay_10us(1);
                    i--;
                }
                for(k=0;k<4;k++){//2个用户码,1个数据码,1个数据反码,共4个字节
                    for(j=0;j<8;j++){ //每个字节8位,以下程序用于确定每位电平的高低
                        i=60;
                        while((IRIN==0)&&(i>0)){//等待0.56ms的低电平,每位前面都有0.56ms的低电平
                            delay_10us(1);            //后面高电平0.565ms(565us)为0,   1.69ms(1690us)为1
                            i--;
                        }
                        i=500;
                        while((IRIN==1)&&(i>0)){//低电平结束,高电平到来后进入,用于计算高电平持续时间
                            delay_10us(10);//延时100us
                            num++;
                            i--;
                            if(num>30){//超出3000us(3ms),本程序出错(最大不能超过2.25ms),返回主调函数
                                return;
                            }
                        }
                        IrValue[k]>>=1;//腾出最高位用于接收本位数据
                        if(num>=8){//高电平持续时间大于800us,该位为1
                            IrValue[k]|=0x80; //给最高位写1
                        }
                        num=0;    //计数变量清零
                    }
                }
            }
            if(IrValue[2]!=~IrValue[3]){//数据位校验
                IrValue[2]=t;
                return;
            }
        }
        if(IrValue[2]==69)
            InfraredGear=LowGear;
        else if(IrValue[2]==70)
            InfraredGear=MiddleGear;
        else if(IrValue[2]==71)
            InfraredGear=HighGear;
        else if(IrValue[2]==68)      //切换自动模式
            Flag = 0;
        else if(IrValue[2]==67)      //切换手动模式
            Flag = 1;
        else if(IrValue[2]==64)      //急停
            IN1 = 1;
        else if(IrValue[2]==21)
            IN1 = 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    红外遥控驱动头文件infrared_driver.h

    1 #ifndef __INFRARED_DRIVER_C__
    2 #define __INFRARED_DRIVER_C__
    3 
    4 #endif
    
    • 1
    • 2
    • 3
    • 4

    4.5 液晶显示驱动及头文件

    液晶显示驱动文件lcd1602_driver.c:

    #include "my52.h"
    
    extern uchar InfraredGear;
    
    void delays(uint i)
    {
        uchar j;
        while(i--)
            for(j=50;j>0;j--);
    }
    void write_com(uchar com)
    {
        RS=0;
        P0=com;
        delays(1);
        E=1;
        delays(1);
        E=0;
    }
    void write_date(uchar date)
    {
        RS=1;
        P0=date;
        delays(1);
        E=1;
        delays(1);
        E=0;
    }
    void lcdinit()
    {
        RW=0;
        E=0;
        write_com(0x38); //设置16X2显示,5X7点阵,8位数据接口
        write_com(0x0c); //设置开显示,不显示光标
        write_com(0x06); //写一个字符后地址指针加1
        write_com(0x01); //显示清零,数据指针清零
    }
    
    void display0(uint dis) //手动调速下1602显示
    {
        uchar g1,g2,g3,g4;
        g1=dis%10;
        g2=(dis/10)%10;
        g3=(dis/100)%10;
        g4=dis/1000;
        lcdinit();
        write_com(0x80);
        write_date('M');
        write_date('o');
        write_date('d');
        write_date('e');
        write_date('l');
        write_date(':');
        write_date('A');
        write_date('U');
        write_date('T');
        write_date('O');
    
        write_date(' ');//挡位显示
        write_date(0x30+InfraredGear-1);
    
        write_com(0x80+0x40);//换行显示
    
        write_date('D');//距离显示
        write_date('i');
        write_date('s');
        write_date(':');
        write_date(0x30+g4);
        write_date(0x30+g3);
        write_date(0x30+g2);
        write_date(0x30+g1);
        write_date('m');
        write_date('m');
    }
    
    void display1()
    {
        lcdinit();
        write_com(0x80);
    
        write_date('M');
        write_date('o');
        write_date('d');
        write_date('e');
        write_date('l');
        write_date(':');
        write_date('M');
        write_date('A');
        write_date('N');
        write_date('U');
    
        write_date(' ');//挡位显示
        write_date(0x30+InfraredGear-1);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94

    液晶显示驱动头文件lcd1602_driver.h:

    #ifndef __LCD1602_DRIVER_C__
    #define __LCD1602_DRIVER_C__
    extern void delays(uint i);
    extern void write_com(uchar com);
    extern void write_date(uchar date);
    extern void lcdinit();
    extern void display0(uint dis);
    extern void display1();
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    4.6 延时函数及头文件

    延时函数所在文件delay.c:

    #include "my52.h"
    
    void delay_ms(uint t)
    {
        uint i,j;
        for(i=0;i<t;i++)
            for(j=0;j<114;j++);
    }
    
    void delay_10us(uint t)  //延时函数,t=1延时10us
    {
        while(t--);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    4.7 主函数

    #include "my52.h"
    #include "motor_driver.h"
    #include "sr04_driver.h"
    #include "delay.h"
    #include "lcd1602_driver.h"
    #include "infrared_driver.h"
    
    uchar InfraredGear = LowGear;//手动调节挡位,红外驱动文件中改变该值
    uchar Flag = 0;//自动0/手动1模式
    
    void main()
    {
        uint dis;
        ENA = 1;
        IN1 = 0;
        IN2 = 1;
        EA = 1;//开总中断
        EX0 = 1; //开外部中断0,接收红外信号
        while(1)
        {
            if(Flag == 0) //自动
            {
                dis = distance(); //超声波测距
                sr04_motor(dis); //根据距离调节挡位
                motor_run(InfraredGear);
                display0(dis);    //液晶显示
                delay_ms(100);    //延时,每100ms更新一次数据
            }
            else
            {
                motor_run(InfraredGear); //手动调节转速
                display1();     //液晶显示
                delay_ms(100); //延时,每100ms更新一次液晶内容
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    单片机-嵌入式毕设选题大全及项目分享:

    https://blog.csdn.net/m0_71572576/article/details/125409052


    5 最后

  • 相关阅读:
    设计一个高并发高性能系统需要考虑哪些方面
    基于 Redis 实现接口限流
    OpenCV1-VS2022+OpenCV环境配置
    【MySQL】(五)DML表数据操作——数据的插入、修改、删除
    软件配置 | Git下载、安装及卸载
    【JS】把Promise手写明白!
    Spring5源码3-BeanDefinition
    从零开始:开发直播商城APP的技术指南
    SpringBoot 读写分离(配Mysql5.7) 笔记
    MYSQL -- Binlog数据还原
  • 原文地址:https://blog.csdn.net/m0_71572576/article/details/125608127