重要声明 看过我前面51小车博客的都知道我是软件工程专业的,对于硬件方面都是因为感兴趣自学的,这不,因为今年寒假放假比较早,趁这个时间学习了STM32相关知识,经过近一个月的学习对于STM32算是入门了,为了检验自己的学习效果,我决定就着51小车的架子用STM32试试,经过一个下午的忙活算是成功了!!!所以再来和大家分享一下。
所需知识贮备 相信看到这篇文章的小伙伴都是有相关基础的,这里只是给和我一样自学的小伙伴提个醒。动手之前你需要这些:
- 硬件电路连接相关能力
- C语言基础能力
- STM32定时器、中断、串口等基础知识
- 查阅相关元件开发手册的能力
- 一定的动手能力
部分原始材料图片
文章图片
程序设计思路
- STM32利用L298N电机驱动模块控制前后两路直流电机
#include "motor.h"//导入led头文件
#include "stm32f10x.h"//导入STM32官方库
#include "stm32f10x_rcc.h"//导入STM32的RCC时钟库
#include "delay.h"//延时库
void Motor_12_Config(void)//定义初始化函数
{
GPIO_InitTypeDef GPIO_InitStructure;
//定义GPIO_InitTypeDef结构体
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOF, ENABLE);
//开启引脚时GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
//定义IN引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
//通用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//设置输出功率
GPIO_Init(GPIOF, &GPIO_InitStructure);
//初始化GPIOF的引脚参数,写进
GPIO_ResetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);
//所有引脚拉低
}
void Motor_1_STOP(void)
{
IN1(High);
IN2(High);
}
void Motor_1_PRun(void)
{
IN1(Low);
IN2(High);
}
void Motor_1_NRun(void)
{
IN1(High);
IN2(Low);
}
void Motor_2_STOP(void)
{
IN3(High);
IN4(High);
}
void Motor_2_PRun(void)
{
IN3(Low);
IN4(High);
}
void Motor_2_NRun(void)
{
IN3(High);
IN4(Low);
}
motor.h
#ifndef __MOTOR1_H
#define __MOTOR1_H
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#define High1
#define Low0
#define IN1(a) if (a)\
GPIO_SetBits(GPIOF,GPIO_Pin_0);
\
else\
GPIO_ResetBits(GPIOF,GPIO_Pin_0)
#define IN2(a) if (a)\
GPIO_SetBits(GPIOF,GPIO_Pin_1);
\
else\
GPIO_ResetBits(GPIOF,GPIO_Pin_1)
#define IN3(a) if (a)\
GPIO_SetBits(GPIOF,GPIO_Pin_2);
\
else\
GPIO_ResetBits(GPIOF,GPIO_Pin_2)
#define IN4(a) if (a)\
GPIO_SetBits(GPIOF,GPIO_Pin_3);
\
else\
GPIO_ResetBits(GPIOF,GPIO_Pin_3)
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);
#endif
- PWM波控制舵机角度用于转向
#include "PWM.h"
#include "stm32f10x.h"
/* 函 数 名: pwm_init
函数功能: IO端口及TIM3初始化函数*/void PWM_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//声明一个结构体变量,用来初始化GPIO TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
//声明一个结构体变量,用来初始化定时器 TIM_OCInitTypeDef TIM_OCInitStructure;
//根据TIM_OCInitStruct中指定的参数初始化外设TIMx /* 开启时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
/*配置GPIO的模式和IO口 */
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
// PC6
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
//复用推挽输出
GPIO_Init(GPIOC,&GPIO_InitStructure);
//TIM3定时器初始化
TIM_TimeBaseInitStructure.TIM_Period = 199;
//PWM 频率=72000/(199+1)=36Khz//设置自动重装载寄存器周期的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 7199;
//设置用来作为TIMx时钟频率预分频值
TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;
//设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
//TIM向上计数模式
TIM_TimeBaseInit(TIM3, & TIM_TimeBaseInitStructure);
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);
//改变指定管脚的映射 //pC6
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
//PWM输出使能
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
TIM_OC1Init(TIM3,&TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
//使能或者失能TIMx在CCR1上的预装载寄存器
TIM_Cmd(TIM3,ENABLE);
}
- HC_06蓝牙模块用于通信(我用的是USART1串口)
(这部分代码参照原子视频代码即可!)
因为文章只是分享一个大概,具体的控制外设CSDN上也有很多可以参考的文章,大家有需要可以自行搜索查看,有问题也可以私信我)
文章图片
主程序代码
#include "stm32f10x.h"//官方库
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "sys.h"
#include "delay.h"
#include "motor.h"
#include "PWM.h"
#include "led.h"
#include "usart.h"
#include "beep.h" int main()
{
u16 RxData;
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//设置NVIC中断分组2:2位抢占优先级,2位响应优先级 uart_init(115200);
//串口初始化为115200
Motor_12_Config();
//电机的初使化
PWM_Init();
//舵机初始化
BEEP_Init();
//初始化蜂鸣器端口
delay_init();
//延时函数初始化
LED_Init();
//初始化LED端口while(1)
{if(USART_GetFlagStatus( USART1, USART_FLAG_RXNE))
{
USART_ClearFlag(USART1, USART_FLAG_RXNE);
RxData=https://www.it610.com/article/USART_ReceiveData( USART1);
}
if(RxData == 0x01){//前进
//GPIO_ResetBits(GPIOE,GPIO_Pin_5);
//LED1对应引脚GPIOE.5拉低,亮 等同LED1=0;
//GPIO_ResetBits(GPIOB,GPIO_Pin_5);
//LED0对应引脚GPIOB.5拉低,亮等同LED0=0
//GPIO_SetBits(GPIOB,GPIO_Pin_8);
Motor_1_PRun();
Motor_2_PRun();
}
if(RxData == 0x02){//后退
Motor_1_NRun();
Motor_2_NRun();
}
if(RxData == 0x03){//左转
TIM_SetCompare1(TIM3,190);
}
if(RxData == 0x04){//回中
TIM_SetCompare1(TIM3,185);
}
if(RxData == 0x05){
TIM_SetCompare1(TIM3,180);
//右转
}
if(RxData == 0x06){
GPIO_SetBits(GPIOB,GPIO_Pin_8);
}
if(RxData == 0x07){
GPIO_ResetBits(GPIOB,GPIO_Pin_8);
}
if(RxData == 0x00){
//GPIO_SetBits(GPIOB,GPIO_Pin_5);
//LED0对应引脚GPIOB.5拉高
//GPIO_SetBits(GPIOE,GPIO_Pin_5);
//LED1对应引脚GPIOE.5拉高
//GPIO_ResetBits(GPIOB,GPIO_Pin_8);
Motor_1_STOP();
Motor_2_STOP();
}
}
}
成品展示 请忽略这草率的走线和供电,因为我只是对自己所学的一个检验,并没有像51小车那样把走线完善好,至于为什么没有放在地上跑,这看着也很明显啊,走线不允许啊!!!而且这里我用的精英开发板,如果是要做项目还是推荐mini板啊。
文章图片
手机遥控界面 ((((安卓的SPP蓝牙串口)))))
个人认为这款蓝牙助手用于开发界面简洁高效,推荐一波!(我可没收广告费)
文章图片
总结 这次相对于上一次的51小车来说轻松了不少,一来是因为51给我奠定了一定的基础,对于硬件的理解更近了一步,二来是这次的时间更加充裕,我能够把STM32的基础知识都过一遍,文章写的比较简略,很多原理都没有细说!有需要的可以评论留言!
需要源码的评论区留言!
有做的不好的地方欢迎大家指出!
【硬件|硬件篇(教你做STM32蓝牙小车(基于STM32F103ZET6))】最近获取源码的小伙伴比较多,所以将源码放在了Gitee上,有需要的自取哦~
Gitee地址:点击这里跳转源码仓库!!!!!
别忘了关注哦~~
文章图片
推荐阅读
- 单片机设计|毕业设计 - 题目(基于stm32的智能扫地机器人设计与实现)
- 知识总结|Java基础知识总结(超级详细-面试必备)
- python|新书推荐 |《精通ROS机器人编程(原书第2版)》
- SCI|小学生发SCI论文,中学生发新英格兰,这不是后浪,这是海啸啊
- 面试|四面美团开发岗,成功斩获offer,这份面经总结终结篇看完就是血赚!
- 中间件|Apache Member、ALC Beijing 发起人姜宁(一个人走的很快,但是一群人能走得更远)
- 区块链|活动回顾丨ALC Beijing 首场 Meetup(《开源到底有多难(》))
- 人工智能|那些离开大厂,回归学术界的科学家们!
- 数据库|【分布式系列01期】常见的分布式ID生成方案浅析及大厂方案调研