# 学习目标:通过pwm使用一个按键来简单驱动一个舵机(跟着b站江科大老师学习)
# 学习内容:学习简单的一些pwm相关语句的作用及其用法,并在屏幕上显示舵机运动角度与按键次数
#代码实现过程:
1.初始化函数
void PWM_Init(void)
2.开始时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //开启TIM2的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
3.GPIO初始化
//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);
4.配置时钟源和时基单元
//配置时钟源
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的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;//预分频器,即PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
5.输出比较初始化
//输出比较初始化
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; //初始的CCR值
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
6.TIM使能
TIM_Cmd(TIM2, ENABLE); //使能TIM2,定时器开始运行
7.设置CCR1的值
void PWM_SetCompare2(uint16_t Compare)
{
TIM_SetCompare2(TIM2, Compare); //设置CCR1的值
}
8.在创建一个servo文件,在里面加上舵机旋转的相关代码(根据舵机的占空比)。
#include "stm32f10x.h" // Device header
#include"PWM.h"
void Servo_init(void)
{
PWM_Init();
}
//0 500
//180 2500
void Servo_SetAngle(float Angle)
{
PWM_SetCompare2(Angle / 180 * 2000 + 500);
}
9.在主函数里包含相关头文件,并调用上述函数。(OLED,KEY相关代码在b站江科大老师视频文件中可以找到)。
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Servo.h"
#include"KEY.h"
uint8_t KeyNum;//定义相关变量
float Angle;
uint8_t NUM;
int main(void)
{
OLED_Init();//初始化
Key_Init();
Servo_init();
OLED_ShowString(1,1,"angle=");//屏幕显示相关数据
OLED_ShowString(3,1,"NUM=");
while (1)
{
KeyNum = Key_GetNum();
if(KeyNum==1)//按下按键
{
Angle+=30;//角度加30
NUM++;//计数加一
if(Angle>180)
{
Angle=0;
}
}
Servo_SetAngle(Angle);
OLED_ShowNum(2,1,Angle,3);
OLED_ShowNum(3,5,NUM,3);
}
}
10.实验结果图
每按一下舵机旋转30度计数次数加一,若超过180度将会转成0度。