STM32F103C8T6智能小车舵机超声波避障

目录

一、定时器

计数和定时器中断

 输出比较(PWM)

二、 舵机

三、超声波测距

四、主函数

总结


推荐的STM32学习链接: 

[6-1] TIM定时中断_哔哩哔哩_bilibili[6-1] TIM定时中断是STM32入门教程-2022持续更新中的第13集视频,该合集共计29集,视频收藏或关注UP主,及时了解更多相关视频内容。https://www.bilibili.com/video/BV1th411z7sn?p=13&vd_source=ed36b2700bbc2bac7746c270bc391540延时函数和OLED函数代码:

STM32F103C8T6延时函数和OLED显示屏代码_HX091624的博客-CSDN博客

扫描二维码关注公众号,回复: 14744277 查看本文章

使用舵机带动超声波转动不同角度,完成左右前三个方向的距离测量、判断后完成避障

一、定时器

计数和定时器中断

#include "stm32f10x.h"                 
//定时器2计数得到时间  计一个数-> 1US
//定时器2主要用在超声波测距
void Timer2_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 50000 - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 144 - 1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	//TIM_Cmd(TIM2, ENABLE);
}
//定时4中断计时  一次中断1MS
//定时器主要是作为时间基准使用
void Timer4_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
	TIM_InternalClockConfig(TIM4);
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;

	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 1000 - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStructure);
	TIM_ClearFlag(TIM4, TIM_FLAG_Update);
	TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	//运行控制
	TIM_Cmd(TIM4, ENABLE);
}

//定时器2启动控制
void TIM2_Run(uint8_t flag)
{
	if(flag)
		TIM_Cmd(TIM2, ENABLE);
	else
		TIM_Cmd(TIM2, DISABLE);
}
//获取定时器2计数器的值
uint16_t TIM2_GetCounter(void)
{
	uint16_t Counter;
	Counter=TIM_GetCounter(TIM2);
	return Counter;
}
//设置定时器2计数器的值
void TIM2_SetCounter(uint16_t Count)
{
	TIM_SetCounter(TIM2,Count);
}

 输出比较(PWM)

#include "stm32f10x.h"                  
//定时器3PWM调速  周期20MS  计一个数->1US
void PWM_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //电动机PWM输出 PA6 PA7
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //舵机PWM输出 PB0
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM3);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 0;		//CCR
	TIM_OC1Init(TIM3, &TIM_OCInitStructure);
	TIM_OC2Init(TIM3, &TIM_OCInitStructure);
	TIM_OC3Init(TIM3, &TIM_OCInitStructure);
	
	TIM_Cmd(TIM3, ENABLE);
}
//左右电机输出比较
void PWM_SetCompare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM3, Compare);
}

void PWM_SetCompare2(uint16_t Compare)
{
	TIM_SetCompare2(TIM3, Compare);
}
//舵机输出比较
void PWM_SetCompare3(uint16_t Compare)
{
	TIM_SetCompare3(TIM3, Compare);
}

二、 舵机

#include "stm32f10x.h"                  
#include "PWM.h"
//SG90舵机
void Servo_Init(void)
{
	PWM_Init();
}
//舵机转动 直接输入角度
void Servo_SetAngle(float Angle)
{
	//0->500 180->2500  2.5ms
	PWM_SetCompare3(Angle / 180 * 2000 + 500);
}

三、超声波测距

超声波测距:完成以下三步即可,同时注意超声波要接5V,否则不工作导致qidongceju函数中的while死循环。

#include "stm32f10x.h"                  
#include "Servo.h" 
#include "Delay.h" 
#include "Timer.h" 
#include "MotorRun.h"

uint16_t T=0; 						
unsigned long S=0;
unsigned long S1=0;			//存放前方距离值
unsigned long S2=0;			//存放右边距离
unsigned long S3=0;			//存放左边距离
extern uint16_t time;		//延时基准变量

//超声波初始化
void bizhang_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	//TRIG
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	//ECHO
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;	//上拉输入
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}
//超声波测距函数
unsigned long qidongceju(void)
{
	GPIO_SetBits(GPIOA,GPIO_Pin_2);					//TRIG
	Delay_ms(20);                                   //20us的信呈
	GPIO_ResetBits(GPIOA,GPIO_Pin_2);
	while(!GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3));//判断ECHO是否输出高电平
	TIM2_SetCounter(0);								//计数器清零
	TIM2_Run(1);									//开启定时器
	while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3));
	TIM2_Run(0);
	T=TIM2_GetCounter();							//ECHO高电平的时长
	TIM2_SetCounter(0);
	S=(T*1.7)/50;									//计算得到距离 CM
	return S;
}
//舵机转动测距函数
void COMM(void)
{
	//测出左中右三个方向的距离  右->左->中
	Servo_SetAngle(30);	     //舵机向右转
	time=0;
	while(time<=400);        //延时400MS让舵机转到其位置
	//启动超声波测距计算距离
	S2=qidongceju();         //存储右边距离
	Servo_SetAngle(150);     //舵机向左转
	time=0;
	while(time<=400); 
	S3=qidongceju(); 	     //存储左边距离
	Servo_SetAngle(90);      //舵机归中
	time=0;
	while(time<=400); 
	S1=qidongceju(); 	     //存储正前方距离
	if((S2<15)||(S3<15))     //左边或者右边的距离小于15cm
	{ 
		backrun(15);	     //小车后退
		time=0;
		while(time<=200);    //后退一段时间
	}
	if(S2>S3)		 	     //如果右边距离大于左边距离
	{
		rightrun(20);  	     //车的左边比车的右边距离小,右转	
		time=0;
		while(time<=600);
	}				      
	else				     //如果右边距离小于左边距离
	{
		leftrun(20);		 //车的左边比车的右边距离大,左转
		time=0;
		while(time<=200);
	}
}	

四、主函数

#include "stm32f10x.h"                  // Device header
#include "bizhang.h"
#include "OLED.h"
#include "Timer.h"
#include "Servo.h"
#include "Motor.h"
#include "MotorRun.h"
#include "Delay.h"

uint16_t time;			//延时基准时间
unsigned long disbance; //距离
float Angle;			//舵机转动角度

int main(void)
{
	OLED_Init();
	Motor_Init();
	Servo_Init();
	Timer2_Init();
	Timer4_Init();
	bizhang_Init();
    //OLED显示
	OLED_ShowString(1,1,"disbance:");
	while (1)
	{
		disbance=qidongceju();  		//启动超声波测出前方距离
		OLED_ShowNum(1,10,disbance,3);
		if(time>=40)	        		//20MS检测启动检测一次
		{
			Servo_SetAngle(90);			//舵机归中
			time=0;
			disbance=qidongceju();  	//启动超声波测出前方距离
			OLED_ShowNum(1,10,disbance,3);
			if(disbance<15)		    	//如果距离小于15CM
			{
				stop();
				COMM();
			}
			else
			{
				run(15);
			}
		}
	}
}

//定时器4中断
void TIM4_IRQHandler(void)  
{   //1MS
	if (TIM_GetITStatus(TIM4, TIM_IT_Update) == SET)
	{
		time++; //基准计时
		TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
	}
}

总结

舵机控制:http://www.51hei.com/bbs/dpj-156595-1.html

猜你喜欢

转载自blog.csdn.net/HX091624/article/details/127197519