51单片机期末设计(循迹,避障小车)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

简单记录一下完成期末作品的过程

一、硬件

小车的动力来源,直流电机(马达) 有电流通过就会产生动力

电机的驱动模块,我选择的是L298N.

 单片机用的是STC89C52,用自己最熟悉的就行。

循迹模块,采用最常用的就行。

二、组装小车

1.L289N的连接

 输入12V电压,输出5V电压(可以为单片机系统供电,建议采用)。使能接口的跳线帽不拆,电机就是最高功率输出。

单片机系统接线就没什么特殊的了,选择合适的就可以。

2.实物图

线接的也是一片混乱, 

三,代码

1,避障

先写避障的吧,因为我先做的避障功能,后续在避障功能的前提下做的循迹。

#include <reg52.H>

typedef unsigned int uint;
typedef unsigned char uchar;

uchar led_mod[] = { 0xfe,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09,0x88,0x83,0xc6,0xa1,0x86,0x8e };

uchar flag;              //由于记录行驶状态

uchar Duty = 1;

sbit IN1 = P1 ^ 2;
sbit IN2 = P1 ^ 3;
sbit IN3 = P1 ^ 4;
sbit IN4 = P1 ^ 5;

sbit BZ = P3 ^ 4;
sbit BY = P3 ^ 5;

sbit TZ = P1 ^ 0;
sbit TY = P1 ^ 1;

unsigned int i, j;



void delay(unsigned int n) {
	unsigned int i, j;
	for (i = 0; i < n; i++)
		for (j = 115; j >= 0; j--);
}	            //以上是带形式参数的延时函数n=1时为1ms


void ting()     //停车
{
	IN1 = 0;
	IN2 = 0;
	IN3 = 0;
	IN4 = 0;
}

void qianjin()     //前进
{
	IN1 = 1;
	IN2 = 0;
	IN3 = 1;
	IN4 = 0;
}

void houtui()      //后退
{
	IN1 = 0;
	IN2 = 1;
	IN3 = 0;
	IN4 = 1;
}

void zuo()        //左转
{
	IN1 = 0;
	IN2 = 1;
	IN3 = 1;
	IN4 = 0;
}

void you()        //右转
{
	IN1 = 1;
	IN2 = 0;
	IN3 = 0;
	IN4 = 1;
}

void bizhang()   //避障函数
{
	if ((BZ == 1) && (BY == 1))
	{
		flag = 0;
	}
	else if ((BZ == 1) && (BY == 0))
	{
		flag = 1;
	}
	else if ((BZ == 0) && (BY == 1))
	{
		flag = 2;
	}
	else if ((BZ == 0) && (BY == 0))
	{
		flag = 3;
	}
	else
	{
		flag = 0;
	}
	switch (flag)
	{
	case 0:qianjin(); break;
	case 1:zuo(); break;
	case 2:you(); break;
	case 3:houtui(); break;
	default:qianjin(); break;
	}
}

void Timer0_init()     //PWM中断初始化
{
	TMOD = (TMOD & 0XF0) | 0X01;
	TH0 = (65536 - 1000 / 1.085) / 256;
	TL0 = 65536 - 1000 / 1.085;
	TR0 = 1;
	ET0 = 1;

}

void TIMER0() interrupt 1     //PWM中断服务函数
{

	static uchar cnt;
	TH0 = (65536 - 1000 / 1.085) / 256;
	TL0 = 65536 - 1000 / 1.085;
	cnt++;
	if (cnt > 9)
		cnt = 0;
	if (cnt < Duty)
	{
		TZ = 1;
		TY = 1;
	}
	else
	{
		TZ = 0;
		TY = 0;
	}
}


void INTO()     //按键中断初始化
{
	IT0 = 1;
	EX0 = 1;
}

void int0() interrupt 0
{
	Duty++;
	if (Duty > 9)
		Duty = 1;
	P0 = led_mod[Duty];
}

void main()
{
	P0 = led_mod[1];
	INTO();
	Timer0_init();
	EA = 1;
	while (1)
	{
		bizhang();
	}
}

写的时候也借鉴了好多人的,这里用到了PWM调速。

PWM调速原理是利用脉冲宽度调制(PWM)来控制直流电机转速的一种方法。PWM调速器会周期性地改变输出电压的占空比,从而控制电机的转速。

具体来讲,PWM调速器会将输入电压(通常为直流电压)变换成矩形脉冲信号,其占空比可以通过改变PWM调速器的控制信号来调整。如果占空比较高,则输出电压较高,电机转速也较快;如果占空比较低,则输出电压较低,电机转速也较慢。

通过不断调整PWM调速器的占空比,可以实现精准的电机调速。

就比如10ms内全是5V输出,电机得到的电压就是5V,如果是前5ms输出5V电压,后5ms不输出电压,在高速的循环下电机得到的电压就等效于2.5V。占空比就相当于做功的时间与总时间的比值。通过调整这个比值来控制电机的功率。

PWM部分代码

void Timer0_init()     //PWM中断初始化
{
	TMOD = (TMOD & 0XF0) | 0X01;
	TH0 = (65536 - 1000 / 1.085) / 256;
	TL0 = 65536 - 1000 / 1.085;
	TR0 = 1;
	ET0 = 1;

}

void TIMER0() interrupt 1     //PWM中断服务函数
{

	static uchar cnt;
	TH0 = (65536 - 1000 / 1.085) / 256;
	TL0 = 65536 - 1000 / 1.085;
	cnt++;
	if (cnt > 9)
		cnt = 0;
	if (cnt < Duty)
	{
		TZ = 1;
		TY = 1;
	}
	else
	{
		TZ = 0;
		TY = 0;
	}
}

 通过调整Duty的值来控制电机的转速

Duty的值通过按键调整,

void INTO()     //按键中断初始化
{
	IT0 = 1;
	EX0 = 1;
}

void int0() interrupt 0
{
	Duty++;
	if (Duty > 9)
		Duty = 1;
	P0 = led_mod[Duty];
}

每按一次按键,Duty就加一,小车的速度就快一点。

2,循迹

循迹就没什么了,就是在避障的前提下把传感器的引脚改一下和对对应的信号做出的行动改一下,大致相同。

#include <reg52.H>

typedef unsigned int uint;
typedef unsigned char uchar;

uchar led_mod[] = { 0xfe,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09,0x88,0x83,0xc6,0xa1,0x86,0x8e };

uchar flag;              //由于记录行驶状态

uchar Duty = 1;

sbit IN1 = P1 ^ 2;
sbit IN2 = P1 ^ 3;
sbit IN3 = P1 ^ 4;
sbit IN4 = P1 ^ 5;

sbit XZ = P3 ^ 6;
sbit XY = P3 ^ 7;

sbit TZ = P1 ^ 0;
sbit TY = P1 ^ 1;

unsigned int i, j;



void delay(unsigned int n) {
	unsigned int i, j;
	for (i = 0; i < n; i++)
		for (j = 115; j >= 0; j--);
}	            //以上是带形式参数的延时函数n=1时为1ms


void ting()     //停车
{
	IN1 = 0;
	IN2 = 0;
	IN3 = 0;
	IN4 = 0;
}

void qianjin()     //前进
{
	IN1 = 1;
	IN2 = 0;
	IN3 = 1;
	IN4 = 0;
}

void houtui()      //后退
{
	IN1 = 0;
	IN2 = 1;
	IN3 = 0;
	IN4 = 1;
}

void zuo()        //左转
{
	IN1 = 0;
	IN2 = 1;
	IN3 = 1;
	IN4 = 0;
}

void you()        //右转
{
	IN1 = 1;
	IN2 = 0;
	IN3 = 0;
	IN4 = 1;
}

void xunji()   //循迹函数
{
	if ((XZ == 1) && (XY == 1))
	{
		flag = 0;
	}
	else if ((XZ == 1) && (XY == 0))
	{
		flag = 1;
	}
	else if ((XZ == 0) && (XY == 1))
	{
		flag = 2;
	}
	else if ((XZ == 0) && (XY == 0))
	{
		flag = 3;
	}
	else
	{
		flag = 0;
	}
	switch (flag)
	{
	case 0:ting(); break;
	case 1:you(); break;
	case 2:zuo(); break;
	case 3:qianjin(); break;
	default:qianjin(); break;
	}
}

void Timer0_init()     //PWM中断初始化
{
	TMOD = (TMOD & 0XF0) | 0X01;
	TH0 = (65536 - 1000 / 1.085) / 256;
	TL0 = 65536 - 1000 / 1.085;
	TR0 = 1;
	ET0 = 1;

}

void TIMER0() interrupt 1     //PWM中断服务函数
{

	static uchar cnt;
	TH0 = (65536 - 1000 / 1.085) / 256;
	TL0 = 65536 - 1000 / 1.085;
	cnt++;
	if (cnt > 9)
		cnt = 0;
	if (cnt < Duty)
	{
		TZ = 1;
		TY = 1;
	}
	else
	{
		TZ = 0;
		TY = 0;
	}
}


void INTO()     //按键中断初始化
{
	IT0 = 1;
	EX0 = 1;
}

void int0() interrupt 0
{
	Duty++;
	if (Duty > 9)
		Duty = 1;
	P0 = led_mod[Duty];
}

void main()
{
	P0 = led_mod[1];
	INTO();
	Timer0_init();
	EA = 1;
	while (1)
	{
		xunji();
	}
}

四,运行图片

只展示循迹的了,也没有画线就沿着地砖缝走了一小节。速度选择的二挡。


 

总结

就是简单记录一下期末作业的完成,有不足的还望指出。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值