STM32F1编写简单的五路黑白循迹 您所在的位置:网站首页 循迹小车代码流程图 STM32F1编写简单的五路黑白循迹

STM32F1编写简单的五路黑白循迹

2023-09-09 07:12| 来源: 网络整理| 查看: 265

STM32F1编写简单的五路黑白循迹

一、小车模型设计

1)硬件搭配:四轮小车底盘、五路红外循迹传感器、L298N两路电机驱动模块、STM32F103RC最小系统板、电源、降压模块。

2)说明:这里只用到了两路电机驱动模块,是因为我将同一边的电机进行了并联;使用的电源应大于7V,才能有效的驱动小车行驶;降压模块的作用是将电压调节到适合单片机最小系统板工作的5V供电。

3)组装起来大概长这个模样 在这里插入图片描述

二、循迹程序设计

(在最后面我提供了工程文件的下载链接,大家可以下载验证)

1)需要配置的外设:五个GPIO输入口,两个定时器输出PWM波(这里只有两路也可以只配置一个定时器,因为一个定时器可以输出4路PWM波);

2)GPIO口配置(五路输入):

// 端口宏定义:

#define TRACK_PORT GPIOA//选择A端口 #define TRACK_PORT_CLK RCC_APB2Periph_GPIOA//端口A时钟 #define TRACK_INFRARED_L2_PIN GPIO_Pin_9//左2传感器对应的引脚 #define TRACK_INFRARED_L1_PIN GPIO_Pin_8//左1传感器对应的引脚 #define TRACK_INFRARED_M_PIN GPIO_Pin_7//中间传感器对应的引脚 #define TRACK_INFRARED_R1_PIN GPIO_Pin_6//右1传感器对应的引脚 #define TRACK_INFRARED_R2_PIN GPIO_Pin_5//右2传感器对应的引脚

// 端口模式配置函数:

void Track_Init(void)//循迹端口初始化 { GPIO_InitTypeDef GPIO_InitStructure;//GPIO结构体定义 RCC_APB2PeriphClockCmd(TRACK_PORT_CLK ,ENABLE);//打开端口时钟 GPIO_InitStructure.GPIO_Pin = TRACK_INFRARED_M_PIN | TRACK_INFRARED_L1_PIN | TRACK_INFRARED_L2_PIN | TRACK_INFRARED_R1_PIN | TRACK_INFRARED_R2_PIN;//配置传感器读取引脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//配置为输入上拉模式 GPIO_Init(TRACK_PORT,&GPIO_InitStructure);//初始化端口

3)定时器TIM配置:

//定时器配置宏定义:

void Motor_Init(void) { uint16_t PrescalerValue;//分频参数变量 GPIO_InitTypeDef GPIO_InitStruct;//GPIO配置结构体定义 TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;//TIM配置结构体定义 TIM_OCInitTypeDef TIM_OCInitStruct;//TIM输出结构体定义 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 | RCC_APB1Periph_TIM2,ENABLE);//开启TIM2、TIM3的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);//开启GPIO的时钟与端口复用时钟 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;//配置TIM3的CH3和CH4输出引脚 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//模式设定为复用模式 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;//设定引脚速率 GPIO_Init(GPIOB,&GPIO_InitStruct);//根据结构体参数初始化GPIOB GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;//配置TIM2的CH3和CH4输出引脚 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//模式设定为复用模式 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;//设定引脚速率 GPIO_Init(GPIOA,&GPIO_InitStruct);//根据结构体参数初始化GPIOA TIM_DeInit(TIM3);//复位TIM3 TIM_DeInit(TIM2);//复位TIM2 PrescalerValue = (uint16_t) (SystemCoreClock / 4000000 ) - 1;//分频系数计算 TIM_TimeBaseStruct.TIM_Period = SPEED_PERIOD;//重载寄存器的值,定时周期 TIM_TimeBaseStruct.TIM_Prescaler = PrescalerValue;//预分频 TIM_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;//时钟切割 TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数 TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStruct);//使用结构体参数初始化TIM3 TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStruct);//使用结构体参数初始化TIM2 TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//PWM模式为1 TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//使能TIM得输出 TIM_OCInitStruct.TIM_Pulse = STARTER_SPEED;//比较寄存器的值 TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//通道1的有效电平为高电平; TIM_OC3Init(TIM3,&TIM_OCInitStruct);//使用结构体参数初始化TIM3的CH3输出PWM波 TIM_OC3Init(TIM2,&TIM_OCInitStruct);//使用结构体参数初始化TIM2的CH3输出PWM波 TIM_OC4Init(TIM3,&TIM_OCInitStruct);//使用结构体参数初始化TIM3的CH4输出PWM波 TIM_OC4Init(TIM2,&TIM_OCInitStruct);//使用结构体参数初始化TIM2的CH4输出PWM波 TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable);//允许随时修改TIM3 CCR3比较寄存器的值; TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);//允许随时修改TIM3 CCR4比较寄存器的值; TIM_OC3PreloadConfig(TIM2,TIM_OCPreload_Enable);//允许随时修改TIM2 CCR3比较寄存器的值; TIM_OC4PreloadConfig(TIM2,TIM_OCPreload_Enable);//允许随时修改TIM2 CCR4比较寄存器的值; TIM_Cmd(TIM3,ENABLE);//开启TIM3 TIM_Cmd(TIM2,ENABLE);//开启TIM2 }

4)电机驱动函数:

/******* 功 能:左边电机驱动函数 形 参:cont1 配置CCR3比较寄存器的值(占空比调整) cont2 配置CCR4比较寄存器的值(占空比调整) 返回值: 无 说 明:当cont1大于0,cont2为0时,电机正转,反之则反转(这里仔细理解一下,后面函数会使用到) ******/ void Motor_L_Cont(uint16_t cont1,uint16_t cont2) { TIM3->CCR3 = cont1; TIM3->CCR4 = cont2; } /******* 功 能:右边电机驱动函数 形 参:cont1 配置CCR3比较寄存器的值(占空比调整) cont2 配置CCR4比较寄存器的值(占空比调整) 返回值: 无 说 明:当cont1大于0,cont2为0时,电机正转,反之则反转(这里仔细理解一下,后面函数会使用到) ******/ void Motor_R_Cont(uint16_t cont1,uint16_t cont2) { TIM2->CCR3 = cont1; TIM2->CCR4 = cont2; } /******* 功 能:双边电机驱动函数 形 参:L_speed 设置左电机前进的转速 R_speed 设置右电机前进的转速 返回值: 无 说 明:这里调用左电机驱动和右电机驱动函数, ******/ void Motor_Speed_Adjust(uint16_t L_speed,uint16_t R_speed) { Motor_L_Cont(L_speed,0); Motor_R_Cont(R_speed,0); } /******* 功 能:小车旋转函数(左右电机反方向转动) 形 参:fx 为1时,逆时针转动(左电机反转,右电机正转) 为0时,顺时针转动(左电机正转,右电机反转) 返回值: 无 说 明:这里使用到的STARTER_SPEED,为宏定义的初始占空参数,这里调用左电机驱动和右电机驱动函数, ******/ void Motor_Opposite(u8 fx)//旋转 { if(fx) { Motor_L_Cont(0,STARTER_SPEED); Motor_R_Cont(STARTER_SPEED,0); } else { Motor_L_Cont(STARTER_SPEED,0); Motor_R_Cont(0,STARTER_SPEED); } } /******** 功 能:后退,左右电机反转 形 参:无 返回值: 无 说 明:这里使用到的STARTER_SPEED,为宏定义的初始占空参数,这里调用左电机驱动和右电机驱动函数, ******/ void Motor_Retreat(void) { Motor_L_Cont(0,STARTER_SPEED); Motor_R_Cont(0,STARTER_SPEED); }

5)循迹函数:

/******** 功 能:读取5个传感器输出的状态 形 参:无 返回值:state 传感器状态 说 明:传感器检测到白线输出1,黑线输出0。。 因为使用的时GPIOA端口的5到9引脚,这里直接读出GPIOA所有引脚的状态, 然后将得到的数据向右移动5位,去掉0到4引脚的数据, 再与上0x001f,得到5到9引脚的状态, ******/ u8 Get_Infrared_State(void) { u8 state = 0; state = (u8)(GPIO_ReadInputData(TRACK_PORT) >> 5) & 0x001f; return state; } /******** 功 能:循迹调整函数 形 参:无 返回值: 无 说 明:根据获取到的传感器输出状态,进行左右电机的速度调整 ******/ void Track_Adjust(void) { u8 flag = 1;//是否复位标志 u8 state = 0;//状态获取变量定义 while(flag) { state = Get_Infrared_State();//获取传感器状态 switch(state) { case 0b00000: case 0b10001: case 0b00001: case 0b10000: Motor_Speed_Adjust(0,0); break;//停止 case 0b10011: Motor_Speed_Adjust(STARTER_SPEED-100,STARTER_SPEED+100); break;//右偏1级 case 0b10111: Motor_Speed_Adjust(STARTER_SPEED-250,STARTER_SPEED+250); break;//右偏2级 case 0b00111: Motor_Speed_Adjust(STARTER_SPEED-400,STARTER_SPEED+400); break;//右偏3级 case 0b01111: Motor_Opposite(L); break;//右偏4级, case 0b11001: Motor_Speed_Adjust(STARTER_SPEED+100,STARTER_SPEED-100); break;//左偏1级 case 0b11101: Motor_Speed_Adjust(STARTER_SPEED+250,STARTER_SPEED-250); break;//左偏2级 case 0b11100: Motor_Speed_Adjust(STARTER_SPEED+400,STARTER_SPEED-400); break;//左偏3级 case 0b11110: Motor_Opposite(R); break;//左偏4级 case 0b11011: Motor_Speed_Adjust(STARTER_SPEED,STARTER_SPEED);flag = 0; break;//正常 case 0b11111: Motor_Speed_Adjust(0,0); break; default: Motor_Speed_Adjust(0,0); break; } } }

工程文件下载链接: 链接:https://pan.baidu.com/s/1SUit597TkdzdcgemiXCrsA 提取码:sdsa

(好的,到这里就完了。写的非常简单,不足的地方请各位不吝赐教)



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有