主要目标:
(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半桥驱动
通过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