今天我们一起来学习如何制作基于STM32F1系列的蓝牙小车
需要硬件:STM32开发板,HC-05蓝牙模块,四个电机和L298N电机驱动模块
分别介绍:
HC-05模块
大家在使用HC-05模块之前别忘了要配置AT指令,不然将无法进行串口通信
配置方法:1:配置AT指令
2:若1看不懂,可在这里查找
L298N的介绍:
**
:**
首先是主函数main:
#include "stm32f10x.h"
#include "dianji.h"
#include "delay.h"
#include
#include "sys.h"
#include
int main(void)
{
uart_init(9600);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Motor_12_Config();
delay_init();
TIM4_PWM_Init(899,0);//PWM
TIM3_PWM_Init(899,0);//PWM
while(1)
{
delay_ms(100);
}
}
电机部分:
电机头文件
#ifndef __MOTOR_H
#define __MOTOR_H
void Motor_12_Config(void);
void Motor1_FORWARD(void);
void Motor1_BACKWARD(void);
void Motor2_FORWARD(void);
void Motor2_BACKWARD(void);
#endif
电机代码:
#include
#include
void Motor_12_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5);
}
void Motor1_FORWARD()
{
GPIO_ResetBits(GPIOA,GPIO_Pin_2);
GPIO_SetBits(GPIOA,GPIO_Pin_3);
}
void Motor1_BACKWARD(void)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_3);
GPIO_SetBits(GPIOA,GPIO_Pin_2);
}
void Motor2_FORWARD()
{
GPIO_ResetBits(GPIOA,GPIO_Pin_4);
GPIO_SetBits(GPIOA,GPIO_Pin_5);
}
void Motor2_BACKWARD(void)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_5);
GPIO_SetBits(GPIOA,GPIO_Pin_4);
}
注:ResetBits 低 setBits ¸高
*PWM调速:
*
PWM头文件:
#ifndef __PWM_H
#define __PWM_H
#include "sys.h"
void TIM3_PWM_Init(u16 arr,u16 psc);
void TIM4_PWM_Init(u16 guo,u16 wen);
#endif
PWM代码:
#include "pwm.h"
#include
void TIM3_PWM_Init(u16 guo,u16 wen)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = guo;
TIM_TimeBaseStructure.TIM_Prescaler =wen;
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //ÉèÖÃʱÖÓ·Ö¸î:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_Cmd(TIM3, ENABLE);
}
void TIM4_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //TIM_CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = arr;
TIM_TimeBaseStructure.TIM_Prescaler =psc;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM4, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);
TIM_Cmd(TIM4, ENABLE);
}
串口通信:
头文件:
#ifndef __USART_H
#define __USART_H
#include "stdio.h"
#include "sys.h"
#define USART_REC_LEN
#define EN_USART1_RX
extern u8 USART_RX_BUF[USART_REC_LEN];
extern u16 USART_RX_STA;
void uart_init(u32 bound);
#endif
串口通信代码部分:
#include "stm32f10x.h"
#include "dianji.h"
#include "delay.h"
#include
#include "sys.h"
#include
#if 1
#pragma import(__use_no_semihosting)
//±ê×¼¿âÐèÒªµÄÖ§³Öº¯Êý
struct __FILE
{
int handle;
};
FILE __stdout;
//¶¨Òå_sys_exit()ÒÔ±ÜÃâʹÓðëÖ÷»úģʽ
_sys_exit(int x)
{
x = x;
}
//Öض¨Òåfputcº¯Êý
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//Ñ»··¢ËÍ,Ö±µ½·¢ËÍÍê±Ï
USART1->DR = (u8) ch;
return ch;
}
#endif
#if EN_USART1_RX //Èç¹ûʹÄÜÁ˽ÓÊÕ
//´®¿Ú1ÖжϷþÎñ³ÌÐò
//×¢Òâ,¶ÁÈ¡USARTx->SRÄܱÜÃâĪÃûÆäÃîµÄ´íÎó
u8 USART_RX_BUF[USART_REC_LEN]; //½ÓÊÕ»º³å,×î´óUSART_REC_LEN¸ö×Ö½Ú.
//½ÓÊÕ״̬
//bit15£¬ ½ÓÊÕÍê³É±êÖ¾
//bit14£¬ ½ÓÊÕµ½0x0d
//bit13~0£¬ ½ÓÊÕµ½µÄÓÐЧ×Ö½ÚÊýÄ¿
u16 USART_RX_STA=0; //½ÓÊÕ״̬±ê¼Ç
void uart_init(u32 bound){
//GPIO¶Ë¿ÚÉèÖÃ
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //ʹÄÜUSART1£¬GPIOAʱÖÓ
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //¸´ÓÃÍÆÍìÊä³ö
GPIO_Init(GPIOA, &GPIO_InitStructure);//³õʼ»¯GPIOA.9
//USART1_RX GPIOA.10³õʼ»¯
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//¸¡¿ÕÊäÈë
GPIO_Init(GPIOA, &GPIO_InitStructure);//³õʼ»¯GPIOA.10
//Usart1 NVIC ÅäÖÃ
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//ÇÀÕ¼ÓÅÏȼ¶3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //×ÓÓÅÏȼ¶3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQͨµÀʹÄÜ
NVIC_Init(&NVIC_InitStructure); //¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ÷
//USART ³õʼ»¯ÉèÖÃ
USART_InitStructure.USART_BaudRate = bound;//´®¿Ú²¨ÌØÂÊ
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//×Ö³¤Îª8λÊý¾Ý¸ñʽ
USART_InitStructure.USART_StopBits = USART_StopBits_1;//Ò»¸öֹͣλ
USART_InitStructure.USART_Parity = USART_Parity_No;//ÎÞÆæżУÑéλ
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//ÎÞÓ²¼þÊý¾ÝÁ÷¿ØÖÆ
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //ÊÕ·¢Ä£Ê½
USART_Init(USART1, &USART_InitStructure); //³õʼ»¯´®¿Ú1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//¿ªÆô´®¿Ú½ÓÊÜÖжÏ
USART_Cmd(USART1, ENABLE); //ʹÄÜ´®¿Ú1
}
u16 flag;
void USART1_IRQHandler(void) //´®¿Ú1ÖжϷþÎñ³ÌÐò
{
u8 Res;
u16 speed=0;
u8 dir=1;
Motor_12_Config();
delay_init();
TIM3_PWM_Init(899,0);
TIM4_PWM_Init(899,0);
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //½ÓÊÕÖжÏ(½ÓÊÕµ½µÄÊý¾Ý±ØÐëÊÇ0x0d 0x0a½áβ)
{
Res =USART_ReceiveData(USART1); //¶ÁÈ¡½ÓÊÕµ½µÄÊý¾Ý
if(Res==0x01) //Ç°½ø
{
Motor1_BACKWARD();
TIM_SetCompare1(TIM4,150);
Motor2_BACKWARD();
TIM_SetCompare1(TIM3,150);
}
if(Res==0x02) //ºóÍË
{
Motor1_FORWARD();
TIM_SetCompare1(TIM4,150);
Motor2_FORWARD();
TIM_SetCompare1(TIM3,150);
}
if(Res==0x03) //×óת
{
Motor1_BACKWARD();
TIM_SetCompare1(TIM4,150);
Motor2_FORWARD();
TIM_SetCompare1(TIM3,150);
}
if(Res==0x04) //ÓÒת
{
Motor1_FORWARD();
TIM_SetCompare1(TIM4,150);
Motor2_BACKWARD();
TIM_SetCompare1(TIM3,150);
}
if(Res==0x05) //Ç°½ø1
{
Motor1_BACKWARD();
TIM_SetCompare1(TIM4,500);
Motor2_BACKWARD();
TIM_SetCompare1(TIM3,500);
}
if(Res==0x06) //Ç°½ø2
{
Motor1_BACKWARD();
TIM_SetCompare1(TIM4,1);
Motor2_BACKWARD();
TIM_SetCompare1(TIM3,1);
}
if(Res==0x07) //Ç°½ø3
{
Motor1_BACKWARD();
TIM_SetCompare1(TIM4,899);
Motor2_BACKWARD();
TIM_SetCompare1(TIM3,899);
}
if(Res==0x08) //Öð²½¼ÓËÙ
{
// delay_ms(100);
// speed--;
// if(speed==0)
// {
// speed=850;
// }
for(speed=500;speed>100;speed--)
{
Motor1_BACKWARD();
TIM_SetCompare1(TIM4,speed);
Motor2_BACKWARD();
TIM_SetCompare1(TIM3,speed);
}
}
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
}
#endif
至此,整个软件部分完成;
电机连接 | STM引脚 |
---|---|
IN1 | PA2 |
IN2 | PA3 |
IN3 | PA4 |
IN4 | PA5 |
ENA | PA6 |
ENB | PB6 |
HC-05模块根据其引脚与PA10,PA9接,这里不再重复。
然后上电,连接蓝牙,连接蓝牙APP软件(推荐使用(蓝牙串口 bluespp))
打开后连接HC-05模块:
注:难以连接上蓝牙的原因:
1.外接电源电量不足,蓝牙时断时续
2.接线错误
3.AT指令配对有问题(要9600的波特率)
4.蓝牙可能坏了。。。(这个机率比较低)去这吧,小伙子
5.手机与APP还有模块不兼容(比如IOS系统)
接下来在APP上设置返回值:
设置成功后,连接蓝牙,上电。
至此,基于STM32F1系列的蓝牙小车制作完毕。