51单片机蓝牙遥控车和遥控器(附Proteus仿真)

在学习完51单片机以后,想着做一个小项目,于是便有了这辆51遥控小车,话不多说,先看实物图

                                                                    遥控器

                                                                     遥控车 

楼主看了很多51小车的帖子,但一直没有找到心仪的,所以楼主便一边摸索一边组装了这辆小车,因为楼主没有焊接的地方,所以这辆车完全靠杜邦线和胶带连接,对新手很友好。

硬件部分

51单片机最小系统板*2
HC05兼容版*2
AMS1117降压模块*2
TBFNG6612电机驱动模块*1
MP2307降压模块*1
7.4V18650电池*1
PDD成品玩具车架*1

以及电池盒及干电池和杜邦线若干,和四个独立按键

软件部分

遥控器端

/*遥控器部分*/
#include <at89c51RC2.h>
#include "UART.H"

// 按键引脚定义
sbit KEY1 = P2^0;  // 前进按键
sbit KEY2 = P2^1;  // 后退按键
sbit KEY3 = P3^2;  // 左转按键
sbit KEY4 = P3^3;  // 右转按键

// 用于标记按键是否按下
bit key1_pressed = 0;
bit key2_pressed = 0;
bit key3_pressed = 0;
bit key4_pressed = 0;

// 记录前进状态(是否正在前进)
bit moving_forward = 0;
// 记录后退状态(是否正在后退)
bit moving_backward = 0;

void main()
{
    Uart1_Init();  // 初始化串口
    IT0 = 1;        // 设置 INT0 为下降沿触发
    IT1 = 1;        // 设置 INT1 为下降沿触发
    EX0 = 1;        // 启用外部中断 0
    EX1 = 1;        // 启用外部中断 1
    EA = 1;         // 启用总中断

    while(1)
    {
        // 处理前进和后退按键
        if (KEY1 == 0 && !key1_pressed) {  // 前进按键按下
            UART_SendChar('F');
            key1_pressed = 1;  // 标记为按下
            moving_forward = 1;  // 记录电机正在前进
            moving_backward = 0; // 停止后退
        } else if (KEY1 == 1 && key1_pressed) {  // 前进按键松开
            key1_pressed = 0;  // 重置标记
            if (!key2_pressed) {  // 只有当没有后退命令时才停止
                UART_SendChar('S');
                moving_forward = 0;  // 电机停止
            }
        }

        if (KEY2 == 0 && !key2_pressed) {  // 后退按键按下
            UART_SendChar('B');
            key2_pressed = 1;  // 标记为按下
            moving_forward = 0;  // 停止前进
            moving_backward = 1; // 记录电机正在后退
        } else if (KEY2 == 1 && key2_pressed) {  // 后退按键松开
            key2_pressed = 0;  // 重置标记
            if (!key1_pressed) {  // 只有当没有前进命令时才停止
                UART_SendChar('S');
                moving_backward = 0; // 电机停止
            }
        }
    }
}

void INT0_ISR(void) interrupt 0 {
    if (KEY3 == 0 && !key3_pressed) {  // 左转按键按下
        UART_SendChar('L');  // 启动转向
        key3_pressed = 1;    // 标记为按下
    }
    while (KEY3 == 0);   // 等待按键松开
    key3_pressed = 0;     // 松开时重置标记
    // 如果前进键或后退键还在按下,则继续前进或后退
    if (moving_forward) {
        UART_SendChar('F');  // 继续前进
    } else if (moving_backward) {
        UART_SendChar('B');  // 继续后退
    } else {
        UART_SendChar('S');  // 否则停止电机
    }
}

void INT1_ISR(void) interrupt 2 {
    if (KEY4 == 0 && !key4_pressed) {  // 右转按键按下
        UART_SendChar('R');  // 启动转向
        key4_pressed = 1;    // 标记为按下
    }
    while (KEY4 == 0);   // 等待按键松开
    key4_pressed = 0;     // 松开时重置标记
    // 如果前进键或后退键还在按下,则继续前进或后退
    if (moving_forward) {
        UART_SendChar('F');  // 继续前进
    } else if (moving_backward) {
        UART_SendChar('B');  // 继续后退
    } else {
        UART_SendChar('S');  // 否则停止电机
    }
}

遥控车端

/*遥控车*/
#include <at89c51RC2.h>
#include "Timer0.h"

// 电机控制引脚定义
sbit STBY = P2^4;  // 待机控制引脚
sbit PWMA = P2^5;  // 电机 A 的 PWM 控制引脚
sbit AIN1 = P2^6;  // 电机 A 的方向控制引脚 1
sbit AIN2 = P2^7;  // 电机 A 的方向控制引脚 2
sbit BIN1 = P1^0;  // 电机 B 的方向控制引脚 1
sbit BIN2 = P1^1;  // 电机 B 的方向控制引脚 2
sbit PWMB = P1^2;  // 电机 B 的 PWM 控制引脚



unsigned char motor1_active = 0;  // 电机1是否处于活动状态
void Uart1_Init(void)	//9600bps@11.0592MHz
{
	PCON &= 0x7F;		//波特率不倍速
	SCON = 0x50;		//8位数据,可变波特率
	AUXR &= 0xBF;		//定时器时钟12T模式
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x20;		//设置定时器模式
	TL1 = 0xFD;			//设置定时初始值
	TH1 = 0xFD;			//设置定时重载值
	ET1 = 0;			//禁止定时器中断
	TR1 = 1;			//定时器1开始计时
}

char UART_ReceiveChar(void) {
    while (!RI);      // 等待接收数据完成
    RI = 0;           // 清除接收标志
    return SBUF;      // 返回接收到的数据
}

// 电机控制函数
void MotorControl(char command) {
    // 先关闭所有电机
    AIN1 = 0;
    AIN2 = 0;
    BIN1 = 0;
    BIN2 = 0;
    PWMA = 0;
    PWMB = 0;
    STBY = 1;  // 保持 STBY 为高电平,使能电机驱动

    switch (command) {
        case 'F':  // 前进
            AIN1 = 1;
            AIN2 = 0;
            PWMA = 1;  // 设置 PWM 为高电平
            break;

        case 'B':  // 后退
            AIN1 = 0;
            AIN2 = 1;
            PWMA = 1;  // 设置 PWM 为高电平
            break;

        case 'L':  // 左转
            BIN1 = 1;
            BIN2 = 0;
            PWMB = 1;  // 设置 PWM 为高电平
            break;

        case 'R':  // 右转
            BIN1 = 0;
            BIN2 = 1;
            PWMB = 1;  // 设置 PWM 为高电平
            break;

        case 'S':  // 停止
            AIN1 = 0;
            AIN2 = 0;
            BIN1 = 0;
            BIN2 = 0;
            PWMA = 0;
            PWMB = 0;
            break;

        default:
            // 无效命令,不做任何操作
            break;
    }
}

void main()
{
	char command;
  Uart1_Init();  // 初始化串口
	while(1)
	{
	   command = UART_ReceiveChar();  // 接收来自单片机A的指令
     MotorControl(command);  // 根据接收到的指令控制电机
	}
}	



详细程序部分请见:shanzhonglong/51-bluetooth-remote-control-car-: 51单片机遥控小车,适合像我一样的初学者

Proteus仿真

大家可参考仿真进行实物连接

目前存在的问题

因为楼主买的是成品车架,前桥和后驱都是各一个成品130玩具电机 ,并且因为51单片机的单线程,小车没法同时执行前进和转向命令,只能调用中断来执行小幅度的转向 ,所以实际跑起来很怪,在这里求助各位大佬有没有更好的解决方案  。

因为是第一次分享文章,有不对的地方还请多多见谅,最后希望大家共同进步。                       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值