#include "PWM_GeneralTim.h"
static void GENERAL_TIM_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 输出比较通道1 GPIO 初始化
RCC_APB2PeriphClockCmd(GENERAL_TIM_CH1_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH1_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStructure);
// 输出比较通道2 GPIO 初始化
RCC_APB2PeriphClockCmd(GENERAL_TIM_CH2_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH2_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GENERAL_TIM_CH2_PORT, &GPIO_InitStructure);
// 输出比较通道3 GPIO 初始化
RCC_APB2PeriphClockCmd(GENERAL_TIM_CH3_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH3_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GENERAL_TIM_CH3_PORT, &GPIO_InitStructure);
// 输出比较通道4 GPIO 初始化
RCC_APB2PeriphClockCmd(GENERAL_TIM_CH4_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH4_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GENERAL_TIM_CH4_PORT, &GPIO_InitStructure);
}
///*
// * 注意:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
// * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
// * 另外三个成员是通用定时器和高级定时器才有.
// *-----------------------------------------------------------------------------
// *typedef struct
// *{ TIM_Prescaler 都有
// * TIM_CounterMode TIMx,x[6,7]没有,其他都有
// * TIM_Period 都有
// * TIM_ClockDivision TIMx,x[6,7]没有,其他都有
// * TIM_RepetitionCounter TIMx,x[1,8,15,16,17]才有
// *}TIM_TimeBaseInitTypeDef;
// *-----------------------------------------------------------------------------
// */
/* ---------------- PWM信号 周期和占空比的计算--------------- */
// ARR :自动重装载寄存器的值
// CLK_cnt:计数器的时钟,等于 Fck_int / (psc+1) = 72M/(psc+1)
// PWM 信号的周期 T = ARR * (1/CLK_cnt) = ARR*(PSC+1) / 72M
// 占空比P=CCR/(ARR+1)
static void GENERAL_TIM_Mode_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
// 开启定时器时钟,即内部时钟CK_INT=72M
GENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK,ENABLE);
/*--------------------时基结构体初始化-------------------------*/
// 配置周期
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM_Period;
// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM_Prescaler;
// 时钟分频因子 ,配置死区时间时需要用到
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
// 计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
// 重复计数器的值,没用到不用管
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
// 初始化定时器
TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);
/*--------------------输出比较结构体初始化-------------------*/
// 配置为PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
// 输出使能
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
// 输出通道电平极性配置
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
// 输出比较通道 1
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC1Init(GENERAL_TIM, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
// 输出比较通道 2
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC2Init(GENERAL_TIM, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
// 输出比较通道 3
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC3Init(GENERAL_TIM, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
// 输出比较通道 4
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC4Init(GENERAL_TIM, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
// 使能计数器
TIM_Cmd(GENERAL_TIM, ENABLE);
}
void GENERAL_TIM_Init(void)
{
GENERAL_TIM_GPIO_Config();
GENERAL_TIM_Mode_Config();
}
//小车左转
void PWM_CarLeft(void){
TIM_SetCompare1(GENERAL_TIM,0);
TIM_SetCompare2(GENERAL_TIM,0);
TIM_SetCompare3(GENERAL_TIM,4000);
TIM_SetCompare4(GENERAL_TIM,4000);
}
//小车右转
void PWM_CarRight(void){
TIM_SetCompare1(GENERAL_TIM,4000);
TIM_SetCompare2(GENERAL_TIM,4000);
TIM_SetCompare3(GENERAL_TIM,0);
TIM_SetCompare4(GENERAL_TIM,0);
}
//小车最大速度
void PWM_CarMaxGo(void){
TIM_SetCompare1(GENERAL_TIM,0);
TIM_SetCompare2(GENERAL_TIM,0);
TIM_SetCompare3(GENERAL_TIM,0);
TIM_SetCompare4(GENERAL_TIM,0);
}
/*********************************************END OF FILE**********************/
- 小车转向的原理是跟坦克的一样,通过降低转向边的轮子速度来实现。而控制转速就要用到PWM波来减少或增多电机的通断时间(其实是驱动板的电机使能引脚)。
- 转向函数的封装
PS:完整的程序太多了,最好下载下来慢慢看。
蓝牙遥控器
做到这里就剩只蓝牙遥控器的配置了,软件呢随便哪个都行,只要能收发数据就行。
不过我推荐用我这个,因为长得好看。
此软件为安卓,ios没有
- 查看指令
单片机复位的时候会通过蓝牙发送这些数据,用手机连上蓝牙然后复位单片机就可以看到了。
printf("-----指令-----n
0x01:小车后退n
0x02:小车向左n
0x03:小车向右n
0x04:小车前进n
0x05:小车刹车n
0x06:电机停止n
0x07:小车逆时针n
0x08:小车转向停止n
0x09:小车顺时针n");
- 单片机就是通过这些十六进制的数据来控制小车的运动,只要将遥控器上的按键对应这些数据就行了。
- 按键说明
- 按键配置
按键配置简单,只要根据指令来配置就好了,我就举几个例子。
- 前进
- 左转
- 刹车
- 原地顺时针 接下来可以开车上路了。
#include "PWM_GeneralTim.h"
static void GENERAL_TIM_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 输出比较通道1 GPIO 初始化
RCC_APB2PeriphClockCmd(GENERAL_TIM_CH1_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH1_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStructure);
// 输出比较通道2 GPIO 初始化
RCC_APB2PeriphClockCmd(GENERAL_TIM_CH2_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH2_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GENERAL_TIM_CH2_PORT, &GPIO_InitStructure);
// 输出比较通道3 GPIO 初始化
RCC_APB2PeriphClockCmd(GENERAL_TIM_CH3_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH3_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GENERAL_TIM_CH3_PORT, &GPIO_InitStructure);
// 输出比较通道4 GPIO 初始化
RCC_APB2PeriphClockCmd(GENERAL_TIM_CH4_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH4_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GENERAL_TIM_CH4_PORT, &GPIO_InitStructure);
}
///*
// * 注意:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
// * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
// * 另外三个成员是通用定时器和高级定时器才有.
// *-----------------------------------------------------------------------------
// *typedef struct
// *{ TIM_Prescaler 都有
// * TIM_CounterMode TIMx,x[6,7]没有,其他都有
// * TIM_Period 都有
// * TIM_ClockDivision TIMx,x[6,7]没有,其他都有
// * TIM_RepetitionCounter TIMx,x[1,8,15,16,17]才有
// *}TIM_TimeBaseInitTypeDef;
// *-----------------------------------------------------------------------------
// */
/* ---------------- PWM信号 周期和占空比的计算--------------- */
// ARR :自动重装载寄存器的值
// CLK_cnt:计数器的时钟,等于 Fck_int / (psc+1) = 72M/(psc+1)
// PWM 信号的周期 T = ARR * (1/CLK_cnt) = ARR*(PSC+1) / 72M
// 占空比P=CCR/(ARR+1)
static void GENERAL_TIM_Mode_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
// 开启定时器时钟,即内部时钟CK_INT=72M
GENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK,ENABLE);
/*--------------------时基结构体初始化-------------------------*/
// 配置周期
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM_Period;
// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM_Prescaler;
// 时钟分频因子 ,配置死区时间时需要用到
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
// 计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
// 重复计数器的值,没用到不用管
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
// 初始化定时器
TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);
/*--------------------输出比较结构体初始化-------------------*/
// 配置为PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
// 输出使能
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
// 输出通道电平极性配置
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
// 输出比较通道 1
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC1Init(GENERAL_TIM, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
// 输出比较通道 2
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC2Init(GENERAL_TIM, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
// 输出比较通道 3
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC3Init(GENERAL_TIM, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
// 输出比较通道 4
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC4Init(GENERAL_TIM, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
// 使能计数器
TIM_Cmd(GENERAL_TIM, ENABLE);
}
void GENERAL_TIM_Init(void)
{
GENERAL_TIM_GPIO_Config();
GENERAL_TIM_Mode_Config();
}
//小车左转
void PWM_CarLeft(void){
TIM_SetCompare1(GENERAL_TIM,0);
TIM_SetCompare2(GENERAL_TIM,0);
TIM_SetCompare3(GENERAL_TIM,4000);
TIM_SetCompare4(GENERAL_TIM,4000);
}
//小车右转
void PWM_CarRight(void){
TIM_SetCompare1(GENERAL_TIM,4000);
TIM_SetCompare2(GENERAL_TIM,4000);
TIM_SetCompare3(GENERAL_TIM,0);
TIM_SetCompare4(GENERAL_TIM,0);
}
//小车最大速度
void PWM_CarMaxGo(void){
TIM_SetCompare1(GENERAL_TIM,0);
TIM_SetCompare2(GENERAL_TIM,0);
TIM_SetCompare3(GENERAL_TIM,0);
TIM_SetCompare4(GENERAL_TIM,0);
}
/*********************************************END OF FILE**********************/
- 小车转向的原理是跟坦克的一样,通过降低转向边的轮子速度来实现。而控制转速就要用到PWM波来减少或增多电机的通断时间(其实是驱动板的电机使能引脚)。
- 转向函数的封装
PS:完整的程序太多了,最好下载下来慢慢看。
蓝牙遥控器
做到这里就剩只蓝牙遥控器的配置了,软件呢随便哪个都行,只要能收发数据就行。
不过我推荐用我这个,因为长得好看。
此软件为安卓,ios没有
- 查看指令
单片机复位的时候会通过蓝牙发送这些数据,用手机连上蓝牙然后复位单片机就可以看到了。
printf("-----指令-----n
0x01:小车后退n
0x02:小车向左n
0x03:小车向右n
0x04:小车前进n
0x05:小车刹车n
0x06:电机停止n
0x07:小车逆时针n
0x08:小车转向停止n
0x09:小车顺时针n");
- 单片机就是通过这些十六进制的数据来控制小车的运动,只要将遥控器上的按键对应这些数据就行了。
- 按键说明
- 按键配置
按键配置简单,只要根据指令来配置就好了,我就举几个例子。
- 前进
- 左转
- 刹车
- 原地顺时针 接下来可以开车上路了。
举报