51单片机 红外控制电机转速

所有项目均采用模块化编程,视频学习参考b站江协科技

main.c中

#include <REGX52.H>
#include "Delay.h"
#include "Key.h"
#include "Nixie.h"
#include "Motor.h"
#include "IR.h"

unsigned char Command,Speed;

void main()
{
    Motor_Init();
    IR_Init();
    while(1)
    {
        if(IR_GetDataFlag())    //如果收到数据帧
        {
            Command=IR_GetCommand();        //获取遥控器命令码
            
            if(Command==IR_0){Speed=0;}        //根据遥控器命令码设置速度
            if(Command==IR_1){Speed=1;}
            if(Command==IR_2){Speed=2;}
            if(Command==IR_3){Speed=3;}
            
            if(Speed==0){Motor_SetSpeed(0);}    //速度输出
            if(Speed==1){Motor_SetSpeed(50);}
            if(Speed==2){Motor_SetSpeed(75);}
            if(Speed==3){Motor_SetSpeed(100);}
        }
        Nixie(1,Speed);                        //数码管显示速度
    }
}
 

delay.c中

void Delay(unsigned int xms)
{
    unsigned char i, j;
    while(xms--)
    {
        i = 2;
        j = 239;
        do
        {
            while (--j);
        } while (--i);
    }
}

delay.h中

#ifndef __DELAY_H__
#define __DELAY_H__

void Delay(unsigned int xms);

#endif

int0.c中

#include <REGX52.H>

/**
  * @brief  外部中断0初始化
  * @param  无
  * @retval 无
  */
void Int0_Init(void)
{
    IT0=1;
    IE0=0;
    EX0=1;
    EA=1;
    PX0=1;
}

/*外部中断0中断函数模板
void Int0_Routine(void) interrupt 0
{
    
}
*/
int0.h中

#ifndef __INT0_H__
#define __INT0_H__

void Int0_Init(void);

#endif

IR.c中

#include <REGX52.H>
#include "Timer0.h"
#include "Int0.h"

unsigned int IR_Time;
unsigned char IR_State;

unsigned char IR_Data[4];
unsigned char IR_pData;

unsigned char IR_DataFlag;
unsigned char IR_RepeatFlag;
unsigned char IR_Address;
unsigned char IR_Command;

/**
  * @brief  红外遥控初始化
  * @param  无
  * @retval 无
  */
void IR_Init(void)
{
    Timer0_Init();
    Int0_Init();
}

/**
  * @brief  红外遥控获取收到数据帧标志位
  * @param  无
  * @retval 是否收到数据帧,1为收到,0为未收到
  */
unsigned char IR_GetDataFlag(void)
{
    if(IR_DataFlag)
    {
        IR_DataFlag=0;
        return 1;
    }
    return 0;
}

/**
  * @brief  红外遥控获取收到连发帧标志位
  * @param  无
  * @retval 是否收到连发帧,1为收到,0为未收到
  */
unsigned char IR_GetRepeatFlag(void)
{
    if(IR_RepeatFlag)
    {
        IR_RepeatFlag=0;
        return 1;
    }
    return 0;
}

/**
  * @brief  红外遥控获取收到的地址数据
  * @param  无
  * @retval 收到的地址数据
  */
unsigned char IR_GetAddress(void)
{
    return IR_Address;
}

/**
  * @brief  红外遥控获取收到的命令数据
  * @param  无
  * @retval 收到的命令数据
  */
unsigned char IR_GetCommand(void)
{
    return IR_Command;
}

//外部中断0中断函数,下降沿触发执行
void Int0_Routine(void) interrupt 0
{
    if(IR_State==0)                //状态0,空闲状态
    {
        Timer0_SetCounter(0);    //定时计数器清0
        Timer0_Run(1);            //定时器启动
        IR_State=1;                //置状态为1
    }
    else if(IR_State==1)        //状态1,等待Start信号或Repeat信号
    {
        IR_Time=Timer0_GetCounter();    //获取上一次中断到此次中断的时间
        Timer0_SetCounter(0);    //定时计数器清0
        //如果计时为13.5ms,则接收到了Start信号(判定值在12MHz晶振下为13500,在11.0592MHz晶振下为12442)
        if(IR_Time>13500-500 && IR_Time<13500+500)
        {
            IR_State=2;            //置状态为2
        }
        //如果计时为11.25ms,则接收到了Repeat信号(判定值在12MHz晶振下为11250,在11.0592MHz晶振下为10368)
        else if(IR_Time>11250-500 && IR_Time<11250+500)
        {
            IR_RepeatFlag=1;    //置收到连发帧标志位为1
            Timer0_Run(0);        //定时器停止
            IR_State=0;            //置状态为0
        }
        else                    //接收出错
        {
            IR_State=1;            //置状态为1
        }
    }
    else if(IR_State==2)        //状态2,接收数据
    {
        IR_Time=Timer0_GetCounter();    //获取上一次中断到此次中断的时间
        Timer0_SetCounter(0);    //定时计数器清0
        //如果计时为1120us,则接收到了数据0(判定值在12MHz晶振下为1120,在11.0592MHz晶振下为1032)
        if(IR_Time>1120-500 && IR_Time<1120+500)
        {
            IR_Data[IR_pData/8]&=~(0x01<<(IR_pData%8));    //数据对应位清0
            IR_pData++;            //数据位置指针自增
        }
        //如果计时为2250us,则接收到了数据1(判定值在12MHz晶振下为2250,在11.0592MHz晶振下为2074)
        else if(IR_Time>2250-500 && IR_Time<2250+500)
        {
            IR_Data[IR_pData/8]|=(0x01<<(IR_pData%8));    //数据对应位置1
            IR_pData++;            //数据位置指针自增
        }
        else                    //接收出错
        {
            IR_pData=0;            //数据位置指针清0
            IR_State=1;            //置状态为1
        }
        if(IR_pData>=32)        //如果接收到了32位数据
        {
            IR_pData=0;            //数据位置指针清0
            if((IR_Data[0]==~IR_Data[1]) && (IR_Data[2]==~IR_Data[3]))    //数据验证
            {
                IR_Address=IR_Data[0];    //转存数据
                IR_Command=IR_Data[2];
                IR_DataFlag=1;    //置收到连发帧标志位为1
            }
            Timer0_Run(0);        //定时器停止
            IR_State=0;            //置状态为0
        }
    }
}

IR.h中

#ifndef __IR_H__
#define __IR_H__

#define IR_POWER        0x45
#define IR_MODE            0x46
#define IR_MUTE            0x47
#define IR_START_STOP    0x44
#define IR_PREVIOUS        0x40
#define IR_NEXT            0x43
#define IR_EQ            0x07
#define IR_VOL_MINUS    0x15
#define IR_VOL_ADD        0x09
#define IR_0            0x16
#define IR_RPT            0x19
#define IR_USD            0x0D
#define IR_1            0x0C
#define IR_2            0x18
#define IR_3            0x5E
#define IR_4            0x08
#define IR_5            0x1C
#define IR_6            0x5A
#define IR_7            0x42
#define IR_8            0x52
#define IR_9            0x4A

void IR_Init(void);
unsigned char IR_GetDataFlag(void);
unsigned char IR_GetRepeatFlag(void);
unsigned char IR_GetAddress(void);
unsigned char IR_GetCommand(void);

#endif

Key.c中

#include <REGX52.H>
#include "Delay.h"

/**
  * @brief  获取独立按键键码
  * @param  无
  * @retval 按下按键的键码,范围:0~4,无按键按下时返回值为0
  */
unsigned char Key()
{
    unsigned char KeyNumber=0;
    
    if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
    if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
    if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
    if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
    
    return KeyNumber;
}

Key.h中

#ifndef __KEY_H__
#define __KEY_H__

unsigned char Key();

#endif
 

Motor.c中

#include <REGX52.H>
#include "Timer1.h"

//引脚定义
sbit Motor=P1^0;

unsigned char Counter,Compare;

/**
  * @brief  电机初始化
  * @param  无
  * @retval 无
  */
void Motor_Init(void)
{
    Timer1_Init();
}

/**
  * @brief  电机设置速度
  * @param  Speed 要设置的速度,范围0~100
  * @retval 无
  */
void Motor_SetSpeed(unsigned char Speed)
{
    Compare=Speed;
}

//定时器1中断函数
void Timer1_Routine() interrupt 3
{
    TL1 = 0x9C;        //设置定时初值
    TH1 = 0xFF;        //设置定时初值
    Counter++;
    Counter%=100;    //计数值变化范围限制在0~99
    if(Counter<Compare)    //计数值小于比较值
    {
        Motor=1;        //输出1
    }
    else                //计数值大于比较值
    {
        Motor=0;        //输出0
    }
}

Motor.h中

#ifndef __MOTOR_H__
#define __MOTOR_H__

void Motor_Init(void);
void Motor_SetSpeed(unsigned char Speed);

#endif

Nixie.c中

#include <REGX52.H>
#include "Delay.h"

unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

void Nixie(unsigned char Location,Number)
{
    switch(Location)
    {
        case 1:P2_4=1;P2_3=1;P2_2=1;break;
        case 2:P2_4=1;P2_3=1;P2_2=0;break;
        case 3:P2_4=1;P2_3=0;P2_2=1;break;
        case 4:P2_4=1;P2_3=0;P2_2=0;break;
        case 5:P2_4=0;P2_3=1;P2_2=1;break;
        case 6:P2_4=0;P2_3=1;P2_2=0;break;
        case 7:P2_4=0;P2_3=0;P2_2=1;break;
        case 8:P2_4=0;P2_3=0;P2_2=0;break;
    }
    P0=NixieTable[Number];
    Delay(1);
    P0=0x00;
}
Nixie.h中

#ifndef __NIXIE_H__
#define __NIXIE_H__

void Nixie(unsigned char Location,Number);

#endif

Timer0.c中

#include <REGX52.H>

/**
  * @brief  定时器0初始化
  * @param  无
  * @retval 无
  */
void Timer0_Init(void)
{
    TMOD &= 0xF0;        //设置定时器模式
    TMOD |= 0x01;        //设置定时器模式
    TL0 = 0;        //设置定时初值
    TH0 = 0;        //设置定时初值
    TF0 = 0;        //清除TF0标志
    TR0 = 0;        //定时器0不计时
}

/**
  * @brief  定时器0设置计数器值
  * @param  Value,要设置的计数器值,范围:0~65535
  * @retval 无
  */
void Timer0_SetCounter(unsigned int Value)
{
    TH0=Value/256;
    TL0=Value%256;
}

/**
  * @brief  定时器0获取计数器值
  * @param  无
  * @retval 计数器值,范围:0~65535
  */
unsigned int Timer0_GetCounter(void)
{
    return (TH0<<8)|TL0;
}

/**
  * @brief  定时器0启动停止控制
  * @param  Flag 启动停止标志,1为启动,0为停止
  * @retval 无
  */
void Timer0_Run(unsigned char Flag)
{
    TR0=Flag;
}


Timer0.h中

#ifndef __TIMER0_H__
#define __TIMER0_H__

void Timer0_Init(void);
void Timer0_SetCounter(unsigned int Value);
unsigned int Timer0_GetCounter(void);
void Timer0_Run(unsigned char Flag);

#endif

Timer1.c中

#include <REGX52.H>

/**
  * @brief  定时器1初始化,100us@12.000MHz
  * @param  无
  * @retval 无
  */
void Timer1_Init(void)
{
    TMOD &= 0x0F;        //设置定时器模式
    TMOD |= 0x10;        //设置定时器模式
    TL1 = 0x9C;        //设置定时初值
    TH1 = 0xFF;        //设置定时初值
    TF1 = 0;        //清除TF1标志
    TR1 = 1;        //定时器1开始计时
    ET1=1;
    EA=1;
    PT1=0;
}

/*定时器中断函数模板
void Timer1_Routine() interrupt 3
{
    static unsigned int T1Count;
    TL1 = 0x9C;        //设置定时初值
    TH1 = 0xFF;        //设置定时初值
    T1Count++;
    if(T1Count>=1000)
    {
        T1Count=0;
        
    }
}
*/

Timer1.h中

#ifndef __TIMER1_H__
#define __TIMER1_H__

void Timer1_Init(void);

#endif

  • 32
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值