PWM.c、Motor.c已发
Track.c
五路循迹
#include "stm32f10x.h" // Device header
#include "Motor.h"
//红外从左到右
#define DET1 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12)
#define DET2 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11)
#define DET3 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10)
#define DET4 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9)
#define DET5 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8)
uint16_t Flag=0;//此标志位仅服务于直角转弯
/*循迹初始化*/
void Track_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
}
//0检测到黑线
void Track()
{
/*注:以下代码每行前面注释的是实际上系统的值,后面注释的的是人为反转的0为黑线*/
if(Flag==0)
{
/*00100*/ if(!DET1 && !DET2 && DET3 && !DET4 && !DET5) {Car_Run();}//11011
///*01110*/ if(!DET1 && DET2 && DET3 && DET4 && !DET5) {Car_Run();}//10001
///*11111*/ if(DET1 && DET2 && DET3 && DET4 && DET5) {Car_Stop();}//00000
/*01000*/ if(!DET1 && DET2 && !DET3 && !DET4 && !DET5) {Car_L_Slow();}//10111
/*01100*/ if(!DET1 && DET2 && DET3 && !DET4 && !DET5) {Car_L_Slow();}//10011
/*10000*/ if(DET1 && !DET2 && !DET3 && !DET4 && !DET5) {Car_Left();}//01111
/*11000*/ if(DET1 && DET2 && !DET3 && !DET4 && !DET5) {Car_Left();}//00111
/*11100*/ if(DET1 && DET2 && DET3 && !DET4 && !DET5) {Angle_Left();Flag=1;}//00011 直角左转
///*11110*/ if(DET1 && DET2 && DET3 && DET4 && !DET5) {Angle_Left();}//00001
/*00010*/ if(!DET1 && !DET2 && !DET3 && DET4 && !DET5) {Car_R_Slow();}//11101
/*00110*/ if(!DET1 && !DET2 && DET3 && DET4 && !DET5) {Car_R_Slow();}//11001
/*00001*/ if(!DET1 && !DET2 && !DET3 && !DET4 && DET5) {Car_Right();}//11110
/*00011*/ if(!DET1 && !DET2 &&!DET3 && DET4 && DET5) {Car_Right();}//11100
/*00111*/ if(!DET1 && !DET2 && DET3 && DET4 && DET5) {Angle_Right();Flag=2;}//11000 直角右转
///*01111*/ if(!DET1 && DET2 && DET3 && DET4 && DET5) {Angle_Right();}//10000
/*00000*/ if(!DET1 && !DET2 && !DET3 && !DET4 && !DET5){Car_Run();}//11111
}
/*以下代码时当检测到该直角转弯时再执行*/
/*我将直角转弯分成了一个函数,可以使转向更稳定*/
else if(Flag==1)//左
{
Angle_Left();
if((!DET1 && !DET2 && !DET3 && !DET4 && DET5)||
(!DET1 && !DET2 &&!DET3 && DET4 && DET5) ||
(!DET1 && !DET2 && DET3 && !DET4 && !DET5)
)//11110||11100||11011转正
{
Flag=0;
}
}
else if(Flag==2)//右
{
Angle_Right();
if((DET1 && !DET2 && !DET3 && !DET4 && !DET5)||
(DET1 && DET2 && !DET3 && !DET4 && !DET5) ||
(!DET1 && !DET2 && DET3 && !DET4 && !DET5)
)//01111||00111||11011转正
{
Flag=0;
}
}
}
SR04.c
注:我用的定时器1计时,用外部中断EXTI来控制定时什么是开始或结束计时,并且计算距离。
因为障碍物是随机出现的,外部中断可以随时响应并且没有固定时间什么时候才可以进中断,而定时器的中断是人为设定的时间,只能固定时间才会进中断计算距离
提醒!
VCC 接5V!!!
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Timer1.h"
#define Trig GPIO_Pin_6
#define Echo GPIO_Pin_5
float Num=0;
int i=0,Counter=0,Sum=0,Dec=0,CNT_Mean=0,CN1=0,CN2=0;
// Device header
void SR04_Init(void )
{
//打开发射端Trig
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//通用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
GPIO_Init(GPIOB,&GPIO_InitStructure);
//打开接收端Echo
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure1;
GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOB, &GPIO_InitStructure1);
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
//配置中断线,Echo接收时进中断
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource5);// 配置GPIOB,选择第五个引脚作为中断源
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line5;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;// 设置为中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿触发中断
EXTI_Init(&EXTI_InitStructure);// 应用配置到EXTI
//NVIC中断优先级配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
NVIC_Init(&NVIC_InitStructure);
}
void SR04_Start(void)//发射
{
GPIO_SetBits(GPIOB,GPIO_Pin_6);
Delay_us(15);
GPIO_ResetBits(GPIOB,GPIO_Pin_6);
}
/*中断函数*/
//在接收到返回的声波时(Echo)才进入,并开始计时
void EXTI9_5_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line5) != RESET)
{
//LED1_ON();
Timer_ON();
CN1 = TIM_GetCounter(TIM1);
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5));
//声波是一段距离,一直有Echo就一直检测为高电平且一直计时,直到一次的信号结束Echo才变低电平,然后执行后续代码
CN2 = TIM_GetCounter(TIM1);
Timer_OFF();
Counter = CN2 - CN1;
EXTI_ClearITPendingBit(EXTI_Line5);
//LED1_OFF();
}
}
float Get_Distant()
{
SR04_Start();
Num=Counter*0.017;//b/5 * 17/1000
return Num;
}
/*注:这个公式适用于从Echo检测到返回的声波时才开始计时的方法。
还有一种是从Trig发射声波时就开始计时,那就用到另一个公式*/
Timer1.c
定时器1配置
#include "stm32f10x.h" // Device header
void Timer_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//????
TIM_TimeBaseInitStructure.TIM_Period = 65535;//ARR
TIM_TimeBaseInitStructure.TIM_Prescaler=72-1;//????
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//CNT??ARR????
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStructure);
TIM_SetCounter(TIM1,0);
//定时器1会清除其当前值(如果之前有计数值),并从0开始计数
}
void Timer_ON(void)
{
TIM_Cmd(TIM1,ENABLE);
}
void Timer_OFF(void)
{
TIM_Cmd(TIM1,DISABLE);
}