STM32F103C8T6 Smart Car Steering Gear Ultrasonic Obstacle Avoidance

Table of contents

1. Timer

Count and Timer Interrupts

 Output compare (PWM)

2. Steering gear

3. Ultrasonic ranging

Fourth, the main function

Summarize


Recommended STM32 learning link: 

[6-1] TIM Timing Interrupt_哔哩哔哩_bilibili [6-1] TIM Timing Interruption is the 13th episode of STM32 Introductory Tutorial-2022 Continuous Update. This collection has a total of 29 episodes. Video collection or follow UP master , keep in touch with more related video content. https://www.bilibili.com/video/BV1th411z7sn?p=13&vd_source=ed36b2700bbc2bac7746c270bc391540 delay function and OLED function code:

STM32F103C8T6 delay function and OLED display code_HX091624's Blog-CSDN Blog

Use the steering gear to drive the ultrasonic to rotate different angles, complete the distance measurement in the first three directions of the left and right, and complete the obstacle avoidance after judgment

1. Timer

Count and Timer Interrupts

#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);
}

 Output compare (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);
}

2. Steering gear

#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);
}

3. Ultrasonic ranging

Ultrasonic ranging: complete the following three steps, and note that the ultrasonic must be connected to 5V, otherwise it will not work and cause a while loop in the qidongceju function.

#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);
	}
}	

Fourth, the main function

#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);
	}
}

Summarize

Servo control: http://www.51hei.com/bbs/dpj-156595-1.html

Guess you like

Origin blog.csdn.net/HX091624/article/details/127197519