【单片机项目】基于STM32的智能小车设计(三)软件设计

        这是智能小车的最后一篇博客,主要讲解一下小车的程序设计。

电机的驱动:

        我写了俩种转弯,一种是一个轮朝后一个轮朝前的转弯,另一种是抱死一个轮另一个向前,使用PWM来调速,PWM的占空比不能太小,有效电压低于2.4伏无法驱动298N。

#ifndef __MOTOR_H
#define __MOTOR_H
#include "sys.h"
#include <stm32f10x.h>


#define HIGH_SPEED 1
#define LOW_SPEED 0
#define Moter1_CH3_Value  TIM2->CCR3 
#define Moter1_CH4_Value  TIM2->CCR4
#define Moter2_CH3_Value  TIM1->CCR1
#define Moter2_CH4_Value  TIM1->CCR4


void MOTOR1_PWM_Init(u16 arr,u16 psc);
void MOTOR2_PWM_Init(u16 arr,u16 psc);
void Motor_Forward(u8 speed);
void Motor_Left1(u16 value);
void Motor_Right1(u16 value);
void Motor_Left2(u16 value);
void Motor_Right2(u16 value);
void Motor_Back(void);
void Motor_Stop(void);


#endif

#include "motor.h"
#include "delay.h"


//电机1(左侧)初始化
//PA3(CH4)  PA2(CH3)

void MOTOR1_PWM_Init(u16 arr,u16 psc)
{
	RCC->APB1ENR|=1<<0; 	//TIM2时钟使能    
	RCC->APB2ENR|=1<<2;    	//使能PORTA时钟	
	GPIOA->CRL&=0XFFFF00FF;	//PB10、11输出
	GPIOA->CRL|=0X0000BB00;	//复用功能输出 	

	   
	RCC->APB2ENR|=1<<0;     //开启辅助时钟	   
	AFIO->MAPR&=0XFFFFFCFF; //清除MAPR的[9:8]
	//AFIO->MAPR|=1<<9;      //部分重映像

	TIM2->ARR=arr;			//设定计数器自动重装值 
	TIM2->PSC=psc;			//预分频器不分频
	TIM2->CR1=0x0080;   	//ARPE使能 
	TIM2->CCMR2|=7<<12;  	//CH2 PWM2模式	
	TIM2->CCMR2|=1<<11; 	//CH2预装载使能	   
//	TIM2->CCER|=1<<12;   	//OC4 输出使能	   
	
	TIM2->CCMR2|=7<<4;  	//CH3 PWM2模式	
	TIM2->CCMR2|=1<<3; 		//CH3预装载使能	   
	//TIM2->CCER|=1<<8;   	//OC3 输出使能	   	
	TIM2->CR1|=0x01;    	//使能定时器3 	
}


//电机2(左侧)初始化
//PB7(CH3)   PB10(CH4)

void MOTOR2_PWM_Init(u16 arr,u16 psc)
{
	RCC->APB2ENR|=1<<11; 	//TIM1时钟使能    
	RCC->APB2ENR|=1<<2;    	//使能PORTB时钟	

	GPIOA->CRH&=0XFFFF0FF0;	//PB0、PB1输出
	GPIOA->CRH|=0X0000B00B;	//复用功能输出 	
	   
	RCC->APB2ENR|=1<<0;     //开启辅助时钟	   
	AFIO->MAPR&=0XFFFFFF3F; //清除MAPR的[7:6]
	//AFIO->MAPR|=1<<11;      //部分重映像
	TIM1->BDTR|=1<<15;
	TIM1->ARR=arr;			//设定计数器自动重装值 
	TIM1->PSC=psc;			//预分频器不分频
	TIM1->CR1=0x0080;   	//ARPE使能 
	TIM1->CCMR2|=7<<12;  	//CH4 PWM2模式	
	TIM1->CCMR2|=1<<11; 		//CH4预装载使能	     
	
	TIM1->CCMR1|=7<<4;  	//CH3 PWM2模式	
	TIM1->CCMR1|=1<<3; 		//CH3预装载使能	    
	TIM1->CR1|=0x01;    	//使能定时器1
}


/************************************************************
***************************停止*****************************
*****返回值:无
************************************************************/
void Motor_Stop(void)
{
	TIM1->CCER|=1<<0;   	//OC3 输出使能
	TIM1->CCER|=1<<12;   	//OC4 输出使能
	TIM2->CCER|=1<<8;   	//OC3 输出使能
	TIM2->CCER|=1<<12;   	//OC4 输出使能	
	Moter1_CH3_Value=0;
	Moter2_CH3_Value=0;
	Moter1_CH4_Value=0;
	Moter2_CH4_Value=0;
	delay_ms(500);
	TIM1->CCER&=~(1<<0);   	//OC3 输出禁止
	TIM1->CCER&=~(1<<12);   	//OC4 输出禁止
	TIM2->CCER&=~(1<<8);   	//OC3 输出禁止
	TIM2->CCER&=~(1<<12);   	//OC4 输出禁止
}

/************************************************************
**************************向前走*****************************
*****入口参数:speed(0:慢速 1:快速)
*****返回值:无
OUT2+ OUT1-      OUT4+ OUT3-
************************************************************/
void Motor_Forward(u8 speed)  
{
	TIM2->CCER&=~(1<<12);   	//OC4 输出禁止
	TIM1->CCER&=~(1<<12);   	//OC4 输出禁止
	TIM1->CCER|=1<<0;   	//TIM3 OC1 输出使能
	TIM2->CCER|=1<<8;   	//TIM2 OC1 输出使能	
	
	switch (speed)
	{
		case 0:
		{						
			Moter1_CH3_Value=390;
			Moter2_CH3_Value=350;			
			break;			
		}
		case 1:
		{
			Moter1_CH3_Value=450;
			Moter2_CH3_Value=440;
			break;
		}
	}
}
/************************************************************
***************************左转1*****************************
*****入口参数:无
*****返回值:无
************************************************************/
void Motor_Left1(u16 value)
{
	TIM2->CCER|=1<<8;   	//OC3 输出使能
	TIM2->CCER&=~(1<<12);   	//OC3 输出禁止
	TIM1->CCER|=1<<12;   	//OC4 输出使能
	TIM1->CCER&=~(1<<0);   	//OC3 输出禁止	
	
	
	Moter1_CH3_Value=150;
	Moter2_CH4_Value=300;
	delay_ms(value);
	TIM1->CCER&=~(1<<12);   	//OC4 输出禁止
	TIM2->CCER&=~(1<<8);   	//OC3 输出使能
}
/************************************************************
***************************右转1*****************************
*****返回值:无
************************************************************/
void Motor_Right1(u16 value)
{
	TIM1->CCER|=1<<0;   	//TIM3 OC1 输出使能
	TIM2->CCER&=~(1<<8);   	//OC3 输出禁止
	TIM2->CCER|=1<<12;   	//OC4 输出使能
	TIM1->CCER&=~(1<<12);   	//OC4 输出禁止
	
	Moter2_CH3_Value=300;
	Moter1_CH4_Value=150;
	delay_ms(value);
	TIM2->CCER&=~(1<<12);   	//OC4 输出禁止
	TIM1->CCER&=~(1<<0);   	//OC3 输出使能
}
/************************************************************
***************************左转1*****************************
*****入口参数:无
*****返回值:无
************************************************************/
void Motor_Left2(u16 value)
{
	Moter2_CH3_Value=990;
	Moter1_CH3_Value=410;
	delay_ms(value);
}
/************************************************************
***************************右转1*****************************
*****返回值:无
************************************************************/
void Motor_Right2(u16 value)
{
	Moter1_CH3_Value=990;
	Moter2_CH3_Value=350;
	delay_ms(value);
}
/************************************************************
***************************后退*****************************
*****入口参数:无
*****返回值:无
************************************************************/
void Motor_Back(void)
{
	TIM1->CCER|=1<<12;   	//OC4 输出使能
	TIM2->CCER|=1<<12;   	//OC4 输出使能
	TIM2->CCER&=~(1<<8);   	//OC3 输出禁止
	TIM1->CCER&=~(1<<0);   	//OC3 输出禁止
	
	Moter1_CH4_Value=50;
	Moter2_CH4_Value=50;
}

红外对管的驱动:

#ifndef __EXTI_H
#define __EXTI_H

void EXTI_Init(void);
#endif
#include "exti.h"
#include "delay.h"
#include "sys.h"
#include "motor.h"


u8 Tracing_Right=0;
u8 Tracing_Left=0;
void EXTI4_IRQHandler(void)
{	
	delay_ms(10);
	Tracing_Right=1;
	Motor_Right2(100);
	EXTI->PR=1<<4;	
}

void EXTI0_IRQHandler(void)
{
	
	delay_ms(10);
	Tracing_Left=1;
	Motor_Left2(100);
	EXTI->PR=1<<0;	
}


void EXTI_Init(void){
	RCC->APB2ENR|=1<<3;
	RCC->APB2ENR|=1<<2;
	GPIOB->CRL&=0xFFF00FFF;
	GPIOB->CRL|=0x00088000;
	GPIOA->CRL&=0xFFFFFFF0;
	GPIOA->CRL|=0x00000008;
	Ex_NVIC_Config(GPIO_B, 4, RTIR);	//PB4 上升沿触发 (右)
	Ex_NVIC_Config(GPIO_A, 0, RTIR);	//PA0 上升沿触发(左)
	MY_NVIC_Init(2, 1, EXTI0_IRQn, 2); //抢占2, 子优先级0, 组2
	MY_NVIC_Init(2, 0, EXTI4_IRQn, 2); //抢占2, 子优先级1, 组2
}

HC-SR04的驱动:

        输入捕获,采样三次取平均值

#ifndef __HCSR_04_
#define __HCSR_04_
#include "sys.h"

void HCSR_04_TIM3_Init(u16 arr,u16 psc);
u16 HCER_04_Get_Length(void);



#endif
#include "hcsr04.h"
#include "sys.h"
#include "delay.h"
#include "usart.h"


//[7] 0表示没有成功捕获 1表示成功捕获一次
//[6] 0表示还没捕获到低电平 1表示捕获到高电平
//[5:0]  捕获高电平后溢出的次数
u8 TIM3CH1_CAPTURE_STA=0;  //输入捕获状态
u16 TIM3CH1_CAPTURE_VAL;   //输入捕获值

void HCSR_04_TIM3_Init(u16 arr,u16 psc)
{
	RCC->APB1ENR|=1<<1;   	//TIM3 时钟使能 
	RCC->APB2ENR|=1<<2;   	//使能PORTA时钟	
	GPIOA->CRL&=0x00FFFFFF;
	GPIOA->CRL|=0x38000000;
	AFIO->MAPR&=0XFFFFF3FF; //清除MAPR的[11:10]
	AFIO->MAPR|=1<<11;      //部分重映像
	
	GPIOA->ODR|=1<<7;
	
 	TIM3->ARR=arr;  		//设定计数器自动重装值   
	TIM3->PSC=psc;  		//预分频器 

	TIM3->CCMR1|=1<<0;		//CC1S=01 	选择输入端 IC1映射到TI1上
 	TIM3->CCMR1|=0<<4; 		//IC1F=0000 配置输入滤波器 不滤波
 	TIM3->CCMR1|=0<<2; 	//IC1PS=00 	配置输入分频,不分频 

	TIM3->CCER|=0<<1; 		//CC1NP=0	上升沿捕获
	TIM3->CCER|=1<<0; 		//CC1E=1 	允许捕获计数器的值到捕获寄存器中

	//TIM3->BDTR|=1<<15;
	TIM3->EGR=1<<0;			//软件控制产生更新事件,使写入PSC的值立即生效,否则将会要等到定时器溢出才会生效!
	TIM3->DIER|=1<<1;   	//允许捕获1中断				
	TIM3->DIER|=1<<0;   	//允许更新中断	
	TIM3->CR1|=0x01;    	//使能定时器1
	
	MY_NVIC_Init(2,1,TIM3_IRQn,2);//抢占3,子优先级1,组2		捕获比较中断
}


void TIM3_IRQHandler(void)
{
	u16 tsr;
	tsr=TIM3->SR;
 	if((TIM3CH1_CAPTURE_STA&0X80)==0)//还未成功捕获	
	{
		if(tsr&0X01)//溢出
		{	     
			if(TIM3CH1_CAPTURE_STA&0X40)//已经捕获到高电平了
			{
				if((TIM3CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
				{
					TIM3CH1_CAPTURE_STA|=0X80;		//标记成功捕获了一次
					TIM3CH1_CAPTURE_VAL=0XFFFF;
				}else TIM3CH1_CAPTURE_STA++;
			}	 
		}
		if(tsr&0x02)//捕获1发生捕获事件
		{	
			if(TIM3CH1_CAPTURE_STA&0X40)		//捕获到一个下降沿 		
			{	  			
				TIM3CH1_CAPTURE_STA|=0X80;		//标记成功捕获到一次高电平脉宽
			    TIM3CH1_CAPTURE_VAL=TIM3->CCR1;	//获取当前的捕获值.
	 			TIM3->CCER&=~(1<<1);			//CC1P=0 设置为上升沿捕获
			}else  								//还未开始,第一次捕获上升沿
			{
				TIM3CH1_CAPTURE_STA=0;			//清空
				TIM3CH1_CAPTURE_VAL=0;
				TIM3CH1_CAPTURE_STA|=0X40;		//标记捕获到了上升沿
				TIM3->CR1&=~(1<<0)		;    	//使能定时器2
	 			TIM3->CNT=0;					//计数器清空
	 			TIM3->CCER|=1<<1; 				//CC1P=1 设置为下降沿捕获
				TIM3->CR1|=0x01;    			//使能定时器2
			}		    
		}			     	    					   
 	}
	TIM3->SR=0;//清除中断标志位   
}
u16 HCER_04_Get_Length()
{
	u16 temp=0;
	u16 length;
	u16 sum=0;
	u8 i=1;
	u16 result;
	while(i<4)
	{
		GPIOA->ODR|=1<<7;         //PA4输出一个高电平
		delay_us(20);
		GPIOA->ODR&=~(1<<7);      //PA4电平拉低
		if(TIM3CH1_CAPTURE_STA&0X80)//成功捕获到了一次高电平
		{
			temp=TIM3CH1_CAPTURE_STA&0X3F; 
			temp*=0XFFFF;		 		//溢出时间总和
			temp+=TIM3CH1_CAPTURE_VAL;		//得到总的高电平时间
			length=temp*0.017;
			/*均值滤波*/
			sum+=length;	
			if(i==3)
				result=sum/3;	
			i++;		
			TIM3CH1_CAPTURE_STA=0;			//开启下一次捕获			
		}
	}
	return result;
}


舵机的驱动:

        使用循环+延时翻转电平的方式控制,舵机的代码里加入了HC-SR04的调用,用来测距,遇到障碍后小车停车,左右循找距离远的方向

#ifndef __SERVO_H
#define __SERVO_H

#include "sys.h"

#define SERVO  PBout(5)


void Servo_Init(void);
u8 Servo_Find(void);
void Servo_Run(void);


#endif
#include "servo.h"
#include "delay.h"
#include "hcsr04.h"
#include "usart.h"
#include "motor.h"


void Servo_Init(void)
{
	RCC->APB2ENR|=1<<3;    	//使能PORTB时钟	
	GPIOB->CRL&=0XFF0FFFFF;	//PB5输出
	GPIOB->CRL|=0X00300000;	//复用功能输出 
	SERVO=0;
}


//ROL 1 向左走,ROL 0 向右走,ROL 2 后退
u8 Servo_Find(void)
{
	int i,j;
	u16 RightLength=999,LeftLength=999,temp;
	u8 ROL;
	for(i=0;i<30;i++)
	  {
		  SERVO=1;
		  delay_us(1600);
		  SERVO=0;
		  delay_us(18400);
	  }
	  //测距
	  delay_ms(100);	  
	for(j=0;j<5;j++)
	 {
		 temp=HCER_04_Get_Length();
		if(temp<=RightLength)
			RightLength=temp;		
	 }
	for(i=0;i<30;i++)
	  {
		  SERVO=1;
		  delay_us(2050);
		  SERVO=0;
		  delay_us(17950);
	  }
	for(i=0;i<30;i++)
	  {
		  SERVO=1;
		  delay_us(2400);
		  SERVO=0;
		  delay_us(17600);
	  }
	  //测距
	  delay_ms(100);
	  for(j=0;j<5;j++)
	  {
		  temp=HCER_04_Get_Length();
		if(temp<=LeftLength)
			LeftLength=temp;		
	  }
	for(i=0;i<30;i++)
	  {
		  SERVO=1;
		  delay_us(2050);
		  SERVO=0;
		  delay_us(17950);
	  }
	  if(RightLength>=30&&RightLength>=LeftLength)
		  return 0;
	  else if(LeftLength>=30&&LeftLength>=RightLength)
		  return 1;
	  else
		  return 2;
	  
}
u8 flag=1;
void Servo_Run(void)
{
	u8 i,ROL;
	u16 FrontLength;
	//舵机回中
	if(flag==1)
	{
		for(i=0;i<30;i++)
	  {
		  SERVO=1;
		  delay_us(2050);
		  SERVO=0;
		  delay_us(17950);
	  }
	  flag=0;
  }
	 FrontLength=HCER_04_Get_Length();
	  if(FrontLength<=30)
	  {
		  flag=1;
		  Motor_Stop();
		  ROL=Servo_Find();
		  if(ROL==0)
		  {
			  //Motor_Stop();
			  Motor_Right1(700);
		  }
		  else if(ROL==1)
		  {
			  //Motor_Stop();
			 Motor_Left1(700);
		  }
		  else if(ROL==2)
		  {
			  Motor_Stop();
		  }		  
	  }
}

按键驱动:

#ifndef __KEY_H
#define __KEY_H	 
#include "sys.h"


#define KEY0_PRES	1		//KEY0按下
#define KEY1_PRES	2		//KEY1按下
#define KEY2_PRES	3		//KEY2按下
#define KEY_ERROR   5       //按键出错

#define KEY0  PBin(6)   	//PB6
#define KEY1  PBin(7)	 	//PB7
#define KEY2  PBin(8)	 	//PB8
	 
void KEY_Init(void);		//IO初始化
u8 KEY_Scan(u8 mode);		//按键扫描函数
//u8 KEY_UP();    //按键松开

#endif
#include "key.h"
#include "delay.h"
   
//按键初始化函数 
void KEY_Init(void)
{
	RCC->APB2ENR|=1<<3;     //使能PORTB时钟
	JTAG_Set(SWD_ENABLE);	//关闭JTAG,开启SWD
	GPIOB->CRL&=0x00FFFFFF;	//PB6、7设置成输入	  
	GPIOB->CRL|=0X88000000;   
	GPIOB->CRH&=0XFFFFFFF0;	//PB8设置成输入	  
	GPIOB->CRH|=0X00000008; 			 
} 
//按键处理函数
//返回按下的按键值
//mode:0,不支持连续按;1,支持连续按;
//返回值:
//0,没有任何按键按下
//KEY_ERROR,有多个按键按下
//KEY0_PRES,KEY0按下
//KEY1_PRES,KEY1按下
//WKUP_PRES,WK_UP按下 
//注意此函数有响应优先级,KEY0>KEY1>KEY2!!
u8 KEY_Scan(u8 mode)
{	 
	static u8 key_up=1;//按键按松开标志
	if(mode)key_up=1;  //支持连按		  
	if(key_up&&(KEY0==1||KEY1==1||KEY2==1))
	{
		delay_ms(10);//去抖动 
		key_up=0;
		if(KEY0==1&&KEY1==0&&KEY2==0)return KEY0_PRES;
		else if(KEY0==0&&KEY1==1&&KEY2==0)return KEY1_PRES;
		else if(KEY0==0&&KEY1==0&&KEY2==1)return KEY2_PRES; 
		else  return KEY_ERROR;
	}else if(KEY0==0&&KEY1==0&&KEY2==0)key_up=1; 	     
	return 0;// 无按键按下
}

蜂鸣器的驱动:

        俩种发声模式,分别用于选择模式以及模式选择错误时(多个按键被按下)

#ifndef __BEEP_H
#define __BEEP_H
#include "sys.h"

#define BEEP PBout(9)

void BEEP_Init(void);
void BEEP_Mode1(void);  //两声短鸣
void BEEP_Mode2(void);	//两声长鸣

#endif

#include "beep.h"
#include "delay.h"

void BEEP_Init(void)
{
	RCC->APB2ENR|=1<<3;			//使能A口时钟
	GPIOB->CRH&=0xFFFFFF0F;
	GPIOB->CRH|=0x0000003F;		//PA9输出
	BEEP=0;		
}


//用于模式选择后的提示
void BEEP_Mode1(void)
{
	BEEP=1;
	delay_ms(300);
	BEEP=0;
	delay_ms(70);
	BEEP=1;
	delay_ms(300);
	BEEP=0;
}


//模式选择错误时
void BEEP_Mode2(void)
{
	BEEP=1;
	delay_ms(1000);
	BEEP=0;
	delay_ms(100);
	BEEP=1;
	delay_ms(1000);
	BEEP=0;
}

USART3(蓝牙)驱动:

#ifndef __USART3_H
#define __USART3_H
#include "sys.h"
#include "stdio.h"

#define USART_REC_LEN  			200  	//定义最大接收字节数 200
#define EN_USART3_RX 			1		//使能(1)/禁止(0)串口1接收
	  	
extern u8  USART3_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern u16 USART3_RX_STA;         		//接收状态标记	
//如果想串口中断接收,请不要注释以下宏定义
void uart3_init(u32 pclk2,u32 bound);

#endif	   
#include "usart3.h"	 
#include "Data_struct.h"
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "motor.h"


u8 BTFlag;
#if EN_USART3_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART3_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART3_RX_STA=0;       //接收状态标记	  
  
void USART3_IRQHandler(void)
{
	char res;	
	//delay_ms(50);
	if(USART3->SR&(1<<5))	//接收到数据
	{	
		//delay_ms(10);		
		res=USART3->DR;
		printf("\r\n%d",res);		
		if(res ==255)
		{	
			Motor_Forward(0);
			printf("\r\nGo Stright");
		}
		else if(res==254)	
		{
			Motor_Back();
			printf("\r\nGo Back");
		}
		else if(res== 248)
		{
			Motor_Left1(300);
			printf("\r\nTurn Left");			
		}
		else if(res==232)
		{
			Motor_Right1(300);
			printf("\r\nTurn Right");
		}
		else if(res==200)
		{
			Motor_Stop();
			printf("\r\nStop");
		}
	}
} 
#endif		


//初始化IO 串口3
//pclk2:PCLK2时钟频率(Mhz)
//bound:波特率 
void uart3_init(u32 pclk2,u32 bound)
{  	 
	float temp;
	u16 mantissa;
	u16 fraction;	   
	temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
	mantissa=temp;				 //得到整数部分
	fraction=(temp-mantissa)*16; //得到小数部分	 
    mantissa<<=4;
	mantissa+=fraction; 
	RCC->APB2ENR|=1<<3;   //使能PORTB口时钟  
	RCC->APB1ENR|=1<<18;  //使能串口3时钟 
	GPIOB->CRH&=0XFFFF00FF;//IO状态设置
	GPIOB->CRH|=0X00008B00;//IO状态设置 
		  
	RCC->APB2RSTR|=1<<18;   //复位串口3
	RCC->APB2RSTR&=~(1<<18);//停止复位	 
	
	//波特率设置
 	USART3->BRR=mantissa; // 波特率设置	 
	USART3->CR1|=0X200C;  //1位停止,无校验位.
//#if EN_USART1_RX		  //如果使能了接收
	//使能接收中断
	//USART3->CR1|=1<<8;    //PE中断使能
	USART3->CR1|=1<<5;    //接收缓冲区非空中断使能	
	USART3_RX_STA=0;	
	MY_NVIC_Init(3,3,USART3_IRQn,2);//组2,最低优先级 
//#endif
}

主程序:

#include "main.h"
#include "motor.h"
#include "exti.h"
#include "beep.h"
#include "key.h"
#include "led.h"
#include "usart.h"
#include "hcsr04.h"
#include "servo.h"
#include "usart3.h"



*/
extern u8 Tracing_Right;
extern u8 Tracing_Left;
extern u8 Flag;
void System_Init(void)
{
	Stm32_Clock_Init(9);					  //初始化系统时钟		
	delay_init(72);		
	uart_init(72,9600);	//初始化延时	
	HCSR_04_TIM3_Init(0xFFFF,36-1);
	MOTOR1_PWM_Init(1000-1,360-1);
	MOTOR2_PWM_Init(1000-1,360-1);
	uart3_init(72,9600);
	Servo_Init();
	EXTI_Init();
	BEEP_Init();
	KEY_Init();
	LED_Init();
	BEEP=0;
	//关中断
		EXTI->IMR&=~(1<<0);     
		EXTI->IMR&=~(1<<4); 
}
int main(void)
{	
	u8 key=0,SROL,flag1=0,flag2=0,flag3=0;
	System_Init();
	Motor_Stop();
	while(1)
	{		
		key=KEY_Scan(0);
		if(key==KEY_ERROR)
		{
			Motor_Stop();
			BEEP_Mode2();
			delay_ms(100);
		}
		//寻迹
		else if(key==KEY0_PRES)
		{
				BEEP_Mode1();
				EXTI->IMR|=1<<0;
				EXTI->IMR|=1<<4;
				//关蓝牙中断
				USART3->CR1&=~(1<<5);  
				delay_ms(2000);
				flag1++;
			while(1)
			{
				if(Tracing_Right==1)
				{
					Tracing_Left=0;					
				}
				else if(Tracing_Left==1)
				{
					Tracing_Right=0;					
				}
				else
				{
					Motor_Forward(LOW_SPEED);
				}
				REDLED=!REDLED;
			}
	    }
		
		//避障碍
		else if(key==KEY1_PRES)
		{			
				BEEP_Mode1();
				//关寻迹中断
				EXTI->IMR&=~(1<<0);     
				EXTI->IMR&=~(1<<4); 
				//关蓝牙中断
				USART3->CR1&=~(1<<5);  
				Motor_Forward(LOW_SPEED);
			while(1)
			{
				Servo_Run();
				Motor_Forward(LOW_SPEED);
			}
		}
		
		//蓝牙
		else if(key==KEY2_PRES)
		{
				BEEP_Mode1();
				//关寻迹中断
				EXTI->IMR&=~(1<<0);     
				EXTI->IMR&=~(1<<4); 
				USART3->CR1|=1<<5;    //接收缓冲区非空中断使能
		}
    }
}

小车的效果视频:链接点我







猜你喜欢

转载自blog.csdn.net/a568713197/article/details/80869200