STM32-微项目02-通用定时器输出比较-PWM控制舵机

一,硬件需求:

1,STM32F103C8T6核心板;2,舵机模块

二、实现目标

1,按键控制舵机转动,分别是0度---30度----60度----90度-----........-180度;每次按键后自增30度,在到达180度后,再有一次按键输入后,回到0度;

三、前导知识梳理:

1,PWM知识:

①PWM是具有一定占空比的输出方波;

②什么是占空比:高电平占整个周期的时间比,Ton/Ts

③PWM波的作用:在一个波形周期内,会有高电平和低电平状态,合理控制PWM占空比,在具有惯性的系统中,可以得到不同输入电压比例;进而对外部单元进行控制

补充:在无刷三相电机的控制,就是通过在不同时期输出不同比例占空比,输出不同电压,从而实现交流电压的输出;

 2,舵机控制

舵机控制的内部原理,不太理解。我这边理解,对应这种控制模块,仅需要知道如何控制即可;

控制原理:输出周期为20ms的pwm波,控制不同的占空比,实现不同转动角的控制;

 3,通用定时器对应PWM的输出控制

①通用定时器的输出比较模块

1-输出模块控制器,可以实现CNT与CCR的比较,在CNT<CCR或者CNT>CCR输出不同的REF,具体由控制模式决定;

2-第二个框,实现对与REF的二轮控制,即REF的高低电平,可以再经过一轮控制;最终输出OC对应电平

 ②输出比较模块-pwm输出模式的控制原理

向上计数:CNT<CCR时,REF置有效电平,CNT≥CCR时,REF置无效电平

向下计数:CNT>CCR时,REF置无效电平,CNT≤CCR时,REF置有效电平

③通用定时器整体控制逻辑

1-配置时基单元,PSC,ARR

2-配置输出比较单元CCR,并选择PWM1模式

3-看情况动态调整CCR的数值,进而实现不同pwm输出

 到此,前导知识梳理完毕;

四、代码模块

1,思路梳理:

①PWM控制模块(PWM初始化模块、动态调整配置PWMCCR模块)

②舵机转向模块(舵机初始化、转向角控制模块)

③按键检测模块

④OLED显示模式

2,PWM控制模块

1-定时器2模块时钟开启、GPIO-PA1时钟开启

//配置时钟RCC
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);

2-配置定时器2的时钟源--为系统时钟72mhz

//配置时钟源为RCC -72mhz
	TIM_InternalClockConfig(TIM2);

3-配置时基单元,主要是预分频PSC、自动重装ARR的数值

计算公式:

PWM频率:    Freq = CK_PSC / (PSC + 1) / (ARR + 1)

PWM占空比:    Duty = CCR / (ARR + 1) PWM

分辨率:    Reso = 1 / (ARR + 1)

目标是形成20ms的周期pwm,设置PSC为72-1,设置ARR为20000-1;

//配置时基单元数值
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1 ;
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up ;
	TIM_TimeBaseInitStruct.TIM_Period=20000-1;  //ARR
	TIM_TimeBaseInitStruct.TIM_Prescaler=72-1;  //psc
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);

4-输出比较模块配置

①定义结构体TIM_OCInitStruct;

②由于部分数据属于高级定时器内容,不需要配置,但是不配置容易出现bug。先使用TIM_OCStructInit(&TIM_OCInitStruct)进行一次默认初始化

③输出模式PWM1

④有效模式设定:在有效状态下,输出高电平

⑤输出使能开启

⑥输出CCR的数值

⑦初始化指令

//输出比较单元配置
	TIM_OCInitTypeDef TIM_OCInitStruct;
	TIM_OCStructInit(&TIM_OCInitStruct);
	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1 ;
	
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High ;
	
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OCInitStruct.TIM_Pulse=0;//设置CCR数值

	TIM_OC2Init(TIM2, &TIM_OCInitStruct);

5-初始化GPIO-PA1

①初始化结构体GPIO_InitStruct;

②初始化为复用推挽输出GPIO_Mode_AF_PP;(其中,配置复用推挽输出的原因是的,只有在配置复用模式下,TIM才能控制GPIO的输出)

// 配置PA1端口
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init( GPIOA, &GPIO_InitStruct);

6-启动定时器

//启动定时器
	TIM_Cmd(TIM2,ENABLE);

7-动态调整CCR的数值

void pwm_setcompare(uint16_t compare)
{
	TIM_SetCompare2(TIM2, compare);
}

至此,核心的PWM模块已经完毕

3,舵机转向模块

舵机转向模块,主要是对PWM模块进行二次封装,需要关注的是:

配置angle,需要配置为float类型,不然运算时刻容易出bug(强制类型转化带来的问题)

计算公式:Angle / 180 * 2000 + 500

#include "stm32f10x.h"                  // Device header
#include "pwm.h" 

//舵机初始化


void servo_init(void)
{
	pwm_init();
}

void Servo_SetAngle(float Angle)
{
	pwm_setcompare(Angle / 180 * 2000 + 500);
}

4,在主函数中实现简单设置

#include "stm32f10x.h"                  // Device header
#include "delay.h"
#include "OLED.H"
#include "service.H"
#include "key.h"

/*
1,初始化时钟
2,定义GPIO端口,并配置输出端口,输出速度和输出方式
3,控制端口输出
*/
uint8_t keynum=0;
float angle=0.0;

int main()
{
	
	OLED_Init();
	keyinit();
	OLED_ShowString(1,1,"Angle:");
	servo_init();
	
	while(1)
	{
		keynum=key_getnum();
		if (keynum == 1)
		{
			angle += 30;
			if (angle > 180)
			{
				angle = 0;
			}
		}
		Servo_SetAngle(angle);
		OLED_ShowNum(1,7,angle,3);
		
		
	}
}

至此,已经完成代码模块配置

实验状态截屏

 四、总结

1,pwm模块配置:开启TIM2时钟、开启GIPIOA时钟----配置时钟源-----配置时基模块----配置输出比较模块---配置GPIO-PA1端口---开启时钟TIM2

2,调用TIM_SetCompare2(TIM2, compare),配置CCR,控制占空比

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值