程序只要按照上面的连接都是可以直接使用,如果硬件有改动我也有定义宏可以直接做更改。
代码里面的注释比较详细,这里只是将重要的代码放上来,稍作讲解,最好是直接下载来看。
下载地址,提取码:z5us
#include "stm32f10x.h" // Device header
#include "MTR_GPIO.h"
#include "USART.h"
#include "LED.h"
#include "blueTooth.h"
#include "PWM_GeneralTim.h"
int main(void){
USART_Config();//串口
MTR_GPIOInit();//电机引脚
GENERAL_TIM_Init();//定时器PWM初始化,用于小车转向
blueToothInit();//蓝牙初始化
LEDInit();
printf("-----指令-----\n\
0x01:小车后退\n\
0x02:小车向左\n\
0x03:小车向右\n\
0x04:小车前进\n\
0x05:小车刹车\n\
0x06:电机停止\n\
0x07:小车逆时针\n\
0x08:小车转向停止\n\
0x09:小车顺时针\n");
while(1){
//如果蓝牙断开,小车会一直在刹车状态
if(BLUE_TOOTH_STATE != Bit_SET){
MTR_CarBrakeAll();
}
}
}
void DEBUG_USART_IRQHandler(void){
uint8_t CMD = 0;//接收的命令
if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET){
LED1_ON;
CMD = USART_ReceiveData(DEBUG_USARTx);//读取一个
switch(CMD){
case 0x06:
//电机停止
MTR_CarBrakeAll();
printf("0x06");
break;
case 0x08:
//小车转向停止
PWM_CarMaxGo();
printf("0x08");
break;
case 0x05:
//小车刹车
MTR_CarBrakeAll();
printf("0x05");
break;
case 0x02:
//小车向左
PWM_CarLeft();
printf("0x02");
break;
case 0x03:
//小车向右
PWM_CarRight();
printf("0x03");
break;
case 0x04:
//小车前进
MTR_CarGo();
printf("0x04");
break;
case 0x01:
//小车后退
MTR_CarBackGo();
printf("0x01");
break;
case 0x07:
//小车逆时针
MTR_CarCCW();
printf("0x07");
break;
case 0x09:
//小车顺时针
MTR_CarCW();
printf("0x09");
break;
}
LED1_OFF;//让LED闪烁来表示数据的接收
}
USART_ClearFlag(DEBUG_USARTx,USART_FLAG_RXNE);
}
#include "MTR_GPIO.h"
//刹车
void MTR_CarBrakeAll(void){
MTR1_BRAKE;
MTR2_BRAKE;
MTR3_BRAKE;
MTR4_BRAKE;
}
//前进
void MTR_CarGo(void){
MTR1_CW;
MTR2_CW;
MTR3_CCW;
MTR4_CCW;
}
//后退
void MTR_CarBackGo(void){
MTR1_CCW;
MTR2_CCW;
MTR3_CW;
MTR4_CW;
}
//顺时针
void MTR_CarCW(void){
MTR1_CCW;
MTR2_CCW;
MTR3_CCW;
MTR4_CCW;
}
//逆时针
void MTR_CarCCW(void){
MTR1_CW;
MTR2_CW;
MTR3_CW;
MTR4_CW;
}
void MTR_GPIOInit(void){
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(MTR1_GPIO_CLK|MTR2_GPIO_CLK|MTR3_GPIO_CLK|MTR4_GPIO_CLK,ENABLE);//时钟
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
//电机1
GPIO_InitStructure.GPIO_Pin = MTR1_GPIO_PIN;
GPIO_Init(MTR1_GPIO_PORT, &GPIO_InitStructure);
//电机2
GPIO_InitStructure.GPIO_Pin = MTR2_GPIO_PIN;
GPIO_Init(MTR2_GPIO_PORT, &GPIO_InitStructure);
//电机3
GPIO_InitStructure.GPIO_Pin = MTR3_GPIO_PIN;
GPIO_Init(MTR3_GPIO_PORT, &GPIO_InitStructure);
//电机4
GPIO_InitStructure.GPIO_Pin = MTR4_GPIO_PIN;
GPIO_Init(MTR4_GPIO_PORT, &GPIO_InitStructure);
//小车刹车
MTR_CarBrakeAll();
}
注意:因为单片机是控制驱动板从而间接的控制电机,为了简单我直接把控制驱动板的引脚看成是控制电机的。
#ifndef __MTR_GPIO_H
#define __MTR_GPIO_H
#include "stm32f10x.h"
/*
小车四轮驱动
电机1:右上
电机2:右下
电机3:左上
电机4:左下
*/
#define MTR1_GPIO_PORT GPIOB
#define MTR1_GPIO_CLK RCC_APB2Periph_GPIOB
#define MTR1_GPIO_PIN GPIO_Pin_6|GPIO_Pin_7
#define MTR1_CW {GPIO_ResetBits(MTR1_GPIO_PORT,GPIO_Pin_6);GPIO_SetBits(MTR1_GPIO_PORT,GPIO_Pin_7);}//顺时针
#define MTR1_CCW {GPIO_SetBits(MTR1_GPIO_PORT,GPIO_Pin_6);GPIO_ResetBits(MTR1_GPIO_PORT,GPIO_Pin_7);}//逆时针
#define MTR1_BRAKE GPIO_ResetBits(MTR1_GPIO_PORT,MTR1_GPIO_PIN);
#define MTR2_GPIO_PORT GPIOB
#define MTR2_GPIO_CLK RCC_APB2Periph_GPIOB
#define MTR2_GPIO_PIN GPIO_Pin_8|GPIO_Pin_9
#define MTR2_CW {GPIO_ResetBits(MTR2_GPIO_PORT,GPIO_Pin_8);GPIO_SetBits(MTR2_GPIO_PORT,GPIO_Pin_9);}//顺时针
#define MTR2_CCW {GPIO_SetBits(MTR2_GPIO_PORT,GPIO_Pin_8);GPIO_ResetBits(MTR2_GPIO_PORT,GPIO_Pin_9);}//逆时针
#define MTR2_BRAKE GPIO_ResetBits(MTR2_GPIO_PORT,MTR2_GPIO_PIN);
#define MTR3_GPIO_PORT GPIOB
#define MTR3_GPIO_CLK RCC_APB2Periph_GPIOB
#define MTR3_GPIO_PIN GPIO_Pin_12|GPIO_Pin_13
#define MTR3_CW {GPIO_ResetBits(MTR3_GPIO_PORT,GPIO_Pin_12);GPIO_SetBits(MTR3_GPIO_PORT,GPIO_Pin_13);}//顺时针
#define MTR3_CCW {GPIO_SetBits(MTR3_GPIO_PORT,GPIO_Pin_12);GPIO_ResetBits(MTR3_GPIO_PORT,GPIO_Pin_13);}//逆时针
#define MTR3_BRAKE GPIO_ResetBits(MTR3_GPIO_PORT,MTR3_GPIO_PIN);
#define MTR4_GPIO_PORT GPIOB
#define MTR4_GPIO_CLK RCC_APB2Periph_GPIOB
#define MTR4_GPIO_PIN GPIO_Pin_14|GPIO_Pin_15
#define MTR4_CW {GPIO_ResetBits(MTR4_GPIO_PORT,GPIO_Pin_14);GPIO_SetBits(MTR4_GPIO_PORT,GPIO_Pin_15);}//顺时针
#define MTR4_CCW {GPIO_SetBits(MTR4_GPIO_PORT,GPIO_Pin_14);GPIO_ResetBits(MTR4_GPIO_PORT,GPIO_Pin_15);}//逆时针
#define MTR4_BRAKE GPIO_ResetBits(MTR4_GPIO_PORT,MTR4_GPIO_PIN);
void MTR_CarBrakeAll(void); //小车刹车
void MTR_CarGo(void); //小车前进
void MTR_CarBackGo(void); //小车后退
void MTR_CarCW(void); //小车顺时针转
void MTR_CarCCW(void); //小车逆时针转
void MTR_GPIOInit(void);
#endif
#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**********************/
PS:完整的程序太多了,最好下载下来慢慢看。
做到这里就剩只蓝牙遥控器的配置了,软件呢随便哪个都行,只要能收发数据就行。
不过我推荐用我这个,因为长得好看。
下载地址,提取码:kvar。此软件为安卓,ios没有
printf("-----指令-----\n
0x01:小车后退\n
0x02:小车向左\n
0x03:小车向右\n
0x04:小车前进\n
0x05:小车刹车\n
0x06:电机停止\n
0x07:小车逆时针\n
0x08:小车转向停止\n
0x09:小车顺时针\n");