89C52RC单片机学习-智能小车通过PWM调速

实际上两个电机即使型号相同还是有转速差,所以小车走直线的时候会偏航,这个时候就需要对两个轮子的转速进行调整以达到同步。
这里使用到定时器中断T0和T2进行PWM调速,这里定时器中断时间设定为0.5ms,40个定时器中断为一个周期,也就是20ms。
如本程序中设定LeftSpeed=33; RightSpeed=40;左轮的占空比为33/40,右轮占空比为40/40.这样就可以调节左轮速度降下来,这里的左转右转也进行了PWM调速,方法类似。
这里还需要注意定时器中断触发时间不能过短,否则轮子不转。

#include "motor.h"
#include "reg52.h"
#include "Usart_Init.h"
#include "delay.h"
#include "intrins.h"
#include "string.h"

#define bufferlen 12
char buffer[12];
char leftcnt=0;
char righrcnt=0;
char LeftSpeed;
char RightSpeed;

//管脚配置
//右轮
sbit RightA=P3^3;
sbit RightB=P3^2;
//左轮
sbit LeftA=P3^4;
sbit LeftB=P3^5;

sbit LeftSersor =P2^6;
sbit RightSersor =P2^7;




//直接通过调节电机的占空比来达到左右轮分明调速的目的。

//前进,左轮动力较强,右轮动力较弱,调节左轮占空比
void ForWard()
{
	
	LeftSpeed=33;//调节左轮占空比位33/40
	RightSpeed=40;//右轮占空比100/100
	//左轮前进
		RightA=1;
		RightB=0;
	//右轮前进
		LeftA=1;
		LeftB=0;
		
}
//后退
void BackWard()
{
	LeftSpeed=33;//调节左轮占空比位33/40
	RightSpeed=40;//右轮占空比100/100
	//左轮后退
		RightA=0;
		RightB=1;
	//右轮后退
		LeftA=0;
		LeftB=1;
}

//左转
void LeftWard()
{
	LeftSpeed=3;//调节左轮占空比位5/40
	RightSpeed=25;//右轮占空比25/40
	//左轮前进
		RightA=1;
		RightB=0;
	//右轮前进
		LeftA=1;
		LeftB=0;
}

//右转
void RightWard()
{
	LeftSpeed=24;//调节左轮占空比位5/40
	RightSpeed=5;//右轮占空比25/40
	//左轮前进
		RightA=1;
		RightB=0;
	//右轮前进
		LeftA=1;
		LeftB=0;

}

void Stop()
{
	//左右轮不动
		RightA=0;
		RightB=0;
		LeftA=0;
		LeftB=0;
}

void TrackCar()
{
//左边探测器和右边探测器都返回信号,保持直线。
		if (LeftSersor==0&&RightSersor==0)	
		{

	    ForWard();//
		}	
//如果左边有黑线,右边没有黑线,左转一点。
		else if(LeftSersor==1&&RightSersor==0)
		{
				RightWard();//
		}
//如果左边没有黑线,右边有黑线,右转一点。		
		else if(LeftSersor==0&&RightSersor==1)
		{
		LeftWard();//
		}
		//如果两边都是黑线停止
		else if(LeftSersor==1&&RightSersor==1)
		{
			Stop();//
		}
}


void main ()
{
	 uart_Init();//串口的初始化设置
	 Timer0Init();//定时器0的初始化
   Timer2Init();//定时器2的初始化
 		while(1)
		{
		  TrackCar();
		}
}
	


	void Speed_L()interrupt 1       //定时器1中断调节PWM,控制左轮速度
{
	leftcnt++;
	//重新赋初值
	  TH1 = 0x0FE;
    TL1 = 0x33;
	if(leftcnt<LeftSpeed)
	{
		LeftWard();//左转
	}	
	else
	{
    Stop();//停止
  }
	
	if(leftcnt==40)
	{
	  leftcnt=0;	
	}
}


void Speed_R() interrupt 5  //计时器2,调节PWM,控制右轮速度
{
	righrcnt++;
  TF2=0;//定时器2需要手动复位
	
	if(righrcnt<RightSpeed)
	{
		ForWard();//右转
	}	
	else
	{
    Stop();//停止
  }
	
	if(righrcnt==40)
	{
	 righrcnt=0;	
	}
}



//由模块Tx发出的有两种指令,1,AT功能设置指令的反馈 2,服务器串口发送的数据传到WiFi模块,再由模块发给单片机
void uart_Interrupt () interrupt 4   //中段函数。每次接收到WiFi模块发过来的数据进入中断
{
  static int i=0; //只在开始的时候执行一次
  if (RI)//当串口中断事件为接收到数据
		{
	  RI=0;
	  if(i==12)//不超过十二个字符
		{
			i=0;
		}
		buffer[i++]=SBUF;//全局变量接收WiFi模块Tx发送过来的数据
		
		if(buffer[i-1]=='M')//第一个数据M
		{
			buffer[0] =buffer[i-1];//buffer[i-1]才是刚才接收的数据
			i=1;
		}
		if (buffer[1]=='F')	//当接受的数据为“MF”
		{
		    ForWard();
			Delay500ms()	;
			memset(buffer, '\0', bufferlen);
		}
		if (buffer[1]=='B')//当接受的数据为“MB”
		{
			BackWard();
		    Delay500ms()	;
			memset(buffer, '\0', bufferlen);
		}

		if (buffer[1]=='L')//当接受的数据为“ML”
		{
	  	    LeftWard();
			Delay200ms();;
			memset(buffer, '\0', bufferlen);
		}
		if (buffer[1]=='R')//当接受的数据为“MR”
		{
	  	    RightWard();
		    Delay200ms();;
			memset(buffer, '\0', bufferlen);
		}	
		}
 	
}

Usart_Init.c

#include "reg52.h"
#include "motor.h"

sfr T2MOD  = 0xC9;//定时器2的模式寄存器
sfr P4  = 0xE8;
sfr XICON  = 0xC0;//拓展外部中断寄存器,外部中断2
sbit EX2   = XICON^2;
sbit IT2       = XICON^0;

void Timer0Init()//定时器0的初始化函数,
{
	TMOD &= 0xF0;		//定时器0设定重置
  TMOD |= 0x01;       //设置16位计时器
	TH1 = 0x0FE;//0.5MS
  TL1 = 0x33;
  EA = 1;//总开关连接
  ET0 = 1;//定时器0支路开关连接
	TF0=0;//溢出标志位清零
}
void Timer2Init()		//定时器2初始化
{
	T2MOD = 0;		//设置为向上计数
	T2CON = 0;		//设置为计时模式 16位重装模式
	TH2 = 0xFE;//0.5MS
  TL2 = 0x33;
	RCAP2H= 0xFE;		//设置定时重载值
	RCAP2L = 0x33;		//设置定时重载值
	ET2=1;
	TF2=0;
  TR2 = 1;		//定时器2开始计时
}

void uart_Init()//串口初始化
{
SCON=0X50;//设置串口的寄存器工作模式

TMOD &=0X0F;//定时器1的工作模式
TMOD |=0X2F;
TH1=0XFD;//设置波特率9600
TL1=TH1;
TR1=1;//定时器开始计时
EA=1;
ES=1;
}


delay.c

# include "intrins.h"


void Delay100ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 180;
	j = 73;
	do
	{
		while (--j);
	} while (--i);
}

void Delay2000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 15;
	j = 2;
	k = 235;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay500ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 129;
	k = 119;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay200ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 2;
	j = 103;
	k = 147;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

头文件

delay.h

void Delay2000ms();
void Delay50ms();
void Delay200ms();
void Delay100ms();
void Delay500ms()	;

Usart_Init.h

void uart_Init();
void Timer0Init();
void Timer2Init();
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值