• 欢迎访问开心洋葱网站,在线教程,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站,欢迎加入开心洋葱 QQ群
  • 为方便开心洋葱网用户,开心洋葱官网已经开启复制功能!
  • 欢迎访问开心洋葱网站,手机也能访问哦~欢迎加入开心洋葱多维思维学习平台 QQ群
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏开心洋葱吧~~~~~~~~~~~~~!
  • 由于近期流量激增,小站的ECS没能经的起亲们的访问,本站依然没有盈利,如果各位看如果觉着文字不错,还请看官给小站打个赏~~~~~~~~~~~~~!

基于STM32F103的红外循迹避障小车设计(含Proteus仿真)

人工智能 鲁棒最小二乘支持向量机 2577次浏览 0个评论

基于STM32F103的红外循迹避障小车设计

红外循迹及红外避障实现较简单,无论是51单片机还是STM32单片机,其例程随处可见。但是完全可以运行的Proteus仿真,开源的并不多,更不要说基于STM32单片机的仿真。
下面跟大家聊聊基于STM32F103的红外循迹避障小车的Proteus仿真。

首先,我们来验证一下,Proteus软件能否对STM32进行仿真。

我所使用的是Proteus8.6版本,我们可以看到STM32芯片有以下几款:

在这里插入图片描述

我选用STM32F103R6芯片,进行点灯仿真,从而证明Proteus可以对STM32进行仿真实验。

在这里插入图片描述

可以看到运行之后,LED灯被点亮。

在这里插入图片描述

此部分程序(即STM32点亮LED)如下:

#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 ();          // 灭       
        */
    }
}

下面开始红外循迹及避障的Proteus仿真:

红外循迹模块,选用此款,使用简单,价格便宜

在这里插入图片描述

其工作原理我不再赘述,其原理图如下图:

在这里插入图片描述

红外避障模块,对比之后,发现红外避障效果最好的,就是这款红外模块。

在这里插入图片描述

电机驱动模块,选择L298电机驱动,此驱动较常用,使用也较简单。

在这里插入图片描述

 其原理图如下:

在这里插入图片描述STM32单片机选择STM32F103C8T6,只需要买此小核心板即可,经济实惠。

在这里插入图片描述

单片机最小系统原理图:

在这里插入图片描述

电源部分原理图如下:

在这里插入图片描述

Proteus红外模块的仿真,只能用按键模拟,即单片机引脚检测0、1信号。

完整Proteus仿真图如下:

点击运行 

在这里插入图片描述

大家可以看到,程序跑不动,显示在运行,但是程序无法正常循环

在这里插入图片描述

实践证明,Proteus仿真STM32只能进行简单的仿真,无法进行复杂仿真。不过仿真51单片机是完全没有问题的。

所以,我的建议,直接做实物,最终实物调试成功,没有任何问题

来张实物图片

在这里插入图片描述

部分程序如下,可参考

主程序

#include "stm32f10x.h"
#include "bsp_SysTick.h"
#include "bsp_led.h"
#include
#include
#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);//直行
        }
    }

}

 


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

 
延时程序


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

涉及到STM32的设计,Proteus软件暂时无法进行完全的仿真,建议直接设计实物,调试实物代替仿真

分享决定高度,学习拉开差距

作为学习者给大家分享自己完成的此作品,希望对大家有帮助,当然上文若有不妥之处,欢迎指正。

欢迎大家留言,批评指正!


开心洋葱 , 版权所有丨如未注明 , 均为原创丨未经授权请勿修改 , 转载请注明基于STM32F103的红外循迹避障小车设计(含Proteus仿真)
喜欢 (0)

您必须 登录 才能发表评论!

加载中……