Diseño de coche de seguimiento por infrarrojos y evitación de obstáculos basado en STM32F103 (incluida la simulación de Proteus)

Diseño de coche de seguimiento por infrarrojos y evitación de obstáculos basado en STM32F103

La realización del seguimiento por infrarrojos y la evitación de obstáculos por infrarrojos es relativamente simple, ya sea 51 de un solo chip o STM32 de un solo chip, sus rutinas se pueden ver en todas partes. Pero no hay muchas simulaciones de Proteus de código abierto que se puedan ejecutar, y mucho menos simulaciones basadas en el microcontrolador STM32.
Vamos a hablar con usted sobre la simulación de Proteus del coche de seguimiento por infrarrojos y evitación de obstáculos basado en STM32F103.

En primer lugar, verifiquemos que el software Proteus pueda simular STM32.

Estoy usando la versión Proteus8.6, podemos ver los siguientes chips STM32:

Inserte la descripción de la imagen aquí

Elegí el chip STM32F103R6 para la simulación de iluminación para demostrar que Proteus puede realizar experimentos de simulación en STM32.

Inserte la descripción de la imagen aquí

Se puede ver que después de correr, la luz LED se enciende.

Inserte la descripción de la imagen aquí

Esta parte del programa (es decir, STM32 enciende el LED) es la siguiente:
#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_key.h"



static void Delay(__IO uint32_t nCount)	 //简单的延时函数
{
    
    
	for(; nCount != 0; nCount--);
}



/**
  * @brief  主函数
  * @param  无  
  * @retval 无
  */
int main ( void )
{
    
    	
	LED_Init ();	//初始化 LED
	Key_GPIO_Config();
  macLED1_OFF ();
  macLED2_OFF ();
	macLED3_OFF ();
	
	while ( 1 )
	{
    
    
		if( Key_Scan(macKEY1_GPIO_PORT,macKEY1_GPIO_PIN) == KEY_ON  )
		
		{
    
    
			/*LED1反转*/
			  macLED1_TOGGLE() ;
				macLED2_TOGGLE() ;
				macLED3_TOGGLE() ;
				 //return main();
		}   
		
			
	/*	macLED1_ON ();			  // 亮 此处为流水灯程序
		Delay ( 22100 );
		macLED1_OFF ();		  // 灭

		macLED2_ON ();			  // 亮
		Delay ( 22100 );
		macLED2_OFF ();		  // 灭

		macLED3_ON ();			  // 亮
		Delay ( 22100 );
		macLED3_OFF ();		  // 灭	   
		*/
	}

}

Ahora inicie la simulación Proteus de seguimiento por infrarrojos y evitación de obstáculos:

Módulo de seguimiento por infrarrojos, elija este modelo, fácil de usar y económico

Inserte la descripción de la imagen aquí

No entraré en detalles sobre su principio de funcionamiento, su diagrama esquemático es el siguiente:

Inserte la descripción de la imagen aquí

Módulo de evitación de obstáculos por infrarrojos, después de la comparación, se encuentra que este módulo de infrarrojos tiene el mejor efecto de evitación de obstáculos por infrarrojos.

Inserte la descripción de la imagen aquí

Módulo de unidad de motor, elija la unidad de motor L298, esta unidad se usa más comúnmente y es fácil de usar.

Inserte la descripción de la imagen aquí

El diagrama esquemático es el siguiente:

Inserte la descripción de la imagen aquí

STM32 MCU elige STM32F103C8T6, solo necesita comprar esta placa de núcleo pequeño, económica.

Inserte la descripción de la imagen aquí

El diagrama esquemático del sistema más pequeño del microordenador de un solo chip:

Inserte la descripción de la imagen aquí

El diagrama esquemático de la fuente de alimentación es el siguiente:

Inserte la descripción de la imagen aquí

La simulación del módulo de infrarrojos Proteus solo se puede simular mediante botones, es decir, los pines del microcontrolador detectan las señales 0 y 1.

El diagrama de simulación completo de Proteus es el siguiente:

Inserte la descripción de la imagen aquí

Haga clic para ejecutar

Inserte la descripción de la imagen aquí

Como puede ver, el programa no se puede ejecutar, muestra que se está ejecutando, pero el programa no puede repetirse normalmente.

Inserte la descripción de la imagen aquí

La práctica ha demostrado que la simulación de Proteus STM32 solo puede realizar simulaciones simples, pero no puede realizar simulaciones complejas. Sin embargo, la simulación de 51 microcomputadoras de un solo chip no supone ningún problema.
Por lo tanto, mi sugerencia es hacer directamente el objeto físico, y finalmente el objeto físico se depura con éxito sin ningún problema.

Ven a una imagen real

Inserte la descripción de la imagen aquí

Parte del procedimiento es el siguiente, como referencia.

Programa principal

#include "stm32f10x.h"
#include "bsp_SysTick.h"
#include "bsp_led.h"
#include <string.h>
#include <stdlib.h>
#include "bsp_pwm_output.h" 
#include "infrared.h" 
#include "delay.h"
//全局变量
unsigned int Task_Delay[NumOfTask];

/**
  * @brief  主函数
  * @param  无
  * @retval 无
  */
int main(void)
{
    
    	
	
	  //初始化systick
	SysTick_Init();											//用于延时等操作
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;
	TIMx_PWM_Init();			//PWM波初始化
  infrared_Initial();		//红外初始化
	while(1)
	{
    
    
		if((infrared_Scan(infrared_5_GPIO_PORT,infrared_5_GPIO_PIN)==INFRARED_ON)&&\
			(infrared_Scan(infrared_6_GPIO_PORT,infrared_6_GPIO_PIN)==INFRARED_ON))//前方有障碍,必须两边同时检测到才能触发,否则均认为是误触
		{
    
    		
			DelayS(3);		//延迟3秒
			if((infrared_Scan(infrared_5_GPIO_PORT,infrared_5_GPIO_PIN)==INFRARED_ON)&&\
			(infrared_Scan(infrared_6_GPIO_PORT,infrared_6_GPIO_PIN)==INFRARED_ON))//仍旧有障碍
			{
    
    
					TIMx_Mode_Config(500,0,0,500);//右转500ms
		  		DelayMs(500);
				
			}
			else
			{
    
    
			     TIMx_Mode_Config(500,0,0,500);//直行500ms
					 DelayMs(500);
			}
			
		}
		else
		{
    
    
			if((infrared_Scan(infrared_3_GPIO_PORT,infrared_3_GPIO_PIN)==INFRARED_ON))//循迹,右侧内部传感器见到黑线,说明车身方向偏右
			    TIMx_Mode_Config(0,0,600,0);//轻微左转
			else if((infrared_Scan(infrared_2_GPIO_PORT,infrared_2_GPIO_PIN)==INFRARED_ON))//循迹,左侧内部传感器见到黑线,说明车身方向偏左
			    TIMx_Mode_Config(600,0,0,0);//轻微右转
			else if((infrared_Scan(infrared_4_GPIO_PORT,infrared_4_GPIO_PIN)==INFRARED_ON))//循迹,右侧外部传感器见到黑线,说明车身方向偏左
			    TIMx_Mode_Config(0,0,900,0);//剧烈左转
			else if((infrared_Scan(infrared_1_GPIO_PORT,infrared_1_GPIO_PIN)==INFRARED_ON))//循迹,左侧外部传感器见到黑线,说明车身方向偏左
			    TIMx_Mode_Config(900,0,0,0);//剧烈右转
			else
				 TIMx_Mode_Config(500,0,500,0);//直行
		}
	}

}

Programa de ondas PWM

#include "bsp_pwm_output.h" 

 /**
  * @brief  配置TIM3复用输出PWM时用到的I/O
  * @param  无
  * @retval 无
  */
static void TIMx_GPIO_Config(void) 
{
    
    
  GPIO_InitTypeDef GPIO_InitStructure;

	/* 设置TIM3CLK 为 72MHZ */
//  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); 
	macTIM_APBxClock_FUN (macTIM_CLK, ENABLE);

  /* GPIOA and GPIOB clock enable */
  macTIM_GPIO_APBxClock_FUN (macTIM_GPIO_CLK, ENABLE); 

  /*GPIOA Configuration: TIM3 channel 1 as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin =  macTIM_CH1_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;		    // 复用推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(macTIM_CH1_PORT, &GPIO_InitStructure);

  /*GPIOB Configuration: TIM3 channel 2 as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin =  macTIM_CH2_PIN;
  GPIO_Init(macTIM_CH2_PORT, &GPIO_InitStructure);

  /*GPIOB Configuration: TIM3 channel 3 as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin =  macTIM_CH3_PIN;
  GPIO_Init(macTIM_CH3_PORT, &GPIO_InitStructure);
	
  /*GPIOB Configuration: TIM3 channel 4 as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin =  macTIM_CH4_PIN;
  GPIO_Init(macTIM_CH4_PORT, &GPIO_InitStructure);
	
}

/**
  * @brief  配置TIM3输出的PWM信号的模式,如周期、极性、占空比
  * @param  无
  * @retval 无
  */
/*
 * TIMxCLK/CK_PSC --> TIMxCNT --> TIMx_ARR --> TIMxCNT 重新计数
 *                    TIMx_CCR(电平发生变化)
 * 信号周期=(TIMx_ARR +1 ) * 时钟周期
 * 占空比=TIMx_CCR/(TIMx_ARR +1)
 */
void TIMx_Mode_Config(u16 CCR1_Val,u16 CCR2_Val,u16 CCR3_Val, u16 CCR4_Val)
{
    
    
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;


/* ----------------------------------------------------------------------- 
    macTIMx Channel1 duty cycle = (macTIMx_CCR1/ macTIMx_ARR+1)* 100% = 50%
    macTIMx Channel2 duty cycle = (macTIMx_CCR2/ macTIMx_ARR+1)* 100% = 37.5%
    macTIMx Channel3 duty cycle = (macTIMx_CCR3/ macTIMx_ARR+1)* 100% = 25%
    macTIMx Channel4 duty cycle = (macTIMx_CCR4/ macTIMx_ARR+1)* 100% = 12.5%
  ----------------------------------------------------------------------- */

  /* Time base configuration */		 
  TIM_TimeBaseStructure.TIM_Period = 999;       //当定时器从0计数到999,即为1000次,为一个定时周期
  TIM_TimeBaseStructure.TIM_Prescaler = 0;	    //设置预分频:不预分频,即为72MHz
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;	//设置时钟分频系数:不分频(这里用不到)
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //向上计数模式
  TIM_TimeBaseInit(macTIMx, &TIM_TimeBaseStructure);

  /* PWM1 Mode configuration: Channel1 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;	    //配置为PWM模式1
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	
  TIM_OCInitStructure.TIM_Pulse = CCR1_Val;	   //设置跳变值,当计数器计数到这个值时,电平发生跳变
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  //当定时器计数值小于CCR1_Val时为高电平
  TIM_OC1Init(macTIMx, &TIM_OCInitStructure);	 //使能通道1
  TIM_OC1PreloadConfig(macTIMx, TIM_OCPreload_Enable);

  /* PWM1 Mode configuration: Channel2 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR2_Val;	  //设置通道2的电平跳变值,输出另外一个占空比的PWM
  TIM_OC2Init(macTIMx, &TIM_OCInitStructure);	  //使能通道2
  TIM_OC2PreloadConfig(macTIMx, TIM_OCPreload_Enable);

  /* PWM1 Mode configuration: Channel3 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR3_Val;	//设置通道3的电平跳变值,输出另外一个占空比的PWM
  TIM_OC3Init(macTIMx, &TIM_OCInitStructure);	 //使能通道3
  TIM_OC3PreloadConfig(macTIMx, TIM_OCPreload_Enable);

  /* PWM1 Mode configuration: Channel4 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR4_Val;	//设置通道4的电平跳变值,输出另外一个占空比的PWM
  TIM_OC4Init(macTIMx, &TIM_OCInitStructure);	//使能通道4
  TIM_OC4PreloadConfig(macTIMx, TIM_OCPreload_Enable);
  TIM_ARRPreloadConfig(macTIMx, ENABLE);			 // 使能TIM3重载寄存器ARR

  /* TIM3 enable counter */
  TIM_Cmd(macTIMx, ENABLE);                   //使能定时器3	
}

/**
  * @brief  TIM3 输出PWM信号初始化,只要调用这个函数
  *         TIM3的四个通道就会有PWM信号输出
  * @param  无
  * @retval 无
  */
void TIMx_PWM_Init(void)
{
    
    
	TIMx_GPIO_Config();
	TIMx_Mode_Config(0,0,0,0);	
}

Programa de retraso

#include "stm32f10x.h"
#include "delay.h"

static u8  fac_us=0;//us延时倍乘数
static u16 fac_ms=0;//ms延时倍乘数

//初始化延迟函数
//当使用ucos的时候,此函数会初始化ucos的时钟节拍
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void DelayInit()
{
    
    
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	//选择外部时钟  HCLK/8
	fac_us=SystemCoreClock/8000000;	//为系统时钟的1/8  
	fac_ms=(u16)fac_us*1000;//非ucos下,代表每个ms需要的systick时钟数   
}

//延时nus
//nus为要延时的us数.		    								   
void DelayUs(unsigned long nus)
{
    
    		
	u32 temp;	    	 
	SysTick->LOAD=nus*fac_us; //时间加载	  		 
	SysTick->VAL=0x00;        //清空计数器
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;          //开始倒数	 
	do
	{
    
    
		temp=SysTick->CTRL;
	}
	while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;       //关闭计数器
	SysTick->VAL =0X00;       //清空计数器	 
}
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864 
void DelayMs(unsigned int nms)
{
    
    
	u32 temp;
	SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)
	SysTick->VAL =0x00;           //清空计数器
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;          //开始倒数  
	do
	{
    
    
		temp=SysTick->CTRL;
	}
	while(temp&0x01&&!(temp&(1<<16)));//等待时间到达
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;       //关闭计数器
	SysTick->VAL =0X00;       //清空计数器
}

void DelayS(unsigned int ns)//延时秒
{
    
    
	unsigned char i;
	for(i=0;i<ns;i++)
	{
    
    
		DelayMs(1000);
	}
}

Cuando se trata del diseño de STM32, el software Proteus temporalmente no puede realizar una simulación completa. Se recomienda diseñar el objeto físico directamente y depurar el objeto físico en lugar de la simulación.

Compartiendo alturas de decisión, aprendiendo a abrir la brecha

Como alumno, me gustaría compartir este trabajo que he completado con usted. Espero que sea de ayuda para todos. Por supuesto, si hay algún problema con lo anterior, corríjame.

¡Bienvenidos todos a dejar un mensaje, criticar y corregir!

Supongo que te gusta

Origin blog.csdn.net/qq_42078934/article/details/105535767
Recomendado
Clasificación