PWM驱动舵机
接线图
程序结构图:
pwm.c部分代码
cpp
#include "stm32f10x.h" // Device header
void PWM_Init(void){
// 开启时钟,这里TIM2是通用寄存器
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
// GPIO初始化代码
/*开启时钟*/
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_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA1和PA2引脚初始化为推挽输出
// 选择时基单元的时钟,选择内部时钟的模式,定时器默认使用的是内部单元的时钟
TIM_InternalClockConfig(TIM2);
// 配置时基单元,初始化结构体
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
// 将结构体成员都引用出来放置在这个位置
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 配置参数是否分屏
TIM_TimeBaseInitStructure.TIM_CounterMode =TIM_CounterMode_Up; // 选择计数的模式选择向上计数
TIM_TimeBaseInitStructure.TIM_Period = 20000 -1; // 表示ARR自动重装器的值,这两个参数的取值都要在0-65535之间
TIM_TimeBaseInitStructure.TIM_Prescaler = 72-1; // PSC预分频器的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; // 重复计数器的值
// 初始化结构体并将结构体的地址放置在init函数中
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
// 初始化输出比较单元
TIM_OCInitTypeDef TIM_OCInitStructure;
// 给结构体赋初始值
TIM_OCStructInit(&TIM_OCInitStructure);
// 设置输出比较的模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
// 设置输出比较的极性,选择高极性
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
// 设置输出使能,输出状态
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable ;
//设置CCR,设置ccr寄存器的值
TIM_OCInitStructure.TIM_Pulse = 0; // CCR
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
// 启动定时器
TIM_Cmd(TIM2, ENABLE);
}
void PWM_SetCompare2(uint16_t Compare){
TIM_SetCompare2(TIM2,Compare);
}
PWM.H文件
cpp
#ifndef __PWM_H_
#define __PWM_H_
void PWM_Init(void);
void PWM_SetCompare2(uint16_t Compare);
#endif
电机驱动文件Servo.c文件
cpp
#include "stm32f10x.h" // Device header
#include "PWM.h"
void Servo_Init(void){
// 初始化PWM底层
PWM_Init();
}
// 设置舵机的角度0 500,180 2500,输入角度/180 = x /2500 ---> 输入角度 / 180 * 2500 = x
// 求取一个线性函数,y =kx+b 已知(0,500)和(180,2500)求取k和b的值
void Servo_SetAngle(float Angle){
// 调用PWM_SetCompare2,计算参数
PWM_SetCompare2(Angle / 180 * 2000 + 500);
}
servo.h文件
cpp
#ifndef __SERVO_H_
#define __SERVO_H_
void Servo_Init(void);
void Servo_SetAngle(float Angle);
#endif
main函数文件
cpp
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Servo.h"
#include "KEY.H"
uint8_t i;
// 按键键码
uint8_t KeyNum;
float Angle;
int main(void)
{
// 初始化oled
OLED_Init();
Servo_Init();
// 初始化按键
Key_Init();
// OLED显示角度的值
OLED_ShowString(1,1,"Angle:");
while (1)
{
KeyNum = Key_GetNum();
if(KeyNum == 1){
Angle += 30;
if(Angle > 180){
Angle = 0;
}
}
Servo_SetAngle(Angle);
OLED_ShowNum(1, 7, Angle, 3);
}
}