STM32入门(5)
STM32入门(5)

TB6612控制逻辑
TB6612的电机方向由IN1、IN2的电平组合决定:
- 正转:IN1=1,IN2=0(代码中正转时PA4=1, PA5=0)
- 反转:IN1=0,IN2=1(代码中反转时PA4=0, PA5=1)
- 停止/刹车:IN1=IN2(相同电平,本函数未使用)
PWM信号(占空比)控制电机转速,占空比越大转速越快。
项目一:PWM驱动直流电机
// 项目:PWM驱动直流电机
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Motor.h"
#include "Key.h"
uint8_t KeyNum; //定义用于接收按键键码的变量
int8_t Speed; //定义速度变量
int main(void)
{
/*模块初始化*/
OLED_Init(); //OLED初始化
Motor_Init(); //直流电机初始化
Key_Init(); //按键初始化
/*显示静态字符串*/
OLED_ShowString(1, 1, "Speed:"); //1行1列显示字符串Speed:
while (1)
{
KeyNum = Key_GetNum(); //获取按键键码
if (KeyNum == 1) //按键1按下
{
Speed += 20; //速度变量自增20
if (Speed > 100) //速度变量超过100后
{
Speed = -100; //速度变量变为-100
//此操作会让电机旋转方向突然改变,可能会因供电不足而导致单片机复位
//若出现了此现象,则应避免使用这样的操作
}
}
Motor_SetSpeed(Speed); //设置直流电机的速度为速度变量
OLED_ShowSignedNum(1, 7, Speed, 3); //OLED显示速度变量
}
}
#include "stm32f10x.h" // Device header
/**
* 函 数:PWM初始化
* 参 数:无
* 返 回 值:无
*/
void PWM_Init(void)
{
// 开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); // 开启TIM2的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); // 开启GPIOA的时钟
// GPIO初始化
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure); // 将PA2引脚初始化为复用推挽引脚
// 受外设控制的引脚,均需要配置为复用模式
// 配置时钟源
TIM_InternalClockConfig(TIM2); // 选择TIM2为内部时钟,若不调用此函数,TIM默认也为内部时钟
// 时间单元初始化
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; // 定义结构体变量
// 时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; // 计数器模式,选择向上计数模式
TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; // 计数周期,即ARR的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 36 - 1; // 预分频器,即PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; // 重复计数器,高级定时器才会用到
// 将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
// 输出比较初始化
TIM_OCInitTypeDef TIM_OCinitStructure; // 定义结构体变量
TIM_OCStructInit(&TIM_OCinitStructure); // 结构体初始化,若结构体没有完整赋值
// 则最好执行此函数,给结构体所有成员都赋一个默认值
// 避免结构体初值不确定的问题
TIM_OCinitStructure.TIM_OCMode = TIM_OCMode_PWM1; // 输出比较模式,选择PWM模式1
// 输出极性,选择为高,若选择极性为低,则输出高低电平取反
TIM_OCinitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCinitStructure.TIM_OutputState = TIM_OutputState_Enable; // 输出使能
TIM_OCinitStructure.TIM_Pulse = 0; // 初始的CRR的值
// 将结构体变量交给TIM_OC3Init,配置TIM2的输出比较通道3
TIM_OC3Init(TIM2,&TIM_OCinitStructure);
// TIM使能
TIM_Cmd(TIM2,ENABLE); // 使能TIM2,定时器开始运行
}
/**
* 函 数:PWM设置CCR
* 参 数:Compare 要写入的CCR的值,范围:0~100
* 返 回 值:无
* 注意事项:CCR和ARR共同决定占空比,此函数仅设置CCR的值,并不直接是占空比
* 占空比Duty = CCR / (ARR + 1)
*/
void PWM_SetCompare3(uint16_t Compare)
{
TIM_SetCompare3(TIM2, Compare); //设置CCR3的值
}
#ifndef __PWM_H
#define __PWM_H
void PWM_Init(void);
void PWM_SetCompare3(uint16_t Compare);
#endif
#include "stm32f10x.h" // Device header
#include "PWM.h"
/**
* 函 数:直流电机初始化
* 参 数:无
* 返 回 值:无
*/
void Motor_Init(void)
{
// 开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); // 开启GPIOA的时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure); // 将PA4和PA5引脚初始化为推挽输出
PWM_Init(); // 初始化直流电机的底层PWM
}
/**
* 函 数:直流电机设置速度
* 参 数:Speed 要设置的速度,范围:-100 ~100
* 返 回 值:无
*/
void Motor_SetSpeed(int8_t Speed)
{
if(Speed >= 0) // 如果设置为正转的速度值
{
GPIO_SetBits(GPIOA,GPIO_Pin_4); // PA4置高电平
GPIO_ResetBits(GPIOA,GPIO_Pin_5); // PA5置低电平,设置方向为正转
PWM_SetCompare3(Speed); // PWM设置为速度值
}
else // 否则,即设置反转的速度值
{
GPIO_ResetBits(GPIOA, GPIO_Pin_4); // PA4置低电平
GPIO_SetBits(GPIOA, GPIO_Pin_5); // PA5置高电平,设置方向为反转
PWM_SetCompare3(-Speed); // PWM设置为负的速度值,因为此时速度值为负数,而PWM只能给正数
}
}
#ifndef __MOTOR_H
#define __MOTOR_H
void Motor_Init(void);
void Motor_SetSpeed(int8_t Speed);
#endif
#include "stm32f10x.h" // Device header
#include "Delay.h"
/**
* 函 数:按键初始化
* 参 数:无
* 返 回 值:无
*/
void Key_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); // 开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 设置为上拉模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
/**
* 函 数:按键获取键码
* 参 数:无
* 返 回 值:按下按键的键码值,范围:0~2,返回0代表没有按键按下
* 注意事项:此函数是阻塞式操作,当按键按住不放时,函数会卡住,直到按键松手
*/
uint8_t Key_GetNum(void)
{
uint8_t KeyNum = 0; // 定义变量,默认键码值为0
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == RESET)
{
Delay_ms(20);
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == RESET);
Delay_ms(20);
KeyNum = 1;
}
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == RESET)
{
Delay_ms(20);
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == RESET);
Delay_ms(20);
KeyNum = 2;
}
return KeyNum;
}
#ifndef __KEY_H_
#define __KEY_H_
void Key_Init(void);
uint8_t Key_GetNum(void);
#endif

浙公网安备 33010602011771号