项目相关链接:
1.智能小车L298N驱动
2.智能小车寻迹驱动
3.智能小车蓝牙模块驱动
4.智能小车超声波测距驱动
对于一般的简单的单片机项目来说一般都是有一个工程师从头做到尾,在一切其他的工作开始之前,我们需要将自己所要使用的驱动全部完成。
正点原子为我们提供了三个系统文件,
usart.c 为我们提供一个通用的串口调试端口
sys.c 简化C语言的类型说明,提供了可以方便访问IO口的位带接口
delay.c 较为通用的延时函数
具体内容不再给出
这里采用差速控制,注意对于左右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);
}
}