在stm32f407的学习过程中,自己动手做一个智能小车,同时也是为了实验室考核的需要。同时用电位器
利用ADC控制LED灯亮度。有问题或者要代码可以问我直接在下方评论或者给我发邮件(我的邮箱2132214366@qq.com)
注意:如果要控制速度ENA,ENB必须与PWM相连。
会串口通信就可以使用蓝牙,一般从淘宝上买的蓝牙默认为从机,直接用杜邦线将蓝牙与单片机连接起来就行。也可通过AT指令调节,这里不做说明,网上很多。PWM调速的原理读者很容易就可以在网上找到,这里也不做说明。
蓝牙连接方式:VCC------+5v
GND-------GND
TXD-------Ux_RX
RXD-------Ux_TX
那两个IO口可以不用连接。 stm32与L298N连接方式(这是我自己的你们可以根据自己的情况修改): IN1----PB6 IN2----PB7 IN3----PB8 IN4----PB9 ENA----PF6 ENB-----PD13
在写代码的时候可以一部分写完再写另一部分,这样出现了错误就能及时修改。在检测PWM的时候可以先用杜邦线将选择的PWM管脚口与LED管脚口连接,通过观察灯的亮度来检测PWM是否正常。
材料清单:小车,蓝牙模块HC05,L298N(具体数量根据电机数决定 ),18650锂电池(4节1.5v的带不动电机),杜邦线,线仔线。
![在这里插入图片描述](ht
tps://img-blog.csdnimg.cn/20200309213535980.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xMWV9BXw==,size_16,color_FFFFFF,t_70)
上代码:
主函数 main.h
#include "system.h"
#include "motor.h"
#include "pwm.h"
#include "motor.h"
#include "usart3.h"
#include "led.h"
#include "SysTick.h"
#include "adc.h"
#include "time.h"
#include "beep.h"
int main()
{
u16 value;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2组
SysTick_Init(168);
LED_Init();
BEEP_Init();
TIM10_CH1_CH3_PWM_Init(500-1,84-1); //PWM调速
TIM4_CH1_CH3_PWM_Init(500-1,84-1); //PWM调速
MotorInit();//动力系统
USART3_Init(9600);//蓝牙串口连接手机
ADCx_Init();
TIM14_CH1_PWM_Init(5000-1,84-1); //频率是2Kh
TIM3_Init(5000-1,84-1); //500ms
while(1)
{
value=Get_ADC_Value(ADC_Channel_5);
TIM_SetCompare1(TIM14,value);
if(value>4000)
{
TIM_SetCompare1(TIM14,0); //adc调节LED灯亮度
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
}
}
}
motor.h
#ifndef _motor_H
#define _motor_H
#include "system.h"
void MotorInit(void);
void Stop(void);
void Turnleft(void);
void Turnright(void);
void Turnback(void);
void Turnfront(void);
#endif
motor.c
#include "motor.h"
void MotorInit(void)
{
//初始化和使能单片机上的GPIO端口,保证可以正常给端口高低电平
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB, GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9);
}
//停止模式
void Stop(void)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_6);
GPIO_ResetBits(GPIOB,GPIO_Pin_7);
GPIO_ResetBits(GPIOB,GPIO_Pin_8);
GPIO_ResetBits(GPIOB,GPIO_Pin_9);
}
//左转模式 -> 左电机反转,右电机正转
void Turnleft(void)
{
GPIO_SetBits(GPIOB,GPIO_Pin_6);
GPIO_ResetBits(GPIOB,GPIO_Pin_7);
GPIO_ResetBits(GPIOB,GPIO_Pin_8);
GPIO_SetBits(GPIOB,GPIO_Pin_9);
}
//右转模式 -> 左电机正转,右电机反转
void Turnright(void)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_6);
GPIO_SetBits(GPIOB,GPIO_Pin_7);
GPIO_SetBits(GPIOB,GPIO_Pin_8);
GPIO_ResetBits(GPIOB,GPIO_Pin_9);
}
//后退模式 -> 左电机反转,右电机反转
void Turnback(void)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_6);
GPIO_SetBits(GPIOB,GPIO_Pin_7);
GPIO_ResetBits(GPIOB,GPIO_Pin_8);
GPIO_SetBits(GPIOB,GPIO_Pin_9);
}
//前进模式 -> 左电机正转,右电机正转
void Turnfront(void)
{
GPIO_SetBits(GPIOB,GPIO_Pin_6);
GPIO_ResetBits(GPIOB,GPIO_Pin_7);
GPIO_SetBits(GPIOB,GPIO_Pin_8);
GPIO_ResetBits(GPIOB,GPIO_Pin_9);
}
pwm.h
#ifndef _pwm_H
#define _pwm_H
#include "system.h"
void TIM10_CH1_CH3_PWM_Init(u16 per,u16 psc);
void TIM4_CH1_CH3_PWM_Init(u16 per,u16 psc);
void TIM14_CH1_PWM_Init(u16 per,u16 psc);
void Speed_1_Control(void);
void Speed_2_Control(void);
void Speed_3_Control(void);
void Speed_0_Control(void);
#endif
pwm.c
#include "pwm.h"
#include "SysTick.h"
#include "motor.h"
void TIM10_CH1_CH3_PWM_Init(u16 per,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10,ENABLE);//使能TIM4时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);
GPIO_PinAFConfig(GPIOF,GPIO_PinSource6,GPIO_AF_TIM10);//管脚复用
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //复用输出模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;//管脚设置
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度为100M
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化结构体
TIM_TimeBaseInitStructure.TIM_Period=per; //自动装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式
TIM_TimeBaseInit(TIM10,&TIM_TimeBaseInitStructure);
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OC1Init(TIM10,&TIM_OCInitStructure); //输出比较通道1初始化
TIM_OC1PreloadConfig(TIM10,TIM_OCPreload_Enable); //使能TIMx在 CCR1 上的预装载寄存器
TIM_ARRPreloadConfig(TIM10,ENABLE);//使能预装载寄存器
TIM_Cmd(TIM10,ENABLE); //使能定时器
}
void TIM4_CH1_CH3_PWM_Init(u16 per,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//使能TIM4时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource13,GPIO_AF_TIM4);//管脚复用
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //复用输出模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;//管脚设置
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度为100M
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOD,&GPIO_InitStructure); //初始化结构体
TIM_TimeBaseInitStructure.TIM_Period=per; //自动装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OC2Init(TIM4,&TIM_OCInitStructure); //输出比较通道1初始化
TIM_OC2PreloadConfig(TIM4,TIM_OCPreload_Enable); //使能TIMx在 CCR1 上的预装载寄存器
TIM_ARRPreloadConfig(TIM4,ENABLE);//使能预装载寄存器
TIM_Cmd(TIM4,ENABLE); //使能定时器
}
void TIM14_CH1_PWM_Init(u16 per,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE);//使能TIM14时钟
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);//管脚复用
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //复用输出模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//管脚设置
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度为100M
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化结构体
TIM_TimeBaseInitStructure.TIM_Period=per; //自动装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式
TIM_TimeBaseInit(TIM14,&TIM_TimeBaseInitStructure);
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OC1Init(TIM14,&TIM_OCInitStructure); //输出比较通道1初始化
TIM_OC1PreloadConfig(TIM14,TIM_OCPreload_Enable); //使能TIMx在 CCR1 上的预装载寄存器
TIM_ARRPreloadConfig(TIM14,ENABLE);//使能预装载寄存器
TIM_Cmd(TIM14,ENABLE); //使能定时器
}
void Speed_1_Control(void) //高速
{
Turnfront();
TIM_SetCompare1(TIM10,1);
TIM_SetCompare2(TIM4,1);
}
void Speed_2_Control(void) //中速
{
Turnfront();
TIM_SetCompare1(TIM10,150);
TIM_SetCompare2(TIM4,150);
}
void Speed_3_Control(void) //低速
{
Turnfront();
TIM_SetCompare1(TIM10,300);
TIM_SetCompare2(TIM4,300);
}
void Speed_0_Control(void) //一键加速
{
u16 a=350;
for(a=350;a>0;a--)
{
Turnfront();
TIM_SetCompare1(TIM10,a);
TIM_SetCompare2(TIM4,a);
delay_ms(5);
}
}
usart3.h
#ifndef _usart3_H
#define _usart3_H
#include "system.h"
void USART3_Init(u32 bound);
#endif
usart3.c
#include "usart3.h"
#include "led.h"
#include "beep.h"
#include "motor.h"
#include "SysTick.h"
#include "pwm.h"
void USART3_Init(u32 bound)
{
GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); //使能GPIOA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//使能USART3时钟
GPIO_PinAFConfig(GPIOB,GPIO_PinSource11,GPIO_AF_USART3);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_USART3);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11|GPIO_Pin_10;//管脚设置F9
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//速度为100M
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOB,&GPIO_InitStructure); //初始化结构体
USART_InitStructure.USART_BaudRate=bound;
USART_InitStructure.USART_WordLength=USART_WordLength_8b;
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(USART3,&USART_InitStructure);
USART_Cmd(USART3,ENABLE);
USART_ClearFlag(USART3,USART_FLAG_TC);
USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel=USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void USART3_IRQHandler (void)
{
u8 r;//r为手机串口APP发送给蓝牙模块的信息
if(USART_GetITStatus(USART3,USART_IT_RXNE)!=RESET)
{
USART_ClearITPendingBit(USART3, USART_IT_RXNE); //清除 USART1 的中断待处理位
r=USART_ReceiveData(USART3);
if(r=='1')
{
Speed_0_Control();
led2=0;
}
if(r=='2')
{
Turnfront();
TIM_SetCompare1(TIM10,1);
TIM_SetCompare2(TIM4,1);
led2=1;
}
if(r=='3')
{
Speed_1_Control();
}
if(r=='4')
{
Turnleft();
TIM_SetCompare1(TIM10,1);
TIM_SetCompare2(TIM4,1);
led2=1;
}
if(r=='5')
{
beep=0;
}
if(r=='6')
{
Turnright();
TIM_SetCompare1(TIM10,1);
TIM_SetCompare2(TIM4,1);
led2=1;
}
if(r=='7')
{
Speed_2_Control();
}
if(r=='8')
{
Turnback();
TIM_SetCompare1(TIM10,1);
TIM_SetCompare2(TIM4,1);
led2=1;
}
if(r=='9')
{
Speed_3_Control();
}
if(r=='0')
{
beep=1;
}
if(r=='a')
{
Stop();
beep=0;
delay_ms(100);
beep=1;
}
}
USART_ClearFlag(USART3,USART_FLAG_TC);
}
time.h
#ifndef _time_H
#define _time_H
#include "system.h"
void TIM3_Init(u32 per,u16 psc);
#endif
time.c
#include "time.h"
#include "led.h"
#include "SysTick.h"
void TIM3_Init(u32 per,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能TIM4时钟
TIM_TimeBaseInitStructure.TIM_Period=per; //自动装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
TIM_ITConfig(TIM3,TIM_IT_Update,DISABLE); //开启定时器中断
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;//定时器中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM3,ENABLE); //使能定时器
}
/*******************************************************************************
* 函 数 名 : TIM4_IRQHandler
* 函数功能 : TIM4中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void TIM3_IRQHandler(void)
{
int i=0;
if(TIM_GetITStatus(TIM3,TIM_IT_Update))
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,DISABLE);//失能TIM3时钟
for(i=0;i<3;i++)
{
TIM_SetCompare1(TIM14,0);
delay_ms(1000);
TIM_SetCompare1(TIM14,4000);
delay_ms(1000);
}
TIM_SetCompare1(TIM14,0);
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
led.h
#ifndef _led_H
#define _led_H
#include "system.h"
#define led1 PFout(9)
#define led2 PFout(10)
void LED_Init(void);
#endif
led.c
#include "led.h"
/*******************************************************************************
* 函 数 名 : LED_Init
* 函数功能 : LED初始化函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void LED_Init()
{
GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE); //使能端口F时钟
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT; //输出模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_10;//管脚设置F9
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度为100M
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化结构体
GPIO_SetBits(GPIOF,GPIO_Pin_9|GPIO_Pin_10);
}
beep.h
#ifndef _beep_H
#define _beep_H
#include "system.h"
#define BEEP_Pin (GPIO_Pin_8) //定义BEEP管脚
#define BEEP_Port (GPIOF) //定义BEEP端口
#define beep PFout(8) //BEEP PF8
void BEEP_Init(void);
#endif
beep.c
#include "beep.h"
/*******************************************************************************
* 函 数 名 : BEEP_Init
* 函数功能 : 蜂鸣器初始化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void BEEP_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE); //使能端口F时钟
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT; //输出模式
GPIO_InitStructure.GPIO_Pin=BEEP_Pin;//管脚设置F8
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度为100M
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
GPIO_Init(BEEP_Port,&GPIO_InitStructure); //初始化结构体
GPIO_SetBits(BEEP_Port,BEEP_Pin); //关闭蜂鸣器
}