51单片机 蓝牙 循迹 ,定时器产生4个PWM

#include <reg52.h>

sbit TestPin =P1^0;

//循迹,四路循迹
//LS1 LS0 MS RS0 RS1
//sbit LS1 = P2^4;
sbit LSe0 = P2^3;
sbit RSe0 = P2^1;
//sbit RS1 = P2^0;


sbit LPWM0 = P1^2;
sbit LPWM1 = P1^3;
sbit RPWM0 = P1^4;
sbit RPWM1 = P1^6;
//全局变量
unsigned int Timer0Delay_cnt=0;

unsigned char LineStatus =0;//传感器状态,没有线,左,右,中,十字,T字,0,1,2,3,4,
unsigned char TrackLineTask =0 ;//循迹的任务标记,由按键设置=1,开始巡线

//蓝牙接收到字符,左,右,前进,后退,停止,调头,开始循迹
bit cmdflag_REC=0; //接收数据的标记位
bit cmdflag=0;
unsigned char cmdnum=0; //接收数据的个数
unsigned char cmddat=0; //接收的数据
unsigned char cmdbuff[5]=0; //接收缓冲字
char cmdlist =0; //1 ,停止,2,前进,3左,4右,5后退,串口命令表
//蓝牙




char LPWM0Set=0;
char LPWM1Set=0;

char RPWM0Set=0;
char RPWM1Set=0;

void delay(int tms)   //20ms
{
	int i,j;
	for(i=0;i<tms;i++)
	{
	  for(j=0;j<110;j++);
	}
}

void main()
{
		TMOD=0x11; //定时器 0 工作在模式 1,16 位定时模式
	 TH0 = 0xFF;                //100us
	  TL0 = 0x0B; 
		TH1=(65535-10)/256; //定时 10us
		TL1=(65535-10)%256;
		ET0=1;//打开定时器0中断开关
	  ET1=1;//打开定时器0中断开关
	
	
	//***********定时器2作为波特率9600
		TL2 = RCAP2L=(65536-(11059200L /32/9600));
		//9600 波特率对应 FFD9,低位为 D9(65536-26)%256
		TH2 = RCAP2H=(65536-(11059200L /32/9600)) >> 8;
	// 高 位 为FF(65536-26)/256
		T2CON=0x34;//RCLK、TCLK、TR2 置 1
		SCON=0x50;//串口工作模式 1,接收使能
		TI=1;
	  ES=1;
	
		
		EA=1;//打开总中断开关
		TR0=1;//打开定时器
    TR1=1;//打开定时器

    
			
	
		while(1)
    { //正转 

			
			if(cmdlist ==1)
			{
				LPWM0Set =10;
			LPWM1Set =10;
			
			RPWM0Set =10;
			RPWM1Set =10;

			}
			else if(cmdlist ==2)
			{
				LPWM0Set =0;
				LPWM1Set =0;
				
				RPWM0Set =0;
				RPWM1Set =0;
			}
		


			
			}
}
/* 定时器0中断函数,定时器0的中断优先级,默认比定时器1的要高,除非额外设置 */
void tm0_isr() interrupt 1 using 1
{
	static unsigned int cnt_tim0=0; //静态变量,只定义一次。
   TH0 = 0xF8;                //65535-2000===3.3ms
	 TL0 = 0x2F;  
   cnt_tim0++;	// 
   Timer0Delay_cnt++;
	 if(cnt_tim0%2==0)//3.3ms*2=6.6ms,读取一次IO口状态,循迹
	 {

		 if(LSe0 ==1 )
		 {
				LineStatus =0;
		 }
		 
		 else	 if(LSe0 ==0 )
		 {
			 LineStatus =1;
		 }
		 
		 
		 
		 
	 }
	  if(cnt_tim0%4==0)//3.3ms*4=13.2ms,做一次循迹,读取一次串口数据,
	 {
		 if(TrackLineTask ==1) //如果是巡线任务,进行判断
		 {
				switch( LineStatus)
			 {
					case 0:
						
						break;
					
					case 1:
						
						break;
					
					case 2:
						
						break;
					
					case 3:
						
						break;
					
					case 4:
						
						break;
					
					
					
					default:break;
					
					
			 }
			 
		 }
		
		 
	    if(cmdflag_REC==1) //
		 {
			cmdflag_REC=0;
			if(cmdbuff[0]=='0'&&cmdbuff[1]=='n')
			//第一个字节为 0,第二个字节为 n,第三个字节为控制码,手机端发送的应该是 0nb 等
			 switch(cmdbuff[2])
				{
						case 'f' :
						//小车前进
								cmdlist=1;
						break;
						
						
						
						case 'b':
						// 后退 backxxx
					
						break;
						
						
						
						case 'l':
						// 左转 leftxxx
					
						break;
						
						
						case 'r':
						// 右转 rightxx
						
						break;
						
						
						
						case 's':
						// 停止 stopxxx
								cmdlist=2;
						break;
						default:break;
				}
			}
		 
			//**********************20ms刷新LCD1602的数据,速度和行程
			  if(cnt_tim0%6==0)
				{
				
				}
				
				if(cnt_tim0 >1000)cnt_tim0=0;
	 }
		 
		
	
}

//定时器1中断函数,产生4路的PWM,最大是20个toc
void tm1_isr() interrupt 3
{
   
		static char cnt00=0;
		TH1=0xFF;
		TL1=0x50;
	  cnt00++;

		//决定PWM的周期,也就是频率,
		if(cnt00>=20)
		{
			cnt00=0;
		}
		

		//输出PWM
		if(cnt00<LPWM0Set)//1s=1000ms 20ms
		{
			LPWM0=1;
		}
		else
		{
			LPWM0=0;
		}


		//输出PWM
		if(cnt00<LPWM1Set)//1s=1000ms 20ms
		{
			LPWM1=1;
		}
		else
		{
			LPWM1=0;
		}
		
		
		
		//输出PWM
		if(cnt00<RPWM0Set)//
		{
			RPWM0=1;
		}
		else
		{
			RPWM0=0;
		}
		//输出PWM
		if(cnt00<RPWM1Set)//
		{
			RPWM1=1;
		}
		else
		{
			RPWM1=0;
		}
		
}


//串口1中断函数,
void UartIsr() interrupt 4 using 1
{
	if(RI) //是否接收中断
	{
		RI=0;
		cmddat=SBUF;
		 if(cmddat=='0'&&(cmdnum==0)) //接收数据第一帧
			{
				cmdbuff[cmdnum]=cmddat;
				cmdflag=1; //开始接收数据
			}
			else
			if(cmdflag==1) //如果不是第一个数据,说明帧头校验通过,就继续接收,
			{
					cmdnum++;
					cmdbuff[cmdnum]=cmddat;//0---1--2--0
				if(cmdnum>=2)
					{
						cmdnum=0;
						cmdflag=0;
						cmdflag_REC=1;// 停止接收
					}
			}
		
		}
	}
	
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个基于51单片机的二驱循迹小车PWM调速代码示例: ```c #include <reg51.h> // 定义左右电机驱动引脚 sbit LEFT_MOTOR_PIN1 = P2^0; sbit LEFT_MOTOR_PIN2 = P2^1; sbit RIGHT_MOTOR_PIN1 = P2^2; sbit RIGHT_MOTOR_PIN2 = P2^3; // 定义左右电机PWM控制引脚 sbit LEFT_MOTOR_PWM = P1^2; sbit RIGHT_MOTOR_PWM = P1^3; // 定义循迹传感器引脚 sbit SENSOR_PIN1 = P0^0; sbit SENSOR_PIN2 = P0^1; sbit SENSOR_PIN3 = P0^2; sbit SENSOR_PIN4 = P0^3; sbit SENSOR_PIN5 = P0^4; // 定义调速变量 unsigned char leftSpeed = 0; unsigned char rightSpeed = 0; void main() { // 初始化定时器0 TMOD |= 0x01; TH0 = 0xFC; TL0 = 0x67; ET0 = 1; TR0 = 1; EA = 1; // 初始化串口 SCON = 0x50; TMOD |= 0x20; TH1 = 0xFD; TL1 = 0xFD; ES = 1; TR1 = 1; // 无限循环 while (1) { // 读取循迹传感器数据 unsigned char sensor1 = SENSOR_PIN1; unsigned char sensor2 = SENSOR_PIN2; unsigned char sensor3 = SENSOR_PIN3; unsigned char sensor4 = SENSOR_PIN4; unsigned char sensor5 = SENSOR_PIN5; // 计算偏差值 int error = sensor1 * 1 + sensor2 * 2 + sensor3 * 3 + sensor4 * 2 + sensor5 * 1 - 10; // 根据偏差值调整左右电机PWM占空比 leftSpeed = 100 - error * 2; rightSpeed = 100 + error * 2; // 限制PWM占空比范围 leftSpeed = leftSpeed > 100 ? 100 : leftSpeed; rightSpeed = rightSpeed > 100 ? 100 : rightSpeed; // 控制电机转速 TH1 = leftSpeed; TL1 = leftSpeed; LEFT_MOTOR_PWM = 1; TH1 = rightSpeed; TL1 = rightSpeed; RIGHT_MOTOR_PWM = 1; // 控制电机方向 if (leftSpeed > 0) { LEFT_MOTOR_PIN1 = 1; LEFT_MOTOR_PIN2 = 0; } else { LEFT_MOTOR_PIN1 = 0; LEFT_MOTOR_PIN2 = 1; } if (rightSpeed > 0) { RIGHT_MOTOR_PIN1 = 1; RIGHT_MOTOR_PIN2 = 0; } else { RIGHT_MOTOR_PIN1 = 0; RIGHT_MOTOR_PIN2 = 1; } } } // 定时器0中断服务程序 void timer0_isr() interrupt 1 { TH0 = 0xFC; TL0 = 0x67; P1 = 0x00; } // 串口中断服务程序 void serial_isr() interrupt 4 { if (RI) { RI = 0; } if (TI) { TI = 0; } } ``` 该代码中使用了定时器0和串口进行PWM输出和调试信息输出,实现了小车的循迹行驶。同时,还对PWM占空比范围进行了限制,并控制电机的转速和方向。最后,通过串口打印调试信息,方便调试和优化程序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值