STM32 PWM

OC (Output Compare) output comparison

The output comparison can set the output level to 1, set 0 or flip it by comparing the relationship between the CNT and CCR register values, and is used to output a PWM waveform with a certain frequency and duty cycle. (CCR is the value we give, when CNT is greater than, less than/equal to CCR, flip)

Each advanced timer and general timer has 4 output compare channels

The first 3 channels of the advanced timer additionally have the functions of dead zone generation and complementary output.

Introduction to PWM

PWM (Pulse Width Modulation) pulse width modulation

In a system with inertia, the required analog parameters can be obtained equivalently by modulating the width of a series of pulses, which is often used in fields such as motor speed control.

PWM parameters:

Frequency = 1 / TS Duty cycle = TON / TS Resolution = Duty cycle change step

The resolution is a variable name based on the changing value of the duty cycle. For example, from 1%, 2, 3%, etc., it jumps in steps of 1%, and the resolution is 1%.

model

describe

freeze

When CNT=CCR , REF remains in its original state

Set effective level when matching

When CNT=CCR , REF is set to a valid level

Set invalid level when matching

When CNT=CCR , REF is set to an invalid level

Level flip on match

When CNT=CCR , the REF level flips

Forced to invalid level

CNT and CCR are invalid, REF is forced to an invalid level

forced to active level

CNT and CCR are invalid, REF is forced to a valid level

PWM mode 1

Counting up: when CNT<CCR, REF is set to a valid level; when CNT≥CCR, REF is set to an inactive level.

Counting down: when CNT>CCR, REF is set to an invalid level; when CNT≤CCR, REF is set to a valid level.

PWM mode 2

Counting up: when CNT<CCR, REF is set to an invalid level; when CNT≥CCR, REF is set to a valid level.

Counting down: when CNT>CCR, REF is set to a valid level; when CNT≤CCR, REF is set to an invalid level.

 PSC is the clock of the prescaler, CCR is the set comparison value, and ARR is the maximum overflow value of the counter.

 Introduction to steering gear

The above values ​​are substituted into the PWM formula to meet the requirements. 20K corresponds to 20ms.

There is this corresponding relationship:

20K=20ms         

         X=Required high level width Find X, X is the value of CCR

The formula for outputting the specified angle can also be derived: Angle/180*2000+500

PWM.c

#include "stm32f10x.h"                  // Device header


void PWM_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//选择TIM2定时器
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//需要复用推挽输出,因为此程序是CH1输出,是片上外设
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;//根据GPIO引脚定义,此程序用的是OC2通道,对应的是CH2,由引脚图可知选PA1
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	TIM_InternalClockConfig(TIM2);//由内部时钟驱动
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;     //预分频系数1
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式
	TIM_TimeBaseInitStructure.TIM_Prescaler=72-1;//             //PSC
    TIM_TimeBaseInitStructure.TIM_Period=20000-1;//                 //ARR
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//高级定时器的中的重复计数器的
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//时机单元初始化函数
	
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能中断
	
	TIM_Cmd(TIM2,ENABLE);
	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);//避免给一些没用到的参数赋予初始值而导致混乱
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//模式选择,此时选择PWM1模式
	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);
	
	
	
	
}

void PWM_SetCompare2(uint16_t Compare)
{
	
	TIM_SetCompare2(TIM2,Compare);//外部设计CCR的值
}

angle.c

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

void Servo_Init(void)
{
	PWM_Init();
	
}

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

PWM.h

#ifndef __PWM_H
#define __PWM_H
void PWM_Init(void);
void PWM_SetCompare2(uint16_t Compare);
#endif

angle.h

#ifndef __SERVO_H
#define __SERVO_H
void Servo_Init(void);
void Servo_SetAngle(float Angle);

#endif

main

#include "OLED.h"  
#include "Servo.h" 
#include "Key.h"
uint8_t KeyNum;
float Angle;
int main(void)
{
	OLED_Init();
	Servo_Init();
	Key_Init();
	OLED_ShowString(1,1,"Angle:");

	while(1)
	{
		KeyNum=Key_GetNum();
		if(KeyNum==1)
		{
			Angle+=15;
			if(Angle>180)
			{
				Angle=0;
			}
		}
			Servo_SetAngle(Angle);
			OLED_ShowNum(1,7,Angle,3);
	}
}

Introduction to DC motors and drives

 

 driver chip.c

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

void Motor_Init()
{
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5| GPIO_Pin_6| GPIO_Pin_7;
 	GPIO_Init(GPIOA, &GPIO_InitStructure);
	PWM_Init();
	
	
}

void Motor_SetSpeed(int8_t Speed)
{
	
	if(Speed>=0)
	{
		GPIO_ResetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_7);
		GPIO_SetBits(GPIOA,GPIO_Pin_4|GPIO_Pin_6);
		PWM_SetCompare3(Speed);
		PWM_SetCompare2(Speed);
	}
	else
		{
		GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_7);
		GPIO_ResetBits(GPIOA,GPIO_Pin_4|GPIO_Pin_6);
		PWM_SetCompare3(-Speed);
		PWM_SetCompare2(-Speed);
		}
	}

PWM.c

#include "stm32f10x.h"                  // Device header


void PWM_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//选择TIM2定时器
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_1;//
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	TIM_InternalClockConfig(TIM2);//由内部时钟驱动
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;     //预分频系数1
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式
	TIM_TimeBaseInitStructure.TIM_Prescaler=36-1;//
TIM_TimeBaseInitStructure.TIM_Period=100-1;//
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//高级定时器的中的重复计数器的
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//时机单元初始化函数
	
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能中断
	
	TIM_Cmd(TIM2,ENABLE);
	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);//避免给一些没用到的参数赋予初始值而导致混乱
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//模式选择,此时选择PWM1模式
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//极性选择,这里是高极性,不翻转,按原来的高低电平输出
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//使能输出
	TIM_OCInitStructure.TIM_Pulse=0;              //设计CCR的值
	TIM_OC3Init(TIM2,&TIM_OCInitStructure);
	TIM_OC2Init(TIM2,&TIM_OCInitStructure);
	
	
	
}

void PWM_SetCompare3(uint16_t Compare)
{
	
	TIM_SetCompare3(TIM2,Compare);//外部设计CCR的值
}
void PWM_SetCompare2(uint16_t Compare)
{
	
	TIM_SetCompare2(TIM2,Compare);//外部设计CCR的值
}

This article was studied with Jiangsu University of Science and Technology and is my study notes. If there is any infringement, please contact me to delete it!

Guess you like

Origin blog.csdn.net/m0_71827453/article/details/131872577