基于51单片机蓝牙直流电机控制(IR2104S驱动H桥)

主要目标:
(1)用51系列单片机作为控制器;
(2)采用由四个MOS管组成的H桥电机驱动电路,并由IR2104S来驱动H桥;
(3)可实现电机正、反转,启停,加、减速;
(4)可采用蓝牙、按键进行效果切换,并加有LED灯(左、右方向灯)及蜂鸣器报警电路(转向时报警);
(5)采用5V直流稳压电源;

主要内容:
1、最小系统设计;
2、综合布局设计;
3、蓝牙控制C程序设计;
4、按键控制C程序设计;
5、方向灯及蜂鸣器C程序设计;
6、仿真观察实验效果;
7、电路焊接与调试;

要实现所要求的功能首先需要规划硬件模块,所需的元件为STC89C52RC芯片,12MHZ晶振,直流单机,IR2104S,MOS管IRF740,HC-05蓝牙模块,电容电阻导线若干,红、黄LED若干、按键若干、USB-TTL模块,三极管8050及8550以及蜂鸣器等一些其他模块。

首先先要实现最小系统的正常运行,单片机最小系统由单片机、晶振电路、复位电路、电源模块构成,硬件电路图会在下面给出的。实现了最小系统的运行后要开始考虑如何实现电机的驱动及状态控制, H桥由四个MOS管组成,全桥驱动可以由实现电机正反转,通过改变MOS开断的时间即通过给PWM波的方式来实现电机调速,可以选用IRF2104S来驱动H桥,需要通过蓝牙,按键切换可以判断出在编程的时候需要用到中断的知识,按下按键打开中断,来执行中断服务程序,具体可以通过代码的编写来实现,下面会对其有详细的叙述;在此次设计中我设计的功能:可实现电机调速,蓝牙控制,LED方向灯显示,蜂鸣器转向报警,在硬件焊接方面需要注意P0口要加上拉电阻、电解电容正负极不能接反等,焊接完成后需要进行电路的测试。

硬件电路图:
在这里插入图片描述

1.IRS2104S驱动电路:

在这里插入图片描述
图1-H桥
图一以四个IR740组成的H桥为基础,通过两个IR2104S来驱动,下面的图二为IR2104S数据手册中的半桥驱动电路图(左边桥和右半桥是对称的,以分析左半桥为例),图3为IR2104S内部电路原理图:
①VCC为芯片的电源输入,手册中给出的工作电压为10~20V。
② IN和#SD作为输入控制,可共同控制电机的转动状态(转向、转速和是否转动)。
③ VB和VS主要用于形成自举电路。
④ HO和LO接到MOS管栅极,分别用于控制上桥臂和下桥臂MOS的导通与截止。
COM脚直接接地即可。
在这里插入图片描述
图2-IR2104S半桥驱动

在这里插入图片描述
图3-IR2104S内部电路原理图

通过IN口给PWM波,#SD给高低电平。VCC通过一个二极管连接到VB,给VB口提供12V的电压,VB通过一个电容连接到VS,VS接到上下两个NMOS的中间,这部分是一个自举电路,因为NMOS导通需要VGS > VGSth ,由于NMOS导通后电阻很小,相当于一条导线,源极电压等于漏极电压,要确保VGS > VGSth ,所以这里需要一个自举电路来提高栅级的对地电压,并且自举电路还可以降低MOS管的导通电阻,从而减少发热损耗,还需要利用二极管的单向导电性来防止电流回流毁坏电路。下面图四为我的全桥电路图
在这里插入图片描述
因为PWM输出使上下两个NMOS轮流导通,(HO,LO)分别经历(0,0),(1,0),(0,1)三个过程,即自举电容电容充电,自举电容放电和下半桥栅级放电和上半桥栅级放电(上一阶段加在上面的电压),我在HO和LO与NMOS之间的限流电阻上并联一个二极管,加快放电速度。在输入电压出接了一个电容到地,是用来起滤波作用的。同时,PWM给不同的占空比可以进行电机调速。
在这里插入图片描述

2.HC-05蓝牙模块
HC-05蓝牙模块通过串口与51连接,可实现人机交互,我这里只将蓝牙当做接收端,通过手机端的蓝牙调试器APP向51发送控制信息(两者之间通信方式为串口通信,波特率设置为4800)。
在APP中设立了五个按键,即LEFT, RIGHT, UP, DOWN以及OK,分别用作左转,右转,加速,减速和停止,按键按下去后会通过串口发送对应的键值,HEX显示分别为0x48, 0x4A, 0x47, 0x4B, 0x49, 51单片机的SBUF寄存器存储接受到的值,然后我对接受的到信息进行处理。

3.独立按键模块
这一块我设置了三个独立按键,接到P0.0, P0.1, P0.2,同时这三个IO口接了上拉电阻起到保护引脚的作用,这三个按键分别起到加速,减速,停止的作用。
做了软件消抖(检测到按下口经过延时后再检测是否按下),提高准确性。

程序如下:

main.c文件:

#include "reg52.h"
#include "light.h"
#include "motor.h"
#include "blue.h"
#include "key.h"
extern  uchar  Turn_flag;
void main(void)
{
    PWM_Init();
    UART_Init();
    while(1)
    {
        Key_Ctrl(Key_Scan());
        LED_Display(Turn_flag);
    }
}

blue.c文件:

#include "reg52.h"
#include "blue.h"
#include "string.h"
#define  UART_RX_STA = 0;
uchar    UART_RX_BUF[UART_MAX_RECV_LEN];
uchar    Turn_flag = 0;
extern   uchar  comp;
sbit  L = P1 ^ 3;
sbit  R = P1 ^ 4;
sbit  LED_Stop = P1 ^ 0; //红色灯--刹车灯
sbit  BEEP  = P2^7;     //蜂鸣器
//定时器1初始化
void  UART_Init(void)
{
    SCON = 0x50;
    TMOD = 0x20;
    PCON = 0x80;
    TH1  = 0xF3;      //设置波特率为4800
    TL1  = 0xF3;
    ES   = 1;
    EA   = 1;
    TR1  = 1;
    L = 0;
R = 0;
LED_Stop =  0; //红色灯--刹车灯
BEEP  = 1;  
}
//串口发送数据
void UART_SendData(uchar *BUFF)
{
    uchar i;
    for(i = 0; i < strlen(BUFF) ; i++)
    {
        SBUF = *(BUFF + i);
        while(!TI);
        TI = 0;
    }
}
//串口中断函数,蓝牙电机控制
void UART_ReceiveData() interrupt 4
{
    ES = 0;		//暂时关闭串口中断
    RI = 0;
    UART_RX_BUF[0] = SBUF;   //把收到的信息从SBUF放到UART_RX_BUF[]中
    switch(UART_RX_BUF[0])
    {
    case 0x47:
        if(comp != 80)  comp += 10;
        else  comp = 80;
        break;
    case 0x48:
        L = 0;
        R = 1;
        Turn_flag = 1;
        break;
    case 0x49:
        comp = 0;
        Turn_flag = 0;
        break;
    case 0x4A:
        L = 1;
        R = 0;
        Turn_flag = 2;
        break;
    case 0x4B:
        if(comp != 0)   comp -= 10;
        else  comp = 0;
        Turn_flag = 3;
        break;
    default:
        break;
    }
    ES = 1;		//重新开启串口中断
    SBUF = UART_RX_BUF[0];
    while(!TI);
    TI = 0;
}

blue.h文件:

#ifndef    _BLUE_H
#define    _BLUE_H
#define    UART_MAX_RECV_LEN  40
#define    uchar   unsigned char
#define    uint	   unsigned int
void  UART_Init(void);
void  UART_SendData(uchar *BUFF);
#endif

motor.c文件:

#include "reg52.h" 
#include "motor.h" 
#define uchar unsigned char 
#define uint  unsigned int 
 
sbit  PWM1 = P2 ^ 6;    //PWM输出IO口 
sbit  PWM2 = P2 ^ 4;  
uchar cont = 0;          //定时器0中断计数值 
uchar comp ;      //定时器0的比较值 
//定时器0初始化 
void  PWM_Init(void) 
{ 
    TMOD = 0x01; 
    TH0  = (65536 - 1000) / 256; 
    TL0  = (65536 - 1000) % 256; 
    EA   = 1; 
    TR0  = 1; 
    ET0  = 1; 
    PWM1  = 0; 
    PWM2  = 0; 
} 

//定时器0中断函数, PWM占空比设置 
void  TIMER0_INT(void) interrupt 1 
{ 
    TH0  = (65536 - 1000) / 256; 
    TL0  = (65536 - 1000) % 256;  //1us 
    cont++; 
    if(cont <= comp) 
    { 
        PWM1 = 1; 
        PWM2 = 1; 
    } 
    else  if(cont <= 100)       //10khz 
    { 
        PWM1 = 0; 
        PWM2 = 0; 
    } 
    else cont = 0; 
} 

motor.h文件:

#ifndef  _MOTOR_H
#define  _MOTOR_H
void  PWM_Init(void);
#endif

light.c文件:

#include "reg52.h"
#include "light.h"
sbit  LED_Stop = P1 ^ 0; //红色灯--刹车灯
sbit  LED_L = P1 ^ 1;   //黄色灯--左边
sbit  LED_R = P1 ^ 2;   //黄色灯--右边
sbit  BEEP  = P2 ^ 7;   //蜂鸣器
sbit  Beep_ST = P1 ^ 5;

//i = 1 ,延时1us
void  delay_ms(uint i)
{
    while(i--);
}

void  LED_Display(uchar Turn_flag)
{
    if(Turn_flag == 0)
{
LED_Stop = 0;
        Beep_ST = 0;
        LED_L = 0;
        LED_R = 0;
        BEEP  = 0;
    }
    else if(Turn_flag == 1)
{
LED_Stop = 0;
        Beep_ST = 1;
        LED_L = 1;
        BEEP  = 1;
        delay_ms(5000);
        LED_L = 0;
        BEEP  = 0;
        delay_ms(5000);
    }
    else if(Turn_flag == 2)
{
LED_Stop = 0;
        Beep_ST = 1;
        LED_R = 1;
        BEEP  = 1;
        delay_ms(5000);
        LED_R = 0;
        BEEP  = 0;
        delay_ms(5000);
    }
    else if(Turn_flag == 3)
    {
        LED_Stop = 1;
       BEEP = 1;
    }
}

light.h文件:

#ifndef   _LIGHT_H
#define   _LIGHT_H
#define  uchar   unsigned char
#define  uint	   unsigned int
void  LED_Display(uchar );
void  delay_ms(uint );
#endif

key.c文件:

 #include "key.h"
#include "reg52.h"
#include "motor.h"
sbit  K1 = P0 ^ 0;
sbit  K2 = P0 ^ 1;
sbit  K3 = P0 ^ 2;
#define uchar unsigned char
#define uint  unsigned int
extern uchar comp ;
extern uchar Turn_flag;

void delay(uint i)
{
    while(i--);
}

u8  Key_Scan(void)
{
    if(K1 == 0)
    {
        delay(500);
        if(K1 == 0)  return 1;
        else         return 0;
    }
    else if(K2 == 0)
    {
        delay(500);
        if(K2 == 0)  return 2;
        else         return 0;
    }
    else if(K3 == 0)
    {
        delay(500);
        if(K3 == 0)  return 3;
        else         return 0;
    }
    else           return 0;
}

void   Key_Ctrl(u8 i)
{
    switch (i)
    {
    case  1:
        if(comp != 80)  comp += 10;
        else  comp = 80;
        break;
    case  2:
        if(comp != 0)   comp -= 10;
        else  comp = 0;
        Turn_flag = 3;
        break;
    case  3:
        comp = 0;
        break;
    default:
        break;
    }
}

key.h文件:

#ifndef  _KEY_H
#define  _KEY_H
#define  u8  unsigned char
#define  u16 unsigned int

u8     Key_Scan(void);
void   Key_Ctrl(u8 );
#endif

附焊接图:在这里插入图片描述

版权声明:本文为CSDN博主「睡不够呀」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zstu_zhoubenshan/article/details/122591977

主要目标:
(1)用51系列单片机作为控制器;
(2)采用由四个MOS管组成的H桥电机驱动电路,并由IR2104S来驱动H桥;
(3)可实现电机正、反转,启停,加、减速;
(4)可采用蓝牙、按键进行效果切换,并加有LED灯(左、右方向灯)及蜂鸣器报警电路(转向时报警);
(5)采用5V直流稳压电源;

主要内容:
1、最小系统设计;
2、综合布局设计;
3、蓝牙控制C程序设计;
4、按键控制C程序设计;
5、方向灯及蜂鸣器C程序设计;
6、仿真观察实验效果;
7、电路焊接与调试;

要实现所要求的功能首先需要规划硬件模块,所需的元件为STC89C52RC芯片,12MHZ晶振,直流单机,IR2104S,MOS管IRF740,HC-05蓝牙模块,电容电阻导线若干,红、黄LED若干、按键若干、USB-TTL模块,三极管8050及8550以及蜂鸣器等一些其他模块。

首先先要实现最小系统的正常运行,单片机最小系统由单片机、晶振电路、复位电路、电源模块构成,硬件电路图会在下面给出的。实现了最小系统的运行后要开始考虑如何实现电机的驱动及状态控制, H桥由四个MOS管组成,全桥驱动可以由实现电机正反转,通过改变MOS开断的时间即通过给PWM波的方式来实现电机调速,可以选用IRF2104S来驱动H桥,需要通过蓝牙,按键切换可以判断出在编程的时候需要用到中断的知识,按下按键打开中断,来执行中断服务程序,具体可以通过代码的编写来实现,下面会对其有详细的叙述;在此次设计中我设计的功能:可实现电机调速,蓝牙控制,LED方向灯显示,蜂鸣器转向报警,在硬件焊接方面需要注意P0口要加上拉电阻、电解电容正负极不能接反等,焊接完成后需要进行电路的测试。

硬件电路图:
在这里插入图片描述

1.IRS2104S驱动电路:

在这里插入图片描述
图1-H桥
图一以四个IR740组成的H桥为基础,通过两个IR2104S来驱动,下面的图二为IR2104S数据手册中的半桥驱动电路图(左边桥和右半桥是对称的,以分析左半桥为例),图3为IR2104S内部电路原理图:
①VCC为芯片的电源输入,手册中给出的工作电压为10~20V。
② IN和#SD作为输入控制,可共同控制电机的转动状态(转向、转速和是否转动)。
③ VB和VS主要用于形成自举电路。
④ HO和LO接到MOS管栅极,分别用于控制上桥臂和下桥臂MOS的导通与截止。
COM脚直接接地即可。
在这里插入图片描述
图2-IR2104S半桥驱动

在这里插入图片描述
图3-IR2104S内部电路原理图

通过IN口给PWM波,#SD给高低电平。VCC通过一个二极管连接到VB,给VB口提供12V的电压,VB通过一个电容连接到VS,VS接到上下两个NMOS的中间,这部分是一个自举电路,因为NMOS导通需要VGS > VGSth ,由于NMOS导通后电阻很小,相当于一条导线,源极电压等于漏极电压,要确保VGS > VGSth ,所以这里需要一个自举电路来提高栅级的对地电压,并且自举电路还可以降低MOS管的导通电阻,从而减少发热损耗,还需要利用二极管的单向导电性来防止电流回流毁坏电路。下面图四为我的全桥电路图
在这里插入图片描述
因为PWM输出使上下两个NMOS轮流导通,(HO,LO)分别经历(0,0),(1,0),(0,1)三个过程,即自举电容电容充电,自举电容放电和下半桥栅级放电和上半桥栅级放电(上一阶段加在上面的电压),我在HO和LO与NMOS之间的限流电阻上并联一个二极管,加快放电速度。在输入电压出接了一个电容到地,是用来起滤波作用的。同时,PWM给不同的占空比可以进行电机调速。
在这里插入图片描述

2.HC-05蓝牙模块
HC-05蓝牙模块通过串口与51连接,可实现人机交互,我这里只将蓝牙当做接收端,通过手机端的蓝牙调试器APP向51发送控制信息(两者之间通信方式为串口通信,波特率设置为4800)。
在APP中设立了五个按键,即LEFT, RIGHT, UP, DOWN以及OK,分别用作左转,右转,加速,减速和停止,按键按下去后会通过串口发送对应的键值,HEX显示分别为0x48, 0x4A, 0x47, 0x4B, 0x49, 51单片机的SBUF寄存器存储接受到的值,然后我对接受的到信息进行处理。

3.独立按键模块
这一块我设置了三个独立按键,接到P0.0, P0.1, P0.2,同时这三个IO口接了上拉电阻起到保护引脚的作用,这三个按键分别起到加速,减速,停止的作用。
做了软件消抖(检测到按下口经过延时后再检测是否按下),提高准确性。

程序如下:

main.c文件:

#include "reg52.h"
#include "light.h"
#include "motor.h"
#include "blue.h"
#include "key.h"
extern  uchar  Turn_flag;
void main(void)
{
    PWM_Init();
    UART_Init();
    while(1)
    {
        Key_Ctrl(Key_Scan());
        LED_Display(Turn_flag);
    }
}

blue.c文件:

#include "reg52.h"
#include "blue.h"
#include "string.h"
#define  UART_RX_STA = 0;
uchar    UART_RX_BUF[UART_MAX_RECV_LEN];
uchar    Turn_flag = 0;
extern   uchar  comp;
sbit  L = P1 ^ 3;
sbit  R = P1 ^ 4;
sbit  LED_Stop = P1 ^ 0; //红色灯--刹车灯
sbit  BEEP  = P2^7;     //蜂鸣器
//定时器1初始化
void  UART_Init(void)
{
    SCON = 0x50;
    TMOD = 0x20;
    PCON = 0x80;
    TH1  = 0xF3;      //设置波特率为4800
    TL1  = 0xF3;
    ES   = 1;
    EA   = 1;
    TR1  = 1;
    L = 0;
R = 0;
LED_Stop =  0; //红色灯--刹车灯
BEEP  = 1;  
}
//串口发送数据
void UART_SendData(uchar *BUFF)
{
    uchar i;
    for(i = 0; i < strlen(BUFF) ; i++)
    {
        SBUF = *(BUFF + i);
        while(!TI);
        TI = 0;
    }
}
//串口中断函数,蓝牙电机控制
void UART_ReceiveData() interrupt 4
{
    ES = 0;		//暂时关闭串口中断
    RI = 0;
    UART_RX_BUF[0] = SBUF;   //把收到的信息从SBUF放到UART_RX_BUF[]中
    switch(UART_RX_BUF[0])
    {
    case 0x47:
        if(comp != 80)  comp += 10;
        else  comp = 80;
        break;
    case 0x48:
        L = 0;
        R = 1;
        Turn_flag = 1;
        break;
    case 0x49:
        comp = 0;
        Turn_flag = 0;
        break;
    case 0x4A:
        L = 1;
        R = 0;
        Turn_flag = 2;
        break;
    case 0x4B:
        if(comp != 0)   comp -= 10;
        else  comp = 0;
        Turn_flag = 3;
        break;
    default:
        break;
    }
    ES = 1;		//重新开启串口中断
    SBUF = UART_RX_BUF[0];
    while(!TI);
    TI = 0;
}

blue.h文件:

#ifndef    _BLUE_H
#define    _BLUE_H
#define    UART_MAX_RECV_LEN  40
#define    uchar   unsigned char
#define    uint	   unsigned int
void  UART_Init(void);
void  UART_SendData(uchar *BUFF);
#endif

motor.c文件:

#include "reg52.h" 
#include "motor.h" 
#define uchar unsigned char 
#define uint  unsigned int 
 
sbit  PWM1 = P2 ^ 6;    //PWM输出IO口 
sbit  PWM2 = P2 ^ 4;  
uchar cont = 0;          //定时器0中断计数值 
uchar comp ;      //定时器0的比较值 
//定时器0初始化 
void  PWM_Init(void) 
{ 
    TMOD = 0x01; 
    TH0  = (65536 - 1000) / 256; 
    TL0  = (65536 - 1000) % 256; 
    EA   = 1; 
    TR0  = 1; 
    ET0  = 1; 
    PWM1  = 0; 
    PWM2  = 0; 
} 

//定时器0中断函数, PWM占空比设置 
void  TIMER0_INT(void) interrupt 1 
{ 
    TH0  = (65536 - 1000) / 256; 
    TL0  = (65536 - 1000) % 256;  //1us 
    cont++; 
    if(cont <= comp) 
    { 
        PWM1 = 1; 
        PWM2 = 1; 
    } 
    else  if(cont <= 100)       //10khz 
    { 
        PWM1 = 0; 
        PWM2 = 0; 
    } 
    else cont = 0; 
} 

motor.h文件:

#ifndef  _MOTOR_H
#define  _MOTOR_H
void  PWM_Init(void);
#endif

light.c文件:

#include "reg52.h"
#include "light.h"
sbit  LED_Stop = P1 ^ 0; //红色灯--刹车灯
sbit  LED_L = P1 ^ 1;   //黄色灯--左边
sbit  LED_R = P1 ^ 2;   //黄色灯--右边
sbit  BEEP  = P2 ^ 7;   //蜂鸣器
sbit  Beep_ST = P1 ^ 5;

//i = 1 ,延时1us
void  delay_ms(uint i)
{
    while(i--);
}

void  LED_Display(uchar Turn_flag)
{
    if(Turn_flag == 0)
{
LED_Stop = 0;
        Beep_ST = 0;
        LED_L = 0;
        LED_R = 0;
        BEEP  = 0;
    }
    else if(Turn_flag == 1)
{
LED_Stop = 0;
        Beep_ST = 1;
        LED_L = 1;
        BEEP  = 1;
        delay_ms(5000);
        LED_L = 0;
        BEEP  = 0;
        delay_ms(5000);
    }
    else if(Turn_flag == 2)
{
LED_Stop = 0;
        Beep_ST = 1;
        LED_R = 1;
        BEEP  = 1;
        delay_ms(5000);
        LED_R = 0;
        BEEP  = 0;
        delay_ms(5000);
    }
    else if(Turn_flag == 3)
    {
        LED_Stop = 1;
       BEEP = 1;
    }
}

light.h文件:

#ifndef   _LIGHT_H
#define   _LIGHT_H
#define  uchar   unsigned char
#define  uint	   unsigned int
void  LED_Display(uchar );
void  delay_ms(uint );
#endif

key.c文件:

 #include "key.h"
#include "reg52.h"
#include "motor.h"
sbit  K1 = P0 ^ 0;
sbit  K2 = P0 ^ 1;
sbit  K3 = P0 ^ 2;
#define uchar unsigned char
#define uint  unsigned int
extern uchar comp ;
extern uchar Turn_flag;

void delay(uint i)
{
    while(i--);
}

u8  Key_Scan(void)
{
    if(K1 == 0)
    {
        delay(500);
        if(K1 == 0)  return 1;
        else         return 0;
    }
    else if(K2 == 0)
    {
        delay(500);
        if(K2 == 0)  return 2;
        else         return 0;
    }
    else if(K3 == 0)
    {
        delay(500);
        if(K3 == 0)  return 3;
        else         return 0;
    }
    else           return 0;
}

void   Key_Ctrl(u8 i)
{
    switch (i)
    {
    case  1:
        if(comp != 80)  comp += 10;
        else  comp = 80;
        break;
    case  2:
        if(comp != 0)   comp -= 10;
        else  comp = 0;
        Turn_flag = 3;
        break;
    case  3:
        comp = 0;
        break;
    default:
        break;
    }
}

key.h文件:

#ifndef  _KEY_H
#define  _KEY_H
#define  u8  unsigned char
#define  u16 unsigned int

u8     Key_Scan(void);
void   Key_Ctrl(u8 );
#endif

附焊接图:在这里插入图片描述

版权声明:本文为CSDN博主「睡不够呀」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zstu_zhoubenshan/article/details/122591977

生成海报
点赞 0

睡不够呀

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

基于8051单片机实现电子时钟+数字秒表设计

概述 电子时钟是一种利用数字电路来显示秒、分、时的计时装置,与传统的机械钟相比,它具有走时准确、显 示直观、无机械传动装置等优点,因而得到广泛应用。随着人们生活环境的不断改善和美化,在许