【单片机开发】智能小车工程 (驱动L298N)

项目相关链接:
1.智能小车L298N驱动
2.智能小车寻迹驱动
3.智能小车蓝牙模块驱动
4.智能小车超声波测距驱动

(一)背景介绍

对于一般的简单的单片机项目来说一般都是有一个工程师从头做到尾,在一切其他的工作开始之前,我们需要将自己所要使用的驱动全部完成。

(二)软件实现

正点原子为我们提供了三个系统文件,
usart.c 为我们提供一个通用的串口调试端口
sys.c 简化C语言的类型说明,提供了可以方便访问IO口的位带接口
delay.c 较为通用的延时函数
具体内容不再给出

1)电机驱动部分

这里采用差速控制,注意对于左右PWM的相对差速需要更根据实际情况进行调节

motor.h

#ifndef __MOTOR1_H
#define __MOTOR1_H
 
 
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"        // 包涵库文件
 
#define High    1                  //相关宏定义
#define Low     0
 
#define IN1(a) if (a)  \            
	GPIO_SetBits(GPIOA,GPIO_Pin_1);\
else  \
	GPIO_ResetBits(GPIOA,GPIO_Pin_1)
 
#define IN2(a) if (a)  \
	GPIO_SetBits(GPIOA,GPIO_Pin_2);\
else  \
	GPIO_ResetBits(GPIOA,GPIO_Pin_2)
 
#define IN3(a) if (a)  \
	GPIO_SetBits(GPIOB,GPIO_Pin_11);\
else  \
	GPIO_ResetBits(GPIOB,GPIO_Pin_11)
 
#define IN4(a) if (a)  \
	GPIO_SetBits(GPIOB,GPIO_Pin_12);\
else  \
	GPIO_ResetBits(GPIOB,GPIO_Pin_12)
 
void Motor_12_Config(void);
 
void Motor_1_STOP(void);
void Motor_1_PRun(void);
void Motor_1_NRun(void);
 
void Motor_2_STOP(void);
void Motor_2_PRun(void);
void Motor_2_NRun(void);
void Motor_right(void);
void Motor_left(void);
#endif

motor.c

#include "motor.h"  //导入led头文件
#include "stm32f10x.h"  //导入STM32官方库
#include "stm32f10x_rcc.h"  //导入STM32的RCC时钟库
#include "PWM.h"  //导入PWM
 
//motor1 右轮 对应PA1  PA2
//motor2 左轮 对应 PA11  PA12
//该文件用于马达的驱动信号 控制相关运动状态
 
void Motor_12_Config(void)  //定义初始化函数
{
	GPIO_InitTypeDef GPIO_InitStructure;   //定义GPIO_InitTypeDef结构体
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);  //开启引脚时钟
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);  //开启引脚
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //通用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  //设置输出功率
	GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化GPIOA的引脚参数,写进
	GPIO_ResetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_2); //所有引脚拉低	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //通用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  //设置输出功率
	GPIO_Init(GPIOB, &GPIO_InitStructure);  //初始化GPIOB的引脚参数,写进
	GPIO_ResetBits(GPIOA,GPIO_Pin_11|GPIO_Pin_12); //所有引脚拉低
}
 
//1是右轮,2是左轮

//下面为运动状态函数

void Motor_1_STOP(void)
{
	TIM_SetCompare1(TIM4,899);  //此为占空比的设置默认的系统函数 初始完PWM即可使用
	                          //在这里899为满空占比,即无动力
	                          //占空比越高速度越慢
}
 
void Motor_1_PRun(void)
{
	TIM_SetCompare1(TIM4,350);//这里的数值是在多次调试后可以使转速大概相同的数值小车速度合适约两米每秒
}
 
void Motor_1_NRun(void)
{
	IN1(High);
	IN2(Low);
}
 
void Motor_2_STOP(void)
{
TIM_SetCompare2(TIM4,899);
}
 
void Motor_2_PRun(void)
{
	TIM_SetCompare2(TIM4,370);
}
 
void Motor_2_NRun(void)
{
	IN3(High);
	IN4(Low);
}

void Motor_right(void)
{
	TIM_SetCompare1(TIM4,899);
	TIM_SetCompare2(TIM4,399);
}

void Motor_left(void)
{
	TIM_SetCompare1(TIM4,370);
	TIM_SetCompare2(TIM4,899);
}

PWM.h

//进行一些关于PWM的初始化
#ifndef __PWM__H
#define __PWM__H
#include "sys.h"



void TIM4_PWM_Init(u16 arr,u16 psc);
void TIM3_Int_Init(u16 arr,u16 psc);
void TIM3_PWM_Init(u16 arr,u16 psc);

#endif




pwm.c
//PWM输出 用于对轮子速度的控制
//使用定时器4 通道12 对应PB6 PB7
#include "PWM.h"
#include "sys.h"  
void TIM4_PWM_Init(u16 arr,u16 psc)
{   
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
        TIM_OCInitTypeDef TIM_OCInitStructure;
        GPIO_InitTypeDef    GPIO_InitStrucyure;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);  //使能定时器4时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); // 使能GPIO
 
 
        GPIO_InitStrucyure.GPIO_Mode=GPIO_Mode_AF_PP;        //改为复用推挽输出GPIO_Mode_AF_PP
        GPIO_InitStrucyure.GPIO_Pin=GPIO_Pin_7;
        GPIO_InitStrucyure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOB,&GPIO_InitStrucyure);                 //初始化io口
	
	      GPIO_InitStrucyure.GPIO_Mode=GPIO_Mode_AF_PP;        //改为复用推挽输出GPIO_Mode_AF_PP
        GPIO_InitStrucyure.GPIO_Pin=GPIO_Pin_6;
        GPIO_InitStrucyure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOB,&GPIO_InitStrucyure);    
	
	
 
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC1Init(TIM4, &TIM_OCInitStructure);        //通道一对应右轮信号输入
 
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC2Init(TIM4, &TIM_OCInitStructure);          //通道2对应左轮信号输入
	
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC3Init(TIM4, &TIM_OCInitStructure);  
	


  TIM_OC1PreloadConfig(TIM4,TIM_OCPreload_Enable);
  TIM_OC2PreloadConfig(TIM4,TIM_OCPreload_Enable);
			
	TIM_Cmd(TIM4,ENABLE);  //使能定时器

    }



好的在做完这些配置后即可驱动小车做一些最简单的运动

main.c

#include "sys.h"
#include "delay.h"
#include "motor.h"
#include "PWM.h"
//#include "remote.h"  //寻迹模块
#include "usart.h"


int main(void)
{  
	
	
	TIM4_PWM_Init(899,0);//以72000000此每秒计数 计数至900
	delay_init();	    	 //延时函数初始化	 
	Motor_12_Config(); //298电机驱动初始化
 // remote_Init();
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	
	//uart_init(9600);
   
	  IN1(Low);
	  IN2(High);
	  IN3(Low);
	  IN4(High);//保持控制正反转电平恒定默认直行
While(1)
      	//转弯程序测试,直行后右转
{				
       delay_ms(1000);
	   delay_ms(1000);
	   Motor_right();
	   delay_ms(500);
	  
	  Motor_1_PRun(); //正转
	  Motor_2_PRun();
	  delay_ms(1000);
	
		Motor_left();
		delay_ms(500);
	    Motor_2_PRun();
	    delay_ms(1000);
	    Motor_left();
		delay_ms(500);
		Motor_1_STOP();  //停止
		Motor_2_STOP();
		delay_ms(1000);
		delay_ms(1000);
		delay_ms(1000);
		delay_ms(1000);
	}
}
©️2020 CSDN 皮肤主题: 书香水墨 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值