it编程 > 硬件开发 > stm32

循迹小车基本原理和代码实现

82人参与 2024-08-06 stm32

目录

一、循迹模块使用

二、接线方式

三、循迹小车原理

四、代码实现


一、循迹模块使用

1、tcrt5000传感器的红外发射二极管不断发射红外线,当发出的红外线没有被反射回来或被反射回来但强度不太够时,红外接收管一直处于关断状态,此时模块的输出为高电平指示二极管一直处于熄灭状态,被检测物体出现在检测范围内时,红外线被反射回来且强度足够大,红外接收管饱和,此时模块的输出端为低电平,指示二极管被点亮

总之一句话:没反射回来,d0输出高电平,灭灯

二、接线方式

vcc:接上官一号正极(3-5v)

gnd:接上官一号负极

d0:ttl开关信号输出0、1

a0:模拟信号输出(不同距离输出不同的电压,此脚一般可以不接)

三、循迹小车原理

由于黑色具有较强的吸收能力,当循迹模块发射的红外线照射到黑线时,红外线将会被黑线吸收,导致循迹模块上光敏二

0.极管处于关闭状态,此时模块上一个led熄灭,在没有检测到黑线时,模块上两个led常亮

总结就是一句话:有感应到黑线,d0输出高电平,灭灯

循迹模块安装在小车车头两侧

下方小车两个模块都能反射回来红外,输出低电平,灯亮,直走

上方小车左循迹模块遇到黑线,红外被吸收,左模块输出高电平,右模块输出低电平,左转,反之右转 

总结:两个小绿灯都亮,那左右两边的车轮就都转动,只亮一个小绿灯的说明这侧遇到了黑线,红外被吸收,红外没有被反射回来,输出高电平,所以就不转动了。

四、代码实现

main.c

#include "motor.h"
#include "delay.h"
#include "uart.h"
#include "time.h"
#include "reg52.h"

extern char speedleft;   //此变量/函数是在别处定义的,要在此处引用
extern char speedright;

sbit leftsensor  = p2^7;
sbit rightsensor = p2^6;

void main()
{
	time0init();   //定时器0初始化
	time1init();   //定时器1初始化
	uartinit();    //串口初始化

	while(1){
		
		if(leftsensor == 0 && rightsensor == 0 ){
			//直走
			speedleft = 40;   
			speedright = 40;
		}
		if(leftsensor == 1 && rightsensor == 0 ){
			//左转
			speedleft = 10;   
			speedright = 40;
			
		}
		if(leftsensor == 0 && rightsensor == 1 ){
			//右转
			speedleft = 40;
			speedright = 10;
			
		}
		if(leftsensor == 1 && rightsensor == 1){
			//停止
			speedleft = 0;
			speedright = 0;
		}		
	}
}

motor.c

#include "reg52.h"


sbit rightcon1a = p3^2;
sbit rightcon1b = p3^3;

sbit leftcon1a = p3^4;
sbit leftcon1b = p3^5;

void goforwardleft(){     //小车左前进

	leftcon1a = 1;
	leftcon1b = 0;
}

void goforwardright(){    //小车右前进
	
	
	rightcon1a = 1;
	rightcon1b = 0; 
}

void stopleft(){          //小车左停止

	leftcon1a = 0;
	leftcon1b = 0;
}

void stopright(){         //小车右停止
	 
	rightcon1a = 0;
	rightcon1b = 0; 
}

void goforward(){         //小车前转

	leftcon1a = 1;
	leftcon1b = 0;
	rightcon1a = 1;
	rightcon1b = 0; 

}

void goback(){           //小车后转
	
	leftcon1a = 0;
	leftcon1b = 1;
	rightcon1a = 0;
	rightcon1b = 1; 
}

void goleft(){   //小车左转
	
	leftcon1a = 0;
	leftcon1b = 0;
	rightcon1a = 1;
	rightcon1b = 0; 
}



void goright(){   //小车右转
	
	leftcon1a = 1;
	leftcon1b = 0;
	rightcon1a = 0;
	rightcon1b = 0; 
}


void stop(){   //小车停止
	
	leftcon1a = 0;
	leftcon1b = 0;
	rightcon1a = 0;
	rightcon1b = 0; 
}

motor.h

void goforward();
void goback();
void goleft();
void goright();
void stop();
void goforwardleft();
void goforwardright();
void stopleft();
void stopright();

delay.c


#include "intrins.h"

void delay1000ms()		//@11.0592mhz
{
	unsigned char i, j, k;

	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void delay10ms()		//@11.0592mhz
{
	unsigned char i, j;

	i = 18;
	j = 235;
	do
	{
		while (--j);
	} while (--i);
}

delay.h

void delay1000ms();
void delay10ms();

uart.c------串口初始化文件

#include "reg52.h"
#include "motor.h"
#include "string.h"
#include "delay.h"
#define size 12

sfr auxr = 0x8e;
char cmd;
char buffer[size];

void uartinit(void)		//9600bps@11.0592mhz
{
	auxr = 0x01;   //降低时钟对外界的辐射
	scon = 0x50;   //串行口寄存器工作模式选择方式1,rne=1,为串行允许接收状态
	
	tmod &= 0x0f;  //定时器1工作方式位8位自动重装
	tmod |= 0x20;
	
	th1 = 0xfd; 
	tl1 = 0xfd;   //9600波特率的初值
	tr1 = 1;      //启动定时器
	
	ea = 1;       //总中断寄存器,开启总中断
	es = 1;       //开启串口中断
	
}



void	uart_handler()	interrupt 4
{
	
	char tmp;
	static int i = 0;   //静态变量,被初始化一次
	if(ri == 1){        //中断处理函数中,对于接收中断的响应  
		ri = 0;           //清除接收中断标志位
		tmp = sbuf;
		if(tmp == 'm'){
			i = 0;
		}
		buffer[i++] = tmp;
	
		if(buffer[0] == 'm'){
			switch(buffer[1]){
				
				case '1':
					goforward();
					delay10ms();
					break;
				case '2':
					goback();
					delay10ms();
					break;
				case '3':
					goleft();
					delay10ms();
					break;
				case '4':
					goright();
					delay10ms();
					break;
				default:
					stop();
					break;
			}
			
		}
		if(i == 12) {
			i = 0;
			memset(buffer,'\0',size);
		}
	}
}

uart.h

void uartinit(void);

time.c------初始化定时器及定时器开启中断文件


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

char speedleft;
char cntleft = 0;


char speedright;
char cntright = 0;

void time1init(){

	//1、配置定时器0工作模式位16位计时
	tmod &= 0x0f;
	tmod |= 0x1 << 4;
	//2、给定时器一个初值,每个周期都等于0.5ms
	tl1 = 0x33;
	th1 = 0xfe;
	//3、定时器开始计时
	tr1 = 1;
	tf1 = 0;
	
	//4、打开中断定时器1
	et1 = 1;
	//5、设置总中断定时器
	ea = 1;
	
}

void time0init(){

	//1、配置定时器0工作模式位16位计时
	tmod = 0x01;
	//2、给定时器一个初值,每个周期都等于0.5ms
	tl0 = 0x33;
	th0 = 0xfe;
	//3、定时器开始计时
	tr0 = 1;
	tf0 = 0;
	
	//4、打开中断定时器
	et0 = 1;
	//5、设置总中断定时器
	ea = 1;
	
}

void time1handler() interrupt 3   //定时器0的中断号为 interrupt 1
{
	
	cntright ++;           //统计爆表的次数
	//给定时器重新定义初值,每个周期都等于0.5ms
	tl1 = 0x33;      
	th1 = 0xfe;
	//控制pwm波形
	if(cntright < speedright){
		//右前进
		goforwardright();
		
	}else{
		//右停止
		stopright();
		
	}
	
	if(cntright == 40){   //要爆表40次,经过了20ms
			cntright = 0;      //当100次表示1s,重新让cnt从0开始,计算下一次的1s
			
	}
}


void time0handler() interrupt 1   //定时器0的中断号为 interrupt 1
{
	
	cntleft ++;           //统计爆表的次数
	//给定时器重新定义初值,每个周期都等于0.5ms
	tl0 = 0x33;      
	th0 = 0xfe;
	//控制pwm波形
	if(cntleft < speedleft){
		//左前进
		goforwardleft();
		
	}else{
		//左停止
		stopleft();
		
	}
	
	if(cntleft == 40){   //要爆表40次,经过了20ms
			cntleft = 0;      //当100次表示1s,重新让cnt从0开始,计算下一次的1s
			
	}
}

time.h

void time0init();
void time1init();

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

STM32 OLED屏幕SSD1306显示浮点 负数

08-06

GD32F303高级定时器输出互补PWM-开发笔记

08-06

STLINK CONNECTION ERROR 问题的解决

08-06

J-Link:STM32使用J-LINK烧录程序,其他MCU也通用

08-06

【STM32】GPIO口以及EXTI外部中断

08-06

【STM32-矩阵键盘】

08-06

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论