基于51单片机的光电传感器测转速仿真

本文介绍了经典的8位单片机AT89C52及其特点,如内部存储、RAM、扩展能力、I/O引脚和定时器。同时,对比了74HC573透明锁存器和DS18B20温度传感器的特性,以及L9110双路驱动电机芯片的性能。文章还涉及了主程序中的相关控制和通信模块。

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

74HC573简介:
74HC573是一种集成电路,属于74系列高速CMOS逻辑系列。它是一个八位透明锁存器,常用于存储和锁定数据,以及在需要时将数据输出到其他器件。

74HC573具有8个数据输入端(D0-D7)和8个对应的数据输出端(Q0-Q7)。它还有一个使能输入端( OE ‾ \overline{\text{OE}} OE)和一个锁存控制输入端(LE),用于控制数据的读写和锁存操作。

当锁存控制输入端(LE)为高电平时,74HC573的数据输入端(D0-D7)的数据会被锁存,并存储在内部的锁存器中。此时,数据可以通过数据输出端(Q0-Q7)进行输出。

当使能输入端( OE ‾ \overline{\text{OE}} OE)为低电平时,输出端(Q0-Q7)将激活,并输出锁存器中存储的数据。而当使能输入端( OE ‾ \overline{\text{OE}} OE)为高电平时,输出端将处于高阻态,不会提供电平输出。

74HC573的主要特点包括:

快速响应时间:74HC573采用高速CMOS技术,具有快速的输入输出响应时间,适用于高速数据传输和信号处理。

透明锁存功能:74HC573具有透明锁存功能,在锁存控制输入端(LE)为高电平时,可以将输入数据直接通过并存入锁存器,实现数据的实时锁存。

高驱动能力:74HC573具有较高的输出驱动能力,可以驱动较长的总线线路以及多个负载。

宽工作电压范围:74HC573的工作电压范围通常为2V至6V,适用于多种逻辑电路的工作。

DS18B20特点:

  1. 单总线接口:DS18B20使用单总线接口进行通信,只需要一个引脚就可以连接多个传感器,简化了电路设计和连接。
  2. 数字输出:DS18B20以数字形式输出温度值,不需要额外的模数转换器。它使用12位的分辨率来表示温度值,可以实现高精度的温度测量。
  3. 高精度:DS18B20可以提供从-55°C到+125°C的温度测量范围,并具有±0.5°C的温度精度。因此,在许多应用中,它可以提供可靠和准确的温度测量结果。
  4. 多功能性:除了测量温度,DS18B20还可以执行其他功能,如温度报警功能。它可以设置上下限温度阈值,并在温度超过或低于这些阈值时触发报警。
  5. 低功耗:DS18B20采用低功耗设计,工作电流极低,只需要很少的能量来进行温度测量和通信。
  6. 耐用性:DS18B20具有良好的耐用性和可靠性,其封装材料和结构设计使其适用于各种环境条件下的应用。

L9110特点:
双路驱动:L9110可以同时驱动两个直流电机,每个驱动通道最大电流可达800mA。这使得它非常适用于需要控制多个电机的应用。

低电压工作:L9110可以在较低的电源电压下工作,通常在2.5V至12V之间。这使得它适用于电池供电的低电压应用,如机器人、小型车辆等。

高效能:该芯片采用了双H桥驱动技术,具有较高的效率和较低的功耗。它可以提供高达15kHz的PWM(脉冲宽度调制)频率,以实现电机速度的精确控制。

内置保护功能:L9110具有过温保护和短路保护功能,可有效保护芯片和电机免受过载和短路等异常情况的损害。

引脚简单:L9110只需要几个引脚就可以实现电机的驱动,包括两个输入引脚控制电机的正反转,以及两个输出引脚连接电机。

主程序:

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

sbit L9110H_IN1  = P1^0; //引脚定义
sbit L9110H_IN2  = P1^1;
sbit BUZZER      = P2^2;

sbit KEY_UP      = P3^5; //按键引脚定义
sbit KEY_DOWN    = P3^7;
sbit KEY_FORWORD = P3^6;
sbit KEY_BACK    = P3^4;
sbit KEY_START   = P1^6;
sbit KEY_STOP    = P1^7;

sbit LED_RED   = P2^1;
sbit LED_GREEN = P2^0;

bit ReadTempFlag; //定义读时间标志

int temp;             //温度读取
float temperature;    //实际温度
char dis0[16]; //定义显示区域临时存储数组

unsigned char levelValue = 5;      //占空比调整
bit startFlag = 0; //启停标志
bit motorFlag = 1; //正反转标志
bit readRateFlag = 0;  //读取速度标志

unsigned int rate;                  //速度值
unsigned long pulseNum;         //脉冲计数

void Timer0_Init(void); //函数声明
void KeyProcess(void); //按键处理

void main(void)
{
    L9110H_IN1 = 1;
    L9110H_IN2 = 1;

    Timer0_Init();
    EX1 = 1; //外部中断1开
    IT1 = 1; //边沿触发
    EA = 1;  //全局中断开

    LCD_Init();  //初始化液晶
    DelayMs(20); //延时有助于稳定
    LCD_Clear(); //清屏
    LCD_DispStr(0, 0, "Now:            ");
    LCD_DispOneChar(8, 0, 0xdf); //写入温度右上角点
    LCD_DispOneChar(9, 0, 'C');  //写入字符C
    LCD_DispStr(0, 1, "L:   Rate:   r/s");

    LED_RED = 1;
    LED_GREEN = 0;
    while (1) //主循环
    {

        if (ReadTempFlag == 1)
        {
            EA = 0;
            while(!DS18B20_GetTemp(&temp)); //读取温度
            temperature = (float)temp * 0.0625;                    //温度转换
            sprintf(dis0, "Now:%4.1f", temperature); //打印温度值
            LCD_DispStr(0, 0, dis0);
            LCD_DispOneChar(8, 0, 0xdf);        //写入温度右上角点
            LCD_DispOneChar(9, 0, 'C');         //写入字符C
            EA = 1;

            if (startFlag == 1)
            {
                LCD_DispStr(10, 0, " Start");
            }
            else
            {
                LCD_DispStr(10, 0, " Stop ");
            }
            
            sprintf(dis0, "L:%02d ", (int)levelValue); //打印等级
            LCD_DispStr(0, 1, dis0);

            if (temperature > 50) //高于报警温度
            {
                startFlag = 0; //电机停止
                BUZZER = 0; //打开蜂鸣器
            }
            else
            {
                BUZZER = 1; //关闭蜂鸣器
            }

            ReadTempFlag = 0;
        }
        
        if (readRateFlag == 1)
        {
            readRateFlag = 0;
            rate = pulseNum; 
            sprintf(dis0, "Rate:%03dr/s", rate); //打印速度
            LCD_DispStr(5, 1, dis0);
            EX1 = 1;
            pulseNum = 0;
        } 

        KeyProcess();
    }
}

void KeyProcess(void)
{
    if (!KEY_UP) //加速
    {
        DelayMs(20);
        if(!KEY_UP)
        {
            if (levelValue <= 9)
                levelValue++;
        }
        while(!KEY_UP);
    }

    if (!KEY_DOWN) //减速
    {
        DelayMs(20);
        if(!KEY_DOWN)
        {
            if (levelValue > 1)
                levelValue--;
        }
        while(!KEY_DOWN);
    }

    if (!KEY_FORWORD) //正转
    {
        DelayMs(20);
        if(!KEY_FORWORD)
        {
            if (startFlag == 1)
            {
                startFlag = 0;
                DelayMs(150);
                startFlag = 1;
            }
            motorFlag = 1;
            LED_RED = 1;
            LED_GREEN = 0;
        }
        while(!KEY_FORWORD);
    }

    if (!KEY_BACK) //反转
    {
        DelayMs(20);
        if(!KEY_BACK)
        {
            if (startFlag == 1)
            {
                startFlag = 0;
                DelayMs(150);
                startFlag = 1;
            }
            motorFlag = 0;
            LED_RED = 0;
            LED_GREEN = 1;
        }
        while(!KEY_BACK);
    }

    if (!KEY_START) //启动
    {
        DelayMs(20);
        if(!KEY_START)
        {
            startFlag = 1;
        }
        while(!KEY_START);
    }

    if (!KEY_STOP) //停止
    {
        DelayMs(20);
        if(!KEY_STOP)
        {
            startFlag = 0;
        }
        while(!KEY_STOP);
    }
}

void Timer0_Init(void)
{
    TMOD |= 0x01;                //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
	TL0 = 0x33;		//设置定时初始值
	TH0 = 0xFE;		//设置定时初始值 500us
    PT0 = 1; //设置高优先级
    EA = 1;  //总中断打开
    ET0 = 1; //定时器中断打开
    TR0 = 1; //定时器开关打开
}

void Timer0_isr(void) interrupt 1
{

    static unsigned char IN1Count = 0;
    static unsigned int numCount = 0;

	TL0 = 0x33;		//设置定时初始值
	TH0 = 0xFE;		//设置定时初始值 500us

    if (startFlag == 1)
    {
        IN1Count++;
        if (IN1Count < levelValue) //占空比调节
        {
            if (motorFlag == 1) //正转
            {
                L9110H_IN1 = 1;
                L9110H_IN2 = 0;
            }
            if (motorFlag == 0) //反转
            {
                L9110H_IN1 = 0;
                L9110H_IN2 = 1;
            }
        }
        else if ((IN1Count >= levelValue) && (IN1Count <= 11)) //关闭时间段
        {
            L9110H_IN1 = 1;
            L9110H_IN2 = 1; //关闭
        }
        else
        {
            IN1Count = 0; //一个周期结束
        }
    }
    else
    {
        L9110H_IN1 = 1;
        L9110H_IN2 = 1; //关闭
    }


    numCount++;

    if (numCount > 2000)
    {
        EX1 = 0;
        readRateFlag = 1;
        numCount = 0;
    }

    if (numCount % 1000 == 0)
    {
        ReadTempFlag = 1;
    }

}

/*------------------------------------------------
                外部中断程序
------------------------------------------------*/
void ISR_Key(void) interrupt 2
{
    pulseNum++;
}

设计文件:
链接:https://pan.baidu.com/s/1ddV_q1yAVGrjs-PhEeNtSA?pwd=mgkv

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值